summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/llmessage
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (diff)
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts: # autobuild.xml # indra/cmake/CMakeLists.txt # indra/cmake/GoogleMock.cmake # indra/llaudio/llaudioengine_fmodstudio.cpp # indra/llaudio/llaudioengine_fmodstudio.h # indra/llaudio/lllistener_fmodstudio.cpp # indra/llaudio/lllistener_fmodstudio.h # indra/llaudio/llstreamingaudio_fmodstudio.cpp # indra/llaudio/llstreamingaudio_fmodstudio.h # indra/llcharacter/llmultigesture.cpp # indra/llcharacter/llmultigesture.h # indra/llimage/llimage.cpp # indra/llimage/llimagepng.cpp # indra/llimage/llimageworker.cpp # indra/llimage/tests/llimageworker_test.cpp # indra/llmessage/tests/llmockhttpclient.h # indra/llprimitive/llgltfmaterial.h # indra/llrender/llfontfreetype.cpp # indra/llui/llcombobox.cpp # indra/llui/llfolderview.cpp # indra/llui/llfolderviewmodel.h # indra/llui/lllineeditor.cpp # indra/llui/lllineeditor.h # indra/llui/lltextbase.cpp # indra/llui/lltextbase.h # indra/llui/lltexteditor.cpp # indra/llui/lltextvalidate.cpp # indra/llui/lltextvalidate.h # indra/llui/lluictrl.h # indra/llui/llview.cpp # indra/llwindow/llwindowmacosx.cpp # indra/newview/app_settings/settings.xml # indra/newview/llappearancemgr.cpp # indra/newview/llappearancemgr.h # indra/newview/llavatarpropertiesprocessor.cpp # indra/newview/llavatarpropertiesprocessor.h # indra/newview/llbreadcrumbview.cpp # indra/newview/llbreadcrumbview.h # indra/newview/llbreastmotion.cpp # indra/newview/llbreastmotion.h # indra/newview/llconversationmodel.h # indra/newview/lldensityctrl.cpp # indra/newview/lldensityctrl.h # indra/newview/llface.inl # indra/newview/llfloatereditsky.cpp # indra/newview/llfloatereditwater.cpp # indra/newview/llfloateremojipicker.h # indra/newview/llfloaterimsessiontab.cpp # indra/newview/llfloaterprofiletexture.cpp # indra/newview/llfloaterprofiletexture.h # indra/newview/llgesturemgr.cpp # indra/newview/llgesturemgr.h # indra/newview/llimpanel.cpp # indra/newview/llimpanel.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryclipboard.cpp # indra/newview/llinventoryclipboard.h # indra/newview/llinventoryfunctions.cpp # indra/newview/llinventoryfunctions.h # indra/newview/llinventorygallery.cpp # indra/newview/lllistbrowser.cpp # indra/newview/lllistbrowser.h # indra/newview/llpanelobjectinventory.cpp # indra/newview/llpanelprofile.cpp # indra/newview/llpanelprofile.h # indra/newview/llpreviewgesture.cpp # indra/newview/llsavedsettingsglue.cpp # indra/newview/llsavedsettingsglue.h # indra/newview/lltooldraganddrop.cpp # indra/newview/llurllineeditorctrl.cpp # indra/newview/llvectorperfoptions.cpp # indra/newview/llvectorperfoptions.h # indra/newview/llviewerparceloverlay.cpp # indra/newview/llviewertexlayer.cpp # indra/newview/llviewertexturelist.cpp # indra/newview/macmain.h # indra/test/test.cpp
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/llassetstorage.h862
-rw-r--r--indra/llmessage/llavatarname.cpp324
-rw-r--r--indra/llmessage/llavatarname.h206
-rw-r--r--indra/llmessage/llavatarnamecache.cpp770
-rw-r--r--indra/llmessage/llavatarnamecache.h136
-rw-r--r--indra/llmessage/llblowfishcipher.cpp128
-rw-r--r--indra/llmessage/llblowfishcipher.h114
-rw-r--r--indra/llmessage/llbuffer.cpp1352
-rw-r--r--indra/llmessage/llbuffer.h1032
-rw-r--r--indra/llmessage/llbufferstream.cpp504
-rw-r--r--indra/llmessage/llbufferstream.h164
-rw-r--r--indra/llmessage/llcachename.cpp2042
-rw-r--r--indra/llmessage/llcachename.h296
-rw-r--r--indra/llmessage/llchainio.cpp64
-rw-r--r--indra/llmessage/llchainio.h108
-rw-r--r--indra/llmessage/llcipher.h112
-rw-r--r--indra/llmessage/llcircuit.cpp2838
-rw-r--r--indra/llmessage/llcircuit.h700
-rw-r--r--indra/llmessage/llclassifiedflags.cpp168
-rw-r--r--indra/llmessage/llclassifiedflags.h124
-rw-r--r--indra/llmessage/llcoproceduremanager.cpp20
-rw-r--r--indra/llmessage/llcoproceduremanager.h12
-rw-r--r--indra/llmessage/llcorehttputil.h206
-rw-r--r--indra/llmessage/lldatapacker.cpp4360
-rw-r--r--indra/llmessage/lldatapacker.h870
-rw-r--r--indra/llmessage/lldbstrings.h248
-rw-r--r--indra/llmessage/lldispatcher.cpp92
-rw-r--r--indra/llmessage/lldispatcher.h96
-rw-r--r--indra/llmessage/lleventflags.h10
-rw-r--r--indra/llmessage/llexperiencecache.cpp388
-rw-r--r--indra/llmessage/llexperiencecache.h84
-rw-r--r--indra/llmessage/llextendedstatus.h64
-rw-r--r--indra/llmessage/llfiltersd2xmlrpc.cpp1074
-rw-r--r--indra/llmessage/llfiltersd2xmlrpc.h186
-rw-r--r--indra/llmessage/llfollowcamparams.h58
-rw-r--r--indra/llmessage/llgenericstreamingmessage.cpp8
-rw-r--r--indra/llmessage/llgenericstreamingmessage.h8
-rw-r--r--indra/llmessage/llhost.cpp352
-rw-r--r--indra/llmessage/llhost.h308
-rw-r--r--indra/llmessage/llhttpnode.cpp490
-rw-r--r--indra/llmessage/llhttpnode.h550
-rw-r--r--indra/llmessage/llhttpnodeadapter.h34
-rw-r--r--indra/llmessage/llhttpsdhandler.cpp50
-rw-r--r--indra/llmessage/llhttpsdhandler.h20
-rw-r--r--indra/llmessage/llinstantmessage.cpp328
-rw-r--r--indra/llmessage/llinstantmessage.h436
-rw-r--r--indra/llmessage/llinvite.h14
-rw-r--r--indra/llmessage/lliobuffer.cpp98
-rw-r--r--indra/llmessage/lliobuffer.h156
-rw-r--r--indra/llmessage/lliohttpserver.cpp1520
-rw-r--r--indra/llmessage/lliohttpserver.h102
-rw-r--r--indra/llmessage/lliopipe.cpp98
-rw-r--r--indra/llmessage/lliopipe.h360
-rw-r--r--indra/llmessage/lliosocket.cpp1034
-rw-r--r--indra/llmessage/lliosocket.h488
-rw-r--r--indra/llmessage/llioutil.cpp78
-rw-r--r--indra/llmessage/llioutil.h146
-rw-r--r--indra/llmessage/llloginflags.h20
-rw-r--r--indra/llmessage/llmail.cpp792
-rw-r--r--indra/llmessage/llmail.h260
-rw-r--r--indra/llmessage/llmessagebuilder.cpp12
-rw-r--r--indra/llmessage/llmessagebuilder.h202
-rw-r--r--indra/llmessage/llmessageconfig.cpp250
-rw-r--r--indra/llmessage/llmessageconfig.h40
-rw-r--r--indra/llmessage/llmessagereader.cpp124
-rw-r--r--indra/llmessage/llmessagereader.h188
-rw-r--r--indra/llmessage/llmessagesenderinterface.h16
-rw-r--r--indra/llmessage/llmessagetemplate.cpp270
-rw-r--r--indra/llmessage/llmessagetemplate.h842
-rw-r--r--indra/llmessage/llmessagetemplateparser.cpp1522
-rw-r--r--indra/llmessage/llmessagetemplateparser.h72
-rw-r--r--indra/llmessage/llmessagethrottle.cpp306
-rw-r--r--indra/llmessage/llmessagethrottle.h160
-rw-r--r--indra/llmessage/llmsgvariabletype.h60
-rw-r--r--indra/llmessage/llnamevalue.cpp1940
-rw-r--r--indra/llmessage/llnamevalue.h366
-rw-r--r--indra/llmessage/llnullcipher.cpp36
-rw-r--r--indra/llmessage/llnullcipher.h20
-rw-r--r--indra/llmessage/llpacketack.cpp164
-rw-r--r--indra/llmessage/llpacketack.h232
-rw-r--r--indra/llmessage/llpacketbuffer.cpp48
-rw-r--r--indra/llmessage/llpacketbuffer.h36
-rw-r--r--indra/llmessage/llpacketring.cpp742
-rw-r--r--indra/llmessage/llpacketring.h202
-rw-r--r--indra/llmessage/llpartdata.cpp838
-rw-r--r--indra/llmessage/llpartdata.h558
-rw-r--r--indra/llmessage/llproxy.cpp588
-rw-r--r--indra/llmessage/llproxy.h256
-rw-r--r--indra/llmessage/llpumpio.cpp2300
-rw-r--r--indra/llmessage/llpumpio.h722
-rw-r--r--indra/llmessage/llqueryflags.h114
-rw-r--r--indra/llmessage/llregionflags.h422
-rw-r--r--indra/llmessage/llregionhandle.h252
-rw-r--r--indra/llmessage/llsdappservices.cpp382
-rw-r--r--indra/llmessage/llsdappservices.h42
-rw-r--r--indra/llmessage/llsdhttpserver.cpp168
-rw-r--r--indra/llmessage/llsdhttpserver.h32
-rw-r--r--indra/llmessage/llsdmessagebuilder.cpp848
-rw-r--r--indra/llmessage/llsdmessagebuilder.h252
-rw-r--r--indra/llmessage/llsdmessagereader.cpp688
-rw-r--r--indra/llmessage/llsdmessagereader.h216
-rw-r--r--indra/llmessage/llservice.cpp118
-rw-r--r--indra/llmessage/llservice.h178
-rw-r--r--indra/llmessage/llservicebuilder.cpp358
-rw-r--r--indra/llmessage/llservicebuilder.h84
-rw-r--r--indra/llmessage/llstoredmessage.cpp12
-rw-r--r--indra/llmessage/llstoredmessage.h20
-rw-r--r--indra/llmessage/lltaskname.h50
-rw-r--r--indra/llmessage/llteleportflags.h68
-rw-r--r--indra/llmessage/lltemplatemessagebuilder.cpp1786
-rw-r--r--indra/llmessage/lltemplatemessagebuilder.h230
-rw-r--r--indra/llmessage/lltemplatemessagedispatcher.cpp48
-rw-r--r--indra/llmessage/lltemplatemessagedispatcher.h18
-rw-r--r--indra/llmessage/lltemplatemessagereader.cpp1660
-rw-r--r--indra/llmessage/lltemplatemessagereader.h254
-rw-r--r--indra/llmessage/llthrottle.cpp1154
-rw-r--r--indra/llmessage/llthrottle.h202
-rw-r--r--indra/llmessage/lltransfermanager.cpp2802
-rw-r--r--indra/llmessage/lltransfermanager.h998
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp508
-rw-r--r--indra/llmessage/lltransfersourceasset.h162
-rw-r--r--indra/llmessage/lltransfersourcefile.cpp348
-rw-r--r--indra/llmessage/lltransfersourcefile.h150
-rw-r--r--indra/llmessage/lltransfertargetfile.cpp156
-rw-r--r--indra/llmessage/lltransfertargetfile.h56
-rw-r--r--indra/llmessage/lltransfertargetvfile.cpp468
-rw-r--r--indra/llmessage/lltransfertargetvfile.h186
-rw-r--r--indra/llmessage/lltrustedmessageservice.cpp90
-rw-r--r--indra/llmessage/lltrustedmessageservice.h20
-rw-r--r--indra/llmessage/lluseroperation.cpp380
-rw-r--r--indra/llmessage/lluseroperation.h194
-rw-r--r--indra/llmessage/llvehicleparams.h150
-rw-r--r--indra/llmessage/llxfer.cpp776
-rw-r--r--indra/llmessage/llxfer.h246
-rw-r--r--indra/llmessage/llxfer_file.cpp950
-rw-r--r--indra/llmessage/llxfer_file.h174
-rw-r--r--indra/llmessage/llxfer_mem.cpp392
-rw-r--r--indra/llmessage/llxfer_mem.h154
-rw-r--r--indra/llmessage/llxfer_vfile.cpp794
-rw-r--r--indra/llmessage/llxfer_vfile.h182
-rw-r--r--indra/llmessage/llxfermanager.cpp2652
-rw-r--r--indra/llmessage/llxfermanager.h446
-rw-r--r--indra/llmessage/llxorcipher.cpp256
-rw-r--r--indra/llmessage/llxorcipher.h134
-rw-r--r--indra/llmessage/machine.cpp50
-rw-r--r--indra/llmessage/machine.h190
-rw-r--r--indra/llmessage/mean_collision_data.h106
-rw-r--r--indra/llmessage/message.cpp8110
-rw-r--r--indra/llmessage/message.h2342
-rw-r--r--indra/llmessage/message_prehash.cpp10
-rw-r--r--indra/llmessage/message_prehash.h8
-rw-r--r--indra/llmessage/message_string_table.cpp182
-rw-r--r--indra/llmessage/net.cpp1326
-rw-r--r--indra/llmessage/net.h148
-rw-r--r--indra/llmessage/partsyspacket.cpp2594
-rw-r--r--indra/llmessage/partsyspacket.h522
-rw-r--r--indra/llmessage/patch_code.cpp816
-rw-r--r--indra/llmessage/patch_code.h30
-rw-r--r--indra/llmessage/patch_dct.cpp1538
-rw-r--r--indra/llmessage/patch_dct.h42
-rw-r--r--indra/llmessage/patch_idct.cpp1368
-rw-r--r--indra/llmessage/sound_ids.cpp80
-rw-r--r--indra/llmessage/sound_ids.h24
-rw-r--r--indra/llmessage/tests/commtest.h12
-rw-r--r--indra/llmessage/tests/llareslistener_test.cpp52
-rw-r--r--indra/llmessage/tests/llavatarnamecache_test.cpp142
-rw-r--r--indra/llmessage/tests/llcoproceduremanager_test.cpp12
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp46
-rw-r--r--indra/llmessage/tests/llhost_test.cpp478
-rw-r--r--indra/llmessage/tests/llhttpclient_test.cpp532
-rw-r--r--indra/llmessage/tests/llhttpnode_stub.cpp24
-rw-r--r--indra/llmessage/tests/llnamevalue_test.cpp734
-rw-r--r--indra/llmessage/tests/llpartdata_test.cpp220
-rw-r--r--indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp320
-rw-r--r--indra/llmessage/tests/lltestmessagesender.cpp20
-rw-r--r--indra/llmessage/tests/lltestmessagesender.h22
-rw-r--r--indra/llmessage/tests/lltrustedmessageservice_test.cpp132
-rw-r--r--indra/llmessage/tests/llxfer_file_test.cpp116
-rw-r--r--indra/llmessage/tests/networkio.h12
179 files changed, 43257 insertions, 43257 deletions
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index dd63724039..6b6d4a3ae7 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -1,431 +1,431 @@
-/**
- * @file llassetstorage.h
- * @brief definition of LLAssetStorage class which allows simple
- * up/downloads of uuid,type asets
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSETSTORAGE_H
-#define LL_LLASSETSTORAGE_H
-#include <string>
-#include <functional>
-
-#include "lluuid.h"
-#include "lltimer.h"
-#include "llnamevalue.h"
-#include "llhost.h"
-#include "lltransfermanager.h" // For LLTSCode enum
-#include "llassettype.h"
-#include "llstring.h"
-#include "llextendedstatus.h"
-#include "llxfer.h"
-
-// Forward declarations
-class LLMessageSystem;
-class LLXferManager;
-class LLAssetStorage;
-class LLSD;
-
-// anything that takes longer than this to download will abort.
-// HTTP Uploads also timeout if they take longer than this.
-const F32Minutes LL_ASSET_STORAGE_TIMEOUT(5);
-
-
-// Specific error codes
-const int LL_ERR_ASSET_REQUEST_FAILED = -1;
-//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
-const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
-const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
-const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
-const int LL_ERR_PRICE_MISMATCH = -23018;
-
-// *TODO: these typedefs are passed into the cache via a legacy C function pointer
-// future project would be to convert these to C++ callables (std::function<>) so that
-// we can use bind and remove the userData parameter.
-//
-typedef std::function<void(const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
-typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
-
-
-class LLAssetInfo
-{
-protected:
- std::string mDescription;
- std::string mName;
-
-public:
- LLUUID mUuid;
- LLTransactionID mTransactionID;
- LLUUID mCreatorID;
- LLAssetType::EType mType;
-
- LLAssetInfo( void );
- LLAssetInfo( const LLUUID& object_id, const LLUUID& creator_id,
- LLAssetType::EType type, const char* name, const char* desc );
- LLAssetInfo( const LLNameValue& nv );
-
- const std::string& getName( void ) const { return mName; }
- const std::string& getDescription( void ) const { return mDescription; }
- void setName( const std::string& name );
- void setDescription( const std::string& desc );
-
- // Assets (aka potential inventory items) can be applied to an
- // object in the world. We'll store that as a string name value
- // pair where the name encodes part of asset info, and the value
- // the rest. LLAssetInfo objects will be responsible for parsing
- // the meaning out froman LLNameValue object. See the inventory
- // design docs for details.
- void setFromNameValue( const LLNameValue& nv );
-};
-
-
-class LLBaseDownloadRequest
-{
-public:
- LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType at);
- virtual ~LLBaseDownloadRequest();
-
- LLUUID getUUID() const { return mUUID; }
- LLAssetType::EType getType() const { return mType; }
-
- void setUUID(const LLUUID& id) { mUUID = id; }
- void setType(LLAssetType::EType type) { mType = type; }
-
- virtual LLBaseDownloadRequest* getCopy();
-
-protected:
- LLUUID mUUID;
- LLAssetType::EType mType;
-
-public:
- LLGetAssetCallback mDownCallback;
-
- void *mUserData;
- LLHost mHost;
- bool mIsTemp;
- F64Seconds mTime; // Message system time
- bool mIsPriority;
- bool mDataSentInFirstPacket;
- bool mDataIsInCache;
-};
-
-class LLAssetRequest : public LLBaseDownloadRequest
-{
-public:
- LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType at);
- virtual ~LLAssetRequest();
-
- void setTimeout(F64Seconds timeout) { mTimeout = timeout; }
-
- virtual LLBaseDownloadRequest* getCopy();
-
- LLStoreAssetCallback mUpCallback;
-// void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
- void (*mInfoCallback)(LLAssetInfo *, void *, S32);
-
- bool mIsLocal;
- bool mIsUserWaiting; // We don't want to try forever if a user is waiting for a result.
- F64Seconds mTimeout; // Amount of time before timing out.
- LLUUID mRequestingAgentID; // Only valid for uploads from an agent
- F64 mBytesFetched;
-
- virtual LLSD getTerseDetails() const;
- virtual LLSD getFullDetails() const;
-};
-
-template <class T>
-struct ll_asset_request_equal : public std::equal_to<T>
-{
- bool operator()(const T& x, const T& y) const
- {
- return ( x->getType() == y->getType()
- && x->getUUID() == y->getUUID() );
- }
-};
-
-
-class LLInvItemRequest : public LLBaseDownloadRequest
-{
-public:
- LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType at);
- virtual ~LLInvItemRequest();
-
- virtual LLBaseDownloadRequest* getCopy();
-};
-
-class LLEstateAssetRequest : public LLBaseDownloadRequest
-{
-public:
- LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType at, EstateAssetType et);
- virtual ~LLEstateAssetRequest();
-
- LLAssetType::EType getAType() const { return mType; }
-
- virtual LLBaseDownloadRequest* getCopy();
-
-protected:
- EstateAssetType mEstateAssetType;
-};
-
-
-// Map of known bad assets
-typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
-
-
-
-class LLAssetStorage
-{
-public:
- typedef ::LLStoreAssetCallback LLStoreAssetCallback;
- typedef ::LLGetAssetCallback LLGetAssetCallback;
-
- enum ERequestType
- {
- RT_INVALID = -1,
- RT_DOWNLOAD = 0,
- RT_UPLOAD = 1,
- RT_LOCALUPLOAD = 2,
- RT_COUNT = 3
- };
-
-protected:
- bool mShutDown;
- LLHost mUpstreamHost;
-
- LLMessageSystem *mMessageSys;
- LLXferManager *mXferManager;
-
-
- typedef std::list<LLAssetRequest*> request_list_t;
- request_list_t mPendingDownloads;
- request_list_t mPendingUploads;
- request_list_t mPendingLocalUploads;
-
- // Map of toxic assets - these caused problems when recently rezzed, so avoid them
- toxic_asset_map_t mToxicAssetMap; // Objects in this list are known to cause problems and are not loaded
-
-public:
- LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, const LLHost &upstream_host);
-
- LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer);
- virtual ~LLAssetStorage();
-
- void setUpstream(const LLHost &upstream_host);
-
- bool hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type);
-
- // public interface methods
- // note that your callback may get called BEFORE the function returns
- void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, bool is_priority = false);
-
- /*
- * TransactionID version
- * Viewer needs the store_local
- */
- virtual void storeAssetData(
- const LLTransactionID& tid,
- LLAssetType::EType atype,
- LLStoreAssetCallback callback,
- void* user_data,
- bool temp_file = false,
- bool is_priority = false,
- bool store_local = false,
- bool user_waiting= false,
- F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) = 0;
-
- virtual void logAssetStorageInfo() = 0;
-
- virtual void checkForTimeouts();
-
- void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
- const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
- LLGetAssetCallback callback, void *user_data, bool is_priority);
-
- void getInvItemAsset(const LLHost &object_sim,
- const LLUUID &agent_id, const LLUUID &session_id,
- const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
- const LLUUID &asset_id, LLAssetType::EType atype,
- LLGetAssetCallback cb, void *user_data, bool is_priority = false); // Get a particular inventory item.
-
- // Check if an asset is in the toxic map. If it is, the entry is updated
- bool isAssetToxic( const LLUUID& uuid );
-
- // Clean the toxic asset list, remove old entries
- void flushOldToxicAssets( bool force_it );
-
- // Add an item to the toxic asset map
- void markAssetToxic( const LLUUID& uuid );
-
-protected:
- bool findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
- LLGetAssetCallback callback, void *user_data);
-
- LLSD getPendingDetailsImpl(const request_list_t* requests,
- LLAssetType::EType asset_type,
- const std::string& detail_prefix) const;
-
- LLSD getPendingRequestImpl(const request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id) const;
-
- bool deletePendingRequestImpl(request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id);
-
-public:
- static const LLAssetRequest* findRequest(const request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id);
- static LLAssetRequest* findRequest(request_list_t* requests,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id);
-
- request_list_t* getRequestList(ERequestType rt);
- const request_list_t* getRequestList(ERequestType rt) const;
- static std::string getRequestName(ERequestType rt);
-
- S32 getNumPendingDownloads() const;
- S32 getNumPendingUploads() const;
- S32 getNumPendingLocalUploads();
- S32 getNumPending(ERequestType rt) const;
-
- LLSD getPendingDetails(ERequestType rt,
- LLAssetType::EType asset_type,
- const std::string& detail_prefix) const;
-
- LLSD getPendingRequest(ERequestType rt,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id) const;
-
- bool deletePendingRequest(ERequestType rt,
- LLAssetType::EType asset_type,
- const LLUUID& asset_id);
-
-
- static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
- const LLUUID& callback_id, LLAssetType::EType callback_type,
- S32 result_code, LLExtStat ext_status);
-
- // download process callbacks
- static void downloadCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data, LLExtStat ext_status);
- static void downloadEstateAssetCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data, LLExtStat ext_status);
- static void downloadInvItemCompleteCallback(
- S32 result,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data, LLExtStat ext_status);
-
- // upload process callbacks
- static void uploadCompleteCallback(const LLUUID&, void *user_data, S32 result, LLExtStat ext_status);
- static void processUploadComplete(LLMessageSystem *msg, void **this_handle);
-
- // debugging
- static const char* getErrorString( S32 status );
-
- // deprecated file-based methods
- // Not overriden
- void getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, bool is_priority = false);
-
- /*
- * TransactionID version
- */
- virtual void storeAssetData(
- const std::string& filename,
- const LLTransactionID &transaction_id,
- LLAssetType::EType type,
- LLStoreAssetCallback callback,
- void *user_data,
- bool temp_file = false,
- bool is_priority = false,
- bool user_waiting = false,
- F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0;
-
- static void legacyGetDataCallback(const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status);
- static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status);
-
- // add extra methods to handle metadata
-
-protected:
- void _cleanupRequests(bool all, S32 error);
- void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, bool success, LLExtStat ext_status);
-
- virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
- void *user_data, bool duplicate,
- bool is_priority) = 0;
-
-private:
- void _init(LLMessageSystem *msg,
- LLXferManager *xfer,
- const LLHost &upstream_host);
-
-protected:
- enum EMetricResult
- {
- // Static valued enums for #dw readability - please copy this
- // declaration to them on updates -- source in llassetstorage.h
- MR_INVALID = -1, // Makes no sense
- MR_OKAY = 0, // Success - no metric normally
- MR_ZERO_SIZE = 1, // Zero size asset
- MR_BAD_FUNCTION = 2, // Tried to use a virtual base (PROGRAMMER ERROR)
- MR_FILE_NONEXIST = 3, // Old format store call - source file does not exist
- MR_NO_FILENAME = 4, // Old format store call - source filename is NULL/0-length
- MR_NO_UPSTREAM = 5, // Upstream provider is missing
- MR_CACHE_CORRUPTION = 6 // cache is corrupt - too-large or mismatched stated/returned sizes
- };
-
- static class LLMetrics *metric_recipient;
-
- static void reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const std::string& filename,
- const LLUUID& agent_id, S32 asset_size, EMetricResult result,
- const char* file, const S32 line, const std::string& message );
-public:
- static void setMetricRecipient( LLMetrics *recip )
- {
- metric_recipient = recip;
- }
-};
-
-////////////////////////////////////////////////////////////////////////
-// Wrappers to replicate deprecated API
-////////////////////////////////////////////////////////////////////////
-
-class LLLegacyAssetRequest
-{
-public:
- void (*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat);
- LLStoreAssetCallback mUpCallback;
-
- void *mUserData;
-};
-
-extern LLAssetStorage *gAssetStorage;
-extern const LLUUID CATEGORIZE_LOST_AND_FOUND_ID;
-#endif
+/**
+ * @file llassetstorage.h
+ * @brief definition of LLAssetStorage class which allows simple
+ * up/downloads of uuid,type asets
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLASSETSTORAGE_H
+#define LL_LLASSETSTORAGE_H
+#include <string>
+#include <functional>
+
+#include "lluuid.h"
+#include "lltimer.h"
+#include "llnamevalue.h"
+#include "llhost.h"
+#include "lltransfermanager.h" // For LLTSCode enum
+#include "llassettype.h"
+#include "llstring.h"
+#include "llextendedstatus.h"
+#include "llxfer.h"
+
+// Forward declarations
+class LLMessageSystem;
+class LLXferManager;
+class LLAssetStorage;
+class LLSD;
+
+// anything that takes longer than this to download will abort.
+// HTTP Uploads also timeout if they take longer than this.
+const F32Minutes LL_ASSET_STORAGE_TIMEOUT(5);
+
+
+// Specific error codes
+const int LL_ERR_ASSET_REQUEST_FAILED = -1;
+//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
+const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
+const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
+const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
+const int LL_ERR_PRICE_MISMATCH = -23018;
+
+// *TODO: these typedefs are passed into the cache via a legacy C function pointer
+// future project would be to convert these to C++ callables (std::function<>) so that
+// we can use bind and remove the userData parameter.
+//
+typedef std::function<void(const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
+typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
+
+
+class LLAssetInfo
+{
+protected:
+ std::string mDescription;
+ std::string mName;
+
+public:
+ LLUUID mUuid;
+ LLTransactionID mTransactionID;
+ LLUUID mCreatorID;
+ LLAssetType::EType mType;
+
+ LLAssetInfo( void );
+ LLAssetInfo( const LLUUID& object_id, const LLUUID& creator_id,
+ LLAssetType::EType type, const char* name, const char* desc );
+ LLAssetInfo( const LLNameValue& nv );
+
+ const std::string& getName( void ) const { return mName; }
+ const std::string& getDescription( void ) const { return mDescription; }
+ void setName( const std::string& name );
+ void setDescription( const std::string& desc );
+
+ // Assets (aka potential inventory items) can be applied to an
+ // object in the world. We'll store that as a string name value
+ // pair where the name encodes part of asset info, and the value
+ // the rest. LLAssetInfo objects will be responsible for parsing
+ // the meaning out froman LLNameValue object. See the inventory
+ // design docs for details.
+ void setFromNameValue( const LLNameValue& nv );
+};
+
+
+class LLBaseDownloadRequest
+{
+public:
+ LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType at);
+ virtual ~LLBaseDownloadRequest();
+
+ LLUUID getUUID() const { return mUUID; }
+ LLAssetType::EType getType() const { return mType; }
+
+ void setUUID(const LLUUID& id) { mUUID = id; }
+ void setType(LLAssetType::EType type) { mType = type; }
+
+ virtual LLBaseDownloadRequest* getCopy();
+
+protected:
+ LLUUID mUUID;
+ LLAssetType::EType mType;
+
+public:
+ LLGetAssetCallback mDownCallback;
+
+ void *mUserData;
+ LLHost mHost;
+ bool mIsTemp;
+ F64Seconds mTime; // Message system time
+ bool mIsPriority;
+ bool mDataSentInFirstPacket;
+ bool mDataIsInCache;
+};
+
+class LLAssetRequest : public LLBaseDownloadRequest
+{
+public:
+ LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType at);
+ virtual ~LLAssetRequest();
+
+ void setTimeout(F64Seconds timeout) { mTimeout = timeout; }
+
+ virtual LLBaseDownloadRequest* getCopy();
+
+ LLStoreAssetCallback mUpCallback;
+// void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
+ void (*mInfoCallback)(LLAssetInfo *, void *, S32);
+
+ bool mIsLocal;
+ bool mIsUserWaiting; // We don't want to try forever if a user is waiting for a result.
+ F64Seconds mTimeout; // Amount of time before timing out.
+ LLUUID mRequestingAgentID; // Only valid for uploads from an agent
+ F64 mBytesFetched;
+
+ virtual LLSD getTerseDetails() const;
+ virtual LLSD getFullDetails() const;
+};
+
+template <class T>
+struct ll_asset_request_equal : public std::equal_to<T>
+{
+ bool operator()(const T& x, const T& y) const
+ {
+ return ( x->getType() == y->getType()
+ && x->getUUID() == y->getUUID() );
+ }
+};
+
+
+class LLInvItemRequest : public LLBaseDownloadRequest
+{
+public:
+ LLInvItemRequest(const LLUUID &uuid, const LLAssetType::EType at);
+ virtual ~LLInvItemRequest();
+
+ virtual LLBaseDownloadRequest* getCopy();
+};
+
+class LLEstateAssetRequest : public LLBaseDownloadRequest
+{
+public:
+ LLEstateAssetRequest(const LLUUID &uuid, const LLAssetType::EType at, EstateAssetType et);
+ virtual ~LLEstateAssetRequest();
+
+ LLAssetType::EType getAType() const { return mType; }
+
+ virtual LLBaseDownloadRequest* getCopy();
+
+protected:
+ EstateAssetType mEstateAssetType;
+};
+
+
+// Map of known bad assets
+typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
+
+
+
+class LLAssetStorage
+{
+public:
+ typedef ::LLStoreAssetCallback LLStoreAssetCallback;
+ typedef ::LLGetAssetCallback LLGetAssetCallback;
+
+ enum ERequestType
+ {
+ RT_INVALID = -1,
+ RT_DOWNLOAD = 0,
+ RT_UPLOAD = 1,
+ RT_LOCALUPLOAD = 2,
+ RT_COUNT = 3
+ };
+
+protected:
+ bool mShutDown;
+ LLHost mUpstreamHost;
+
+ LLMessageSystem *mMessageSys;
+ LLXferManager *mXferManager;
+
+
+ typedef std::list<LLAssetRequest*> request_list_t;
+ request_list_t mPendingDownloads;
+ request_list_t mPendingUploads;
+ request_list_t mPendingLocalUploads;
+
+ // Map of toxic assets - these caused problems when recently rezzed, so avoid them
+ toxic_asset_map_t mToxicAssetMap; // Objects in this list are known to cause problems and are not loaded
+
+public:
+ LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, const LLHost &upstream_host);
+
+ LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer);
+ virtual ~LLAssetStorage();
+
+ void setUpstream(const LLHost &upstream_host);
+
+ bool hasLocalAsset(const LLUUID &uuid, LLAssetType::EType type);
+
+ // public interface methods
+ // note that your callback may get called BEFORE the function returns
+ void getAssetData(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback cb, void *user_data, bool is_priority = false);
+
+ /*
+ * TransactionID version
+ * Viewer needs the store_local
+ */
+ virtual void storeAssetData(
+ const LLTransactionID& tid,
+ LLAssetType::EType atype,
+ LLStoreAssetCallback callback,
+ void* user_data,
+ bool temp_file = false,
+ bool is_priority = false,
+ bool store_local = false,
+ bool user_waiting= false,
+ F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT) = 0;
+
+ virtual void logAssetStorageInfo() = 0;
+
+ virtual void checkForTimeouts();
+
+ void getEstateAsset(const LLHost &object_sim, const LLUUID &agent_id, const LLUUID &session_id,
+ const LLUUID &asset_id, LLAssetType::EType atype, EstateAssetType etype,
+ LLGetAssetCallback callback, void *user_data, bool is_priority);
+
+ void getInvItemAsset(const LLHost &object_sim,
+ const LLUUID &agent_id, const LLUUID &session_id,
+ const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id,
+ const LLUUID &asset_id, LLAssetType::EType atype,
+ LLGetAssetCallback cb, void *user_data, bool is_priority = false); // Get a particular inventory item.
+
+ // Check if an asset is in the toxic map. If it is, the entry is updated
+ bool isAssetToxic( const LLUUID& uuid );
+
+ // Clean the toxic asset list, remove old entries
+ void flushOldToxicAssets( bool force_it );
+
+ // Add an item to the toxic asset map
+ void markAssetToxic( const LLUUID& uuid );
+
+protected:
+ bool findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
+ LLGetAssetCallback callback, void *user_data);
+
+ LLSD getPendingDetailsImpl(const request_list_t* requests,
+ LLAssetType::EType asset_type,
+ const std::string& detail_prefix) const;
+
+ LLSD getPendingRequestImpl(const request_list_t* requests,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id) const;
+
+ bool deletePendingRequestImpl(request_list_t* requests,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id);
+
+public:
+ static const LLAssetRequest* findRequest(const request_list_t* requests,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id);
+ static LLAssetRequest* findRequest(request_list_t* requests,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id);
+
+ request_list_t* getRequestList(ERequestType rt);
+ const request_list_t* getRequestList(ERequestType rt) const;
+ static std::string getRequestName(ERequestType rt);
+
+ S32 getNumPendingDownloads() const;
+ S32 getNumPendingUploads() const;
+ S32 getNumPendingLocalUploads();
+ S32 getNumPending(ERequestType rt) const;
+
+ LLSD getPendingDetails(ERequestType rt,
+ LLAssetType::EType asset_type,
+ const std::string& detail_prefix) const;
+
+ LLSD getPendingRequest(ERequestType rt,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id) const;
+
+ bool deletePendingRequest(ERequestType rt,
+ LLAssetType::EType asset_type,
+ const LLUUID& asset_id);
+
+
+ static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type,
+ const LLUUID& callback_id, LLAssetType::EType callback_type,
+ S32 result_code, LLExtStat ext_status);
+
+ // download process callbacks
+ static void downloadCompleteCallback(
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data, LLExtStat ext_status);
+ static void downloadEstateAssetCompleteCallback(
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data, LLExtStat ext_status);
+ static void downloadInvItemCompleteCallback(
+ S32 result,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data, LLExtStat ext_status);
+
+ // upload process callbacks
+ static void uploadCompleteCallback(const LLUUID&, void *user_data, S32 result, LLExtStat ext_status);
+ static void processUploadComplete(LLMessageSystem *msg, void **this_handle);
+
+ // debugging
+ static const char* getErrorString( S32 status );
+
+ // deprecated file-based methods
+ // Not overriden
+ void getAssetData(const LLUUID uuid, LLAssetType::EType type, void (*callback)(const char*, const LLUUID&, void *, S32, LLExtStat), void *user_data, bool is_priority = false);
+
+ /*
+ * TransactionID version
+ */
+ virtual void storeAssetData(
+ const std::string& filename,
+ const LLTransactionID &transaction_id,
+ LLAssetType::EType type,
+ LLStoreAssetCallback callback,
+ void *user_data,
+ bool temp_file = false,
+ bool is_priority = false,
+ bool user_waiting = false,
+ F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0;
+
+ static void legacyGetDataCallback(const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status);
+ static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status);
+
+ // add extra methods to handle metadata
+
+protected:
+ void _cleanupRequests(bool all, S32 error);
+ void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, bool success, LLExtStat ext_status);
+
+ virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
+ void *user_data, bool duplicate,
+ bool is_priority) = 0;
+
+private:
+ void _init(LLMessageSystem *msg,
+ LLXferManager *xfer,
+ const LLHost &upstream_host);
+
+protected:
+ enum EMetricResult
+ {
+ // Static valued enums for #dw readability - please copy this
+ // declaration to them on updates -- source in llassetstorage.h
+ MR_INVALID = -1, // Makes no sense
+ MR_OKAY = 0, // Success - no metric normally
+ MR_ZERO_SIZE = 1, // Zero size asset
+ MR_BAD_FUNCTION = 2, // Tried to use a virtual base (PROGRAMMER ERROR)
+ MR_FILE_NONEXIST = 3, // Old format store call - source file does not exist
+ MR_NO_FILENAME = 4, // Old format store call - source filename is NULL/0-length
+ MR_NO_UPSTREAM = 5, // Upstream provider is missing
+ MR_CACHE_CORRUPTION = 6 // cache is corrupt - too-large or mismatched stated/returned sizes
+ };
+
+ static class LLMetrics *metric_recipient;
+
+ static void reportMetric( const LLUUID& asset_id, const LLAssetType::EType asset_type, const std::string& filename,
+ const LLUUID& agent_id, S32 asset_size, EMetricResult result,
+ const char* file, const S32 line, const std::string& message );
+public:
+ static void setMetricRecipient( LLMetrics *recip )
+ {
+ metric_recipient = recip;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////
+// Wrappers to replicate deprecated API
+////////////////////////////////////////////////////////////////////////
+
+class LLLegacyAssetRequest
+{
+public:
+ void (*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat);
+ LLStoreAssetCallback mUpCallback;
+
+ void *mUserData;
+};
+
+extern LLAssetStorage *gAssetStorage;
+extern const LLUUID CATEGORIZE_LOST_AND_FOUND_ID;
+#endif
diff --git a/indra/llmessage/llavatarname.cpp b/indra/llmessage/llavatarname.cpp
index 7e1246f885..650a76860a 100644
--- a/indra/llmessage/llavatarname.cpp
+++ b/indra/llmessage/llavatarname.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llavatarname.cpp
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -48,222 +48,222 @@ bool LLAvatarName::sUseUsernames = true;
// Minimum time-to-live (in seconds) for a name entry.
// Avatar name should always guarantee to expire reasonably soon by default
-// so if the failure to get a valid expiration time was due to something temporary
+// so if the failure to get a valid expiration time was due to something temporary
// we will eventually request and get the right data.
const F64 MIN_ENTRY_LIFETIME = 60.0;
LLAvatarName::LLAvatarName()
-: mUsername(),
- mDisplayName(),
- mLegacyFirstName(),
- mLegacyLastName(),
- mIsDisplayNameDefault(false),
- mIsTemporaryName(false),
- mExpires(F64_MAX),
- mNextUpdate(0.0)
+: mUsername(),
+ mDisplayName(),
+ mLegacyFirstName(),
+ mLegacyLastName(),
+ mIsDisplayNameDefault(false),
+ mIsTemporaryName(false),
+ mExpires(F64_MAX),
+ mNextUpdate(0.0)
{ }
bool LLAvatarName::operator<(const LLAvatarName& rhs) const
{
- if (mUsername == rhs.mUsername)
- return mDisplayName < rhs.mDisplayName;
- else
- return mUsername < rhs.mUsername;
+ if (mUsername == rhs.mUsername)
+ return mDisplayName < rhs.mDisplayName;
+ else
+ return mUsername < rhs.mUsername;
}
-//static
+//static
void LLAvatarName::setUseDisplayNames(bool use)
{
- sUseDisplayNames = use;
+ sUseDisplayNames = use;
}
-//static
-bool LLAvatarName::useDisplayNames()
-{
- return sUseDisplayNames;
+//static
+bool LLAvatarName::useDisplayNames()
+{
+ return sUseDisplayNames;
}
void LLAvatarName::setUseUsernames(bool use)
{
- sUseUsernames = use;
+ sUseUsernames = use;
}
bool LLAvatarName::useUsernames()
{
- return sUseUsernames;
+ return sUseUsernames;
}
LLSD LLAvatarName::asLLSD() const
{
- LLSD sd;
- sd[USERNAME] = mUsername;
- sd[DISPLAY_NAME] = mDisplayName;
- sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
- sd[LEGACY_LAST_NAME] = mLegacyLastName;
- sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
- sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
- sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
- return sd;
+ LLSD sd;
+ sd[USERNAME] = mUsername;
+ sd[DISPLAY_NAME] = mDisplayName;
+ sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
+ sd[LEGACY_LAST_NAME] = mLegacyLastName;
+ sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
+ sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
+ sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
+ return sd;
}
void LLAvatarName::fromLLSD(const LLSD& sd)
{
- mUsername = sd[USERNAME].asString();
- mDisplayName = sd[DISPLAY_NAME].asString();
- mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
- mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
- mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
- LLDate expires = sd[DISPLAY_NAME_EXPIRES];
- mExpires = expires.secondsSinceEpoch();
- LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
- mNextUpdate = next_update.secondsSinceEpoch();
-
- // Some avatars don't have explicit display names set. Force a legible display name here.
- if (mDisplayName.empty())
- {
- mDisplayName = mUsername;
- }
+ mUsername = sd[USERNAME].asString();
+ mDisplayName = sd[DISPLAY_NAME].asString();
+ mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
+ mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
+ mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
+ LLDate expires = sd[DISPLAY_NAME_EXPIRES];
+ mExpires = expires.secondsSinceEpoch();
+ LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
+ mNextUpdate = next_update.secondsSinceEpoch();
+
+ // Some avatars don't have explicit display names set. Force a legible display name here.
+ if (mDisplayName.empty())
+ {
+ mDisplayName = mUsername;
+ }
}
// Transform a string (typically provided by the legacy service) into a decent
// avatar name instance.
void LLAvatarName::fromString(const std::string& full_name)
{
- mDisplayName = full_name;
- std::string::size_type index = full_name.find(' ');
- if (index != std::string::npos)
- {
- // The name is in 2 parts (first last)
- mLegacyFirstName = full_name.substr(0, index);
- mLegacyLastName = full_name.substr(index+1);
- if (mLegacyLastName != "Resident")
- {
- mUsername = mLegacyFirstName + "." + mLegacyLastName;
- mDisplayName = full_name;
- LLStringUtil::toLower(mUsername);
- }
- else
- {
- // Very old names do have a dummy "Resident" last name
- // that we choose to hide from users.
- mUsername = mLegacyFirstName;
- mDisplayName = mLegacyFirstName;
- }
- }
- else
- {
- mLegacyFirstName = full_name;
- mLegacyLastName = "";
- mUsername = full_name;
- mDisplayName = full_name;
- }
- mIsDisplayNameDefault = true;
- mIsTemporaryName = true;
- setExpires(MIN_ENTRY_LIFETIME);
+ mDisplayName = full_name;
+ std::string::size_type index = full_name.find(' ');
+ if (index != std::string::npos)
+ {
+ // The name is in 2 parts (first last)
+ mLegacyFirstName = full_name.substr(0, index);
+ mLegacyLastName = full_name.substr(index+1);
+ if (mLegacyLastName != "Resident")
+ {
+ mUsername = mLegacyFirstName + "." + mLegacyLastName;
+ mDisplayName = full_name;
+ LLStringUtil::toLower(mUsername);
+ }
+ else
+ {
+ // Very old names do have a dummy "Resident" last name
+ // that we choose to hide from users.
+ mUsername = mLegacyFirstName;
+ mDisplayName = mLegacyFirstName;
+ }
+ }
+ else
+ {
+ mLegacyFirstName = full_name;
+ mLegacyLastName = "";
+ mUsername = full_name;
+ mDisplayName = full_name;
+ }
+ mIsDisplayNameDefault = true;
+ mIsTemporaryName = true;
+ setExpires(MIN_ENTRY_LIFETIME);
}
void LLAvatarName::setExpires(F64 expires)
{
- mExpires = LLFrameTimer::getTotalSeconds() + expires;
+ mExpires = LLFrameTimer::getTotalSeconds() + expires;
}
std::string LLAvatarName::getCompleteName(bool use_parentheses, bool force_use_complete_name) const
{
- std::string name;
- if (sUseDisplayNames || force_use_complete_name)
- {
- if (mUsername.empty() || mIsDisplayNameDefault)
- {
- // If this particular display name is defaulted (i.e. based on user name),
- // then display only the easier to read instance of the person's name.
- name = mDisplayName;
- }
- else
- {
- name = mDisplayName;
- if(sUseUsernames || force_use_complete_name)
- {
- if(use_parentheses)
- {
- name += " (" + mUsername + ")";
- }
- else
- {
- name += " [ " + mUsername + " ]";
- }
- }
- }
- }
- else
- {
- name = getUserName();
- }
- return name;
+ std::string name;
+ if (sUseDisplayNames || force_use_complete_name)
+ {
+ if (mUsername.empty() || mIsDisplayNameDefault)
+ {
+ // If this particular display name is defaulted (i.e. based on user name),
+ // then display only the easier to read instance of the person's name.
+ name = mDisplayName;
+ }
+ else
+ {
+ name = mDisplayName;
+ if(sUseUsernames || force_use_complete_name)
+ {
+ if(use_parentheses)
+ {
+ name += " (" + mUsername + ")";
+ }
+ else
+ {
+ name += " [ " + mUsername + " ]";
+ }
+ }
+ }
+ }
+ else
+ {
+ name = getUserName();
+ }
+ return name;
}
std::string LLAvatarName::getLegacyName() const
{
- if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
- {
- return mDisplayName;
- }
+ if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
+ {
+ return mDisplayName;
+ }
- std::string name;
- name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
- name = mLegacyFirstName;
- name += " ";
- name += mLegacyLastName;
- return name;
+ std::string name;
+ name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
+ name = mLegacyFirstName;
+ name += " ";
+ name += mLegacyLastName;
+ return name;
}
std::string LLAvatarName::getDisplayName(bool force_use_display_name) const
{
- if (sUseDisplayNames || force_use_display_name)
- {
- return mDisplayName;
- }
- else
- {
- return getUserName();
- }
+ if (sUseDisplayNames || force_use_display_name)
+ {
+ return mDisplayName;
+ }
+ else
+ {
+ return getUserName();
+ }
}
std::string LLAvatarName::getUserName(bool lowercase) const
{
- std::string name;
- if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
- {
- if (mLegacyFirstName.empty())
- {
- // If we cannot create a user name from the legacy strings, use the display name
- name = mDisplayName;
- }
- else
- {
- // The last name might be empty if it defaulted to "Resident"
- name = mLegacyFirstName;
- }
- }
- else
- {
- if(lowercase)
- {
- name = mLegacyFirstName + "." + mLegacyLastName;
- LLStringUtil::toLower(name);
- }
- else
- {
- name = mLegacyFirstName + " " + mLegacyLastName;
- }
- }
- return name;
+ std::string name;
+ if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
+ {
+ if (mLegacyFirstName.empty())
+ {
+ // If we cannot create a user name from the legacy strings, use the display name
+ name = mDisplayName;
+ }
+ else
+ {
+ // The last name might be empty if it defaulted to "Resident"
+ name = mLegacyFirstName;
+ }
+ }
+ else
+ {
+ if(lowercase)
+ {
+ name = mLegacyFirstName + "." + mLegacyLastName;
+ LLStringUtil::toLower(name);
+ }
+ else
+ {
+ name = mLegacyFirstName + " " + mLegacyLastName;
+ }
+ }
+ return name;
}
void LLAvatarName::dump() const
{
- LL_DEBUGS("AvNameCache") << "LLAvatarName: "
- << "user '" << mUsername << "' "
- << "display '" << mDisplayName << "' "
- << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
- << LL_ENDL;
+ LL_DEBUGS("AvNameCache") << "LLAvatarName: "
+ << "user '" << mUsername << "' "
+ << "display '" << mDisplayName << "' "
+ << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
+ << LL_ENDL;
}
diff --git a/indra/llmessage/llavatarname.h b/indra/llmessage/llavatarname.h
index 20f7140797..eec966d51b 100644
--- a/indra/llmessage/llavatarname.h
+++ b/indra/llmessage/llavatarname.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llavatarname.h
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,105 +35,105 @@ class LLSD;
class LL_COMMON_API LLAvatarName
{
public:
- LLAvatarName();
-
- bool operator<(const LLAvatarName& rhs) const;
-
- // Conversion to and from LLSD (cache file or server response)
- LLSD asLLSD() const;
- void fromLLSD(const LLSD& sd);
-
- // Used only in legacy mode when the display name capability is not provided server side
- // or to otherwise create a temporary valid item.
- void fromString(const std::string& full_name);
-
- // Set the name object to become invalid in "expires" seconds from now
- void setExpires(F64 expires);
-
- // Set and get the display name flag set by the user in preferences.
- static void setUseDisplayNames(bool use);
- static bool useDisplayNames();
-
- static void setUseUsernames(bool use);
- static bool useUsernames();
-
- // A name object is valid if not temporary and not yet expired (default is expiration not checked)
- bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); }
-
- // Return true if the name is made up from legacy or temporary data
- bool isDisplayNameDefault() const { return mIsDisplayNameDefault; }
-
- // For normal names, returns "James Linden (james.linden)"
- // When display names are disabled returns just "James Linden"
- std::string getCompleteName(bool use_parentheses = true, bool force_use_complete_name = false) const;
-
- // Returns "James Linden" or "bobsmith123 Resident" for backwards
- // compatibility with systems like voice and muting
- // *TODO: Eliminate this in favor of username only
- std::string getLegacyName() const;
-
- // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
- // Takes the display name preference into account. This is truly the name that should
- // be used for all UI where an avatar name has to be used unless we truly want something else (rare)
- std::string getDisplayName(bool force_use_display_name = false) const;
-
- // Returns "James Linden" or "bobsmith123 Resident"
- // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
- // Also used for backwards compatibility with systems like voice and muting
- std::string getUserName(bool lowercase = false) const;
-
- // Returns "james.linden" or the legacy name for very old names
- std::string getAccountName() const { return mUsername; }
-
- // Debug print of the object
- void dump() const;
-
- // Names can change, so need to keep track of when name was
- // last checked.
- // Unix time-from-epoch seconds for efficiency
- F64 mExpires;
-
- // You can only change your name every N hours, so record
- // when the next update is allowed
- // Unix time-from-epoch seconds
- F64 mNextUpdate;
-
+ LLAvatarName();
+
+ bool operator<(const LLAvatarName& rhs) const;
+
+ // Conversion to and from LLSD (cache file or server response)
+ LLSD asLLSD() const;
+ void fromLLSD(const LLSD& sd);
+
+ // Used only in legacy mode when the display name capability is not provided server side
+ // or to otherwise create a temporary valid item.
+ void fromString(const std::string& full_name);
+
+ // Set the name object to become invalid in "expires" seconds from now
+ void setExpires(F64 expires);
+
+ // Set and get the display name flag set by the user in preferences.
+ static void setUseDisplayNames(bool use);
+ static bool useDisplayNames();
+
+ static void setUseUsernames(bool use);
+ static bool useUsernames();
+
+ // A name object is valid if not temporary and not yet expired (default is expiration not checked)
+ bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); }
+
+ // Return true if the name is made up from legacy or temporary data
+ bool isDisplayNameDefault() const { return mIsDisplayNameDefault; }
+
+ // For normal names, returns "James Linden (james.linden)"
+ // When display names are disabled returns just "James Linden"
+ std::string getCompleteName(bool use_parentheses = true, bool force_use_complete_name = false) const;
+
+ // Returns "James Linden" or "bobsmith123 Resident" for backwards
+ // compatibility with systems like voice and muting
+ // *TODO: Eliminate this in favor of username only
+ std::string getLegacyName() const;
+
+ // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
+ // Takes the display name preference into account. This is truly the name that should
+ // be used for all UI where an avatar name has to be used unless we truly want something else (rare)
+ std::string getDisplayName(bool force_use_display_name = false) const;
+
+ // Returns "James Linden" or "bobsmith123 Resident"
+ // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
+ // Also used for backwards compatibility with systems like voice and muting
+ std::string getUserName(bool lowercase = false) const;
+
+ // Returns "james.linden" or the legacy name for very old names
+ std::string getAccountName() const { return mUsername; }
+
+ // Debug print of the object
+ void dump() const;
+
+ // Names can change, so need to keep track of when name was
+ // last checked.
+ // Unix time-from-epoch seconds for efficiency
+ F64 mExpires;
+
+ // You can only change your name every N hours, so record
+ // when the next update is allowed
+ // Unix time-from-epoch seconds
+ F64 mNextUpdate;
+
private:
- // "bobsmith123" or "james.linden", US-ASCII only
- std::string mUsername;
-
- // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
- // Contains data whether or not user has explicitly set
- // a display name; may duplicate their username.
- std::string mDisplayName;
-
- // For "James Linden", "James"
- // For "bobsmith123", "bobsmith123"
- // Used to communicate with legacy systems like voice and muting which
- // rely on old-style names.
- // *TODO: Eliminate this in favor of username only
- std::string mLegacyFirstName;
-
- // For "James Linden", "Linden"
- // For "bobsmith123", "Resident"
- // see above for rationale
- std::string mLegacyLastName;
-
- // If true, both display name and SLID were generated from
- // a legacy first and last name, like "James Linden (james.linden)"
- bool mIsDisplayNameDefault;
-
- // Under error conditions, we may insert "dummy" records with
- // names like "???" into caches as placeholders. These can be
- // shown in UI, but are not serialized.
- bool mIsTemporaryName;
-
- // Global flag indicating if display name should be used or not
- // This will affect the output of the high level "get" methods
- static bool sUseDisplayNames;
-
- // Flag indicating if username should be shown after display name or not
- static bool sUseUsernames;
+ // "bobsmith123" or "james.linden", US-ASCII only
+ std::string mUsername;
+
+ // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
+ // Contains data whether or not user has explicitly set
+ // a display name; may duplicate their username.
+ std::string mDisplayName;
+
+ // For "James Linden", "James"
+ // For "bobsmith123", "bobsmith123"
+ // Used to communicate with legacy systems like voice and muting which
+ // rely on old-style names.
+ // *TODO: Eliminate this in favor of username only
+ std::string mLegacyFirstName;
+
+ // For "James Linden", "Linden"
+ // For "bobsmith123", "Resident"
+ // see above for rationale
+ std::string mLegacyLastName;
+
+ // If true, both display name and SLID were generated from
+ // a legacy first and last name, like "James Linden (james.linden)"
+ bool mIsDisplayNameDefault;
+
+ // Under error conditions, we may insert "dummy" records with
+ // names like "???" into caches as placeholders. These can be
+ // shown in UI, but are not serialized.
+ bool mIsTemporaryName;
+
+ // Global flag indicating if display name should be used or not
+ // This will affect the output of the high level "get" methods
+ static bool sUseDisplayNames;
+
+ // Flag indicating if username should be shown after display name or not
+ static bool sUseUsernames;
};
#endif
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index f7a9f55685..a0cd6f93c1 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llavatarnamecache.cpp
* @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
* ("James Cook") from avatar UUIDs.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,7 +28,7 @@
#include "llavatarnamecache.h"
-#include "llcachename.h" // we wrap this system
+#include "llcachename.h" // we wrap this system
#include "llframetimer.h"
#include "llsd.h"
#include "llsdserialize.h"
@@ -60,10 +60,10 @@ const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0;
static LLFrameTimer sRequestTimer;
// static to avoid unnessesary dependencies
-LLCore::HttpRequest::ptr_t sHttpRequest;
-LLCore::HttpHeaders::ptr_t sHttpHeaders;
-LLCore::HttpOptions::ptr_t sHttpOptions;
-LLCore::HttpRequest::policy_t sHttpPolicy;
+LLCore::HttpRequest::ptr_t sHttpRequest;
+LLCore::HttpHeaders::ptr_t sHttpHeaders;
+LLCore::HttpOptions::ptr_t sHttpOptions;
+LLCore::HttpRequest::policy_t sHttpPolicy;
/* Sample response:
<?xml version="1.0"?>
@@ -104,7 +104,7 @@ LLCore::HttpRequest::policy_t sHttpPolicy;
</llsd>
*/
-// Coroutine for sending and processing avatar name cache requests.
+// Coroutine for sending and processing avatar name cache requests.
// Do not call directly. See documentation in lleventcoro.h and llcoro.h for
// further explanation.
@@ -180,7 +180,7 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
if (LLAvatarNameCache::instanceExists())
{
if (!success)
- { // on any sort of failure add dummy records for any agent IDs
+ { // on any sort of failure add dummy records for any agent IDs
// in this request that we do not have cached already
std::vector<LLUUID>::const_iterator it = agentIds.begin();
for (; it != agentIds.end(); ++it)
@@ -268,16 +268,16 @@ void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &h
// Provide some fallback for agents that return errors
void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
{
- std::map<LLUUID,LLAvatarName>::iterator existing = mCache.find(agent_id);
- if (existing == mCache.end())
+ std::map<LLUUID,LLAvatarName>::iterator existing = mCache.find(agent_id);
+ if (existing == mCache.end())
{
// there is no existing cache entry, so make a temporary name from legacy
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache get legacy for agent "
- << agent_id << LL_ENDL;
+ << agent_id << LL_ENDL;
gCacheName->get(agent_id, false, // legacy compatibility
boost::bind(&LLAvatarNameCache::legacyNameFetch, _1, _2, _3));
}
- else
+ else
{
// we have a cached (but probably expired) entry - since that would have
// been returned by the get method, there is no need to signal anyone
@@ -287,19 +287,19 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
LLAvatarName& av_name = existing->second;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL;
- av_name.dump();
+ av_name.dump();
- // Reset expiry time so we don't constantly rerequest.
- av_name.setExpires(TEMP_CACHE_ENTRY_LIFETIME);
+ // Reset expiry time so we don't constantly rerequest.
+ av_name.setExpires(TEMP_CACHE_ENTRY_LIFETIME);
}
}
void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName& av_name)
{
- if (agent_id.isNull())
- {
- return;
- }
+ if (agent_id.isNull())
+ {
+ return;
+ }
bool updated_account = true; // assume obsolete value for new arrivals by default
@@ -310,175 +310,175 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName&
updated_account = false;
}
- // Add to the cache
- mCache[agent_id] = av_name;
+ // Add to the cache
+ mCache[agent_id] = av_name;
- // Suppress request from the queue
- mPendingQueue.erase(agent_id);
+ // Suppress request from the queue
+ mPendingQueue.erase(agent_id);
- // notify mute list about changes
+ // notify mute list about changes
if (updated_account && mAccountNameChangedCallback)
{
mAccountNameChangedCallback(agent_id, av_name);
}
- // Signal everyone waiting on this name
- signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
- if (sig_it != mSignalMap.end())
- {
- callback_signal_t* signal = sig_it->second;
- (*signal)(agent_id, av_name);
+ // Signal everyone waiting on this name
+ signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
+ if (sig_it != mSignalMap.end())
+ {
+ callback_signal_t* signal = sig_it->second;
+ (*signal)(agent_id, av_name);
- mSignalMap.erase(agent_id);
+ mSignalMap.erase(agent_id);
- delete signal;
- signal = NULL;
- }
+ delete signal;
+ signal = NULL;
+ }
}
void LLAvatarNameCache::requestNamesViaCapability()
{
- F64 now = LLFrameTimer::getTotalSeconds();
-
- // URL format is like:
- // http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
- //
- // Apache can handle URLs of 4096 chars, but let's be conservative
- static const U32 NAME_URL_MAX = 4096;
- static const U32 NAME_URL_SEND_THRESHOLD = 3500;
-
- std::string url;
- url.reserve(NAME_URL_MAX);
-
- std::vector<LLUUID> agent_ids;
- agent_ids.reserve(128);
-
- U32 ids = 0;
- ask_queue_t::const_iterator it;
- while(!mAskQueue.empty())
- {
- it = mAskQueue.begin();
- LLUUID agent_id = *it;
- mAskQueue.erase(it);
-
- if (url.empty())
- {
- // ...starting new request
- url += mNameLookupURL;
- url += "?ids=";
- ids = 1;
- }
- else
- {
- // ...continuing existing request
- url += "&ids=";
- ids++;
- }
- url += agent_id.asString();
- agent_ids.push_back(agent_id);
-
- // mark request as pending
- mPendingQueue[agent_id] = now;
-
- if (url.size() > NAME_URL_SEND_THRESHOLD)
- {
- break;
- }
- }
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // URL format is like:
+ // http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
+ //
+ // Apache can handle URLs of 4096 chars, but let's be conservative
+ static const U32 NAME_URL_MAX = 4096;
+ static const U32 NAME_URL_SEND_THRESHOLD = 3500;
+
+ std::string url;
+ url.reserve(NAME_URL_MAX);
+
+ std::vector<LLUUID> agent_ids;
+ agent_ids.reserve(128);
+
+ U32 ids = 0;
+ ask_queue_t::const_iterator it;
+ while(!mAskQueue.empty())
+ {
+ it = mAskQueue.begin();
+ LLUUID agent_id = *it;
+ mAskQueue.erase(it);
+
+ if (url.empty())
+ {
+ // ...starting new request
+ url += mNameLookupURL;
+ url += "?ids=";
+ ids = 1;
+ }
+ else
+ {
+ // ...continuing existing request
+ url += "&ids=";
+ ids++;
+ }
+ url += agent_id.asString();
+ agent_ids.push_back(agent_id);
+
+ // mark request as pending
+ mPendingQueue[agent_id] = now;
+
+ if (url.size() > NAME_URL_SEND_THRESHOLD)
+ {
+ break;
+ }
+ }
if (!url.empty())
{
LL_DEBUGS("AvNameCache") << "requested " << ids << " ids" << LL_ENDL;
- std::string coroname =
+ std::string coroname =
LLCoros::instance().launch("LLAvatarNameCache::requestAvatarNameCache_",
boost::bind(&LLAvatarNameCache::requestAvatarNameCache_, url, agent_ids));
LL_DEBUGS("AvNameCache") << coroname << " with url '" << url << "', agent_ids.size()=" << agent_ids.size() << LL_ENDL;
- }
+ }
}
void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
- const std::string& full_name,
- bool is_group)
+ const std::string& full_name,
+ bool is_group)
{
- // Put the received data in the cache
- legacyNameFetch(agent_id, full_name, is_group);
-
- // Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy
- // protocol, we do not get an expiration date for each name and there's no reason to ask the
- // data again and again so we set the expiration time to the largest value admissible.
- std::map<LLUUID,LLAvatarName>::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id);
- LLAvatarName& av_name = av_record->second;
- av_name.setExpires(MAX_UNREFRESHED_TIME);
+ // Put the received data in the cache
+ legacyNameFetch(agent_id, full_name, is_group);
+
+ // Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy
+ // protocol, we do not get an expiration date for each name and there's no reason to ask the
+ // data again and again so we set the expiration time to the largest value admissible.
+ std::map<LLUUID,LLAvatarName>::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id);
+ LLAvatarName& av_name = av_record->second;
+ av_name.setExpires(MAX_UNREFRESHED_TIME);
}
void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id,
- const std::string& full_name,
- bool is_group)
-{
- LL_DEBUGS("AvNameCache") << "LLAvatarNameCache agent " << agent_id << " "
- << "full name '" << full_name << "'"
- << ( is_group ? " [group]" : "" )
- << LL_ENDL;
-
- // Construct an av_name record from this name.
- LLAvatarName av_name;
- av_name.fromString(full_name);
-
- // Add to cache: we're still using the new cache even if we're using the old (legacy) protocol.
- LLAvatarNameCache::getInstance()->processName(agent_id, av_name);
+ const std::string& full_name,
+ bool is_group)
+{
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache agent " << agent_id << " "
+ << "full name '" << full_name << "'"
+ << ( is_group ? " [group]" : "" )
+ << LL_ENDL;
+
+ // Construct an av_name record from this name.
+ LLAvatarName av_name;
+ av_name.fromString(full_name);
+
+ // Add to cache: we're still using the new cache even if we're using the old (legacy) protocol.
+ LLAvatarNameCache::getInstance()->processName(agent_id, av_name);
}
void LLAvatarNameCache::requestNamesViaLegacy()
{
- static const S32 MAX_REQUESTS = 100;
- F64 now = LLFrameTimer::getTotalSeconds();
- std::string full_name;
- ask_queue_t::const_iterator it;
- for (S32 requests = 0; !mAskQueue.empty() && requests < MAX_REQUESTS; ++requests)
- {
- it = mAskQueue.begin();
- LLUUID agent_id = *it;
- mAskQueue.erase(it);
+ static const S32 MAX_REQUESTS = 100;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ std::string full_name;
+ ask_queue_t::const_iterator it;
+ for (S32 requests = 0; !mAskQueue.empty() && requests < MAX_REQUESTS; ++requests)
+ {
+ it = mAskQueue.begin();
+ LLUUID agent_id = *it;
+ mAskQueue.erase(it);
- // Mark as pending first, just in case the callback is immediately
- // invoked below. This should never happen in practice.
- mPendingQueue[agent_id] = now;
+ // Mark as pending first, just in case the callback is immediately
+ // invoked below. This should never happen in practice.
+ mPendingQueue[agent_id] = now;
- LL_DEBUGS("AvNameCache") << "agent " << agent_id << LL_ENDL;
+ LL_DEBUGS("AvNameCache") << "agent " << agent_id << LL_ENDL;
- gCacheName->get(agent_id, false, // legacy compatibility
- boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3));
- }
+ gCacheName->get(agent_id, false, // legacy compatibility
+ boost::bind(&LLAvatarNameCache::legacyNameCallback, _1, _2, _3));
+ }
}
bool LLAvatarNameCache::importFile(std::istream& istr)
{
- LLSD data;
- if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
- {
+ LLSD data;
+ if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
+ {
LL_WARNS("AvNameCache") << "avatar name cache data xml parse failed" << LL_ENDL;
- return false;
- }
-
- // by convention LLSD storage is a map
- // we only store one entry in the map
- LLSD agents = data["agents"];
-
- LLUUID agent_id;
- LLAvatarName av_name;
- LLSD::map_const_iterator it = agents.beginMap();
- for ( ; it != agents.endMap(); ++it)
- {
- agent_id.set(it->first);
- av_name.fromLLSD( it->second );
- mCache[agent_id] = av_name;
- }
+ return false;
+ }
+
+ // by convention LLSD storage is a map
+ // we only store one entry in the map
+ LLSD agents = data["agents"];
+
+ LLUUID agent_id;
+ LLAvatarName av_name;
+ LLSD::map_const_iterator it = agents.beginMap();
+ for ( ; it != agents.endMap(); ++it)
+ {
+ agent_id.set(it->first);
+ av_name.fromLLSD( it->second );
+ mCache[agent_id] = av_name;
+ }
LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << mCache.size() << LL_ENDL;
- // Some entries may have expired since the cache was stored,
+ // Some entries may have expired since the cache was stored,
// but they will be flushed in the first call to eraseUnrefreshed
// from LLAvatarNameResponder::idle
@@ -487,35 +487,35 @@ bool LLAvatarNameCache::importFile(std::istream& istr)
void LLAvatarNameCache::exportFile(std::ostream& ostr)
{
- LLSD agents;
- F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME;
+ LLSD agents;
+ F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME;
LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << mCache.size() << LL_ENDL;
- cache_t::const_iterator it = mCache.begin();
- for ( ; it != mCache.end(); ++it)
- {
- const LLUUID& agent_id = it->first;
- const LLAvatarName& av_name = it->second;
- // Do not write temporary or expired entries to the stored cache
- if (av_name.isValidName(max_unrefreshed))
- {
- // key must be a string
- agents[agent_id.asString()] = av_name.asLLSD();
- }
- }
+ cache_t::const_iterator it = mCache.begin();
+ for ( ; it != mCache.end(); ++it)
+ {
+ const LLUUID& agent_id = it->first;
+ const LLAvatarName& av_name = it->second;
+ // Do not write temporary or expired entries to the stored cache
+ if (av_name.isValidName(max_unrefreshed))
+ {
+ // key must be a string
+ agents[agent_id.asString()] = av_name.asLLSD();
+ }
+ }
LL_INFOS("AvNameCache") << "LLAvatarNameCache returning " << agents.size() << LL_ENDL;
- LLSD data;
- data["agents"] = agents;
- LLSDSerialize::toPrettyXML(data, ostr);
+ LLSD data;
+ data["agents"] = agents;
+ LLSDSerialize::toPrettyXML(data, ostr);
}
void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url)
{
- mNameLookupURL = name_lookup_url;
+ mNameLookupURL = name_lookup_url;
}
bool LLAvatarNameCache::hasNameLookupURL()
{
- return !mNameLookupURL.empty();
+ return !mNameLookupURL.empty();
}
void LLAvatarNameCache::setUsePeopleAPI(bool use_api)
@@ -525,25 +525,25 @@ void LLAvatarNameCache::setUsePeopleAPI(bool use_api)
bool LLAvatarNameCache::usePeopleAPI()
{
- return hasNameLookupURL() && mUsePeopleAPI;
+ return hasNameLookupURL() && mUsePeopleAPI;
}
void LLAvatarNameCache::idle()
{
- // By convention, start running at first idle() call
- mRunning = true;
+ // By convention, start running at first idle() call
+ mRunning = true;
- // *TODO: Possibly re-enabled this based on People API load measurements
- // 100 ms is the threshold for "user speed" operations, so we can
- // stall for about that long to batch up requests.
- const F32 SECS_BETWEEN_REQUESTS = 0.1f;
- if (!sRequestTimer.hasExpired())
- {
- return;
- }
+ // *TODO: Possibly re-enabled this based on People API load measurements
+ // 100 ms is the threshold for "user speed" operations, so we can
+ // stall for about that long to batch up requests.
+ const F32 SECS_BETWEEN_REQUESTS = 0.1f;
+ if (!sRequestTimer.hasExpired())
+ {
+ return;
+ }
- if (!mAskQueue.empty())
- {
+ if (!mAskQueue.empty())
+ {
if (usePeopleAPI())
{
requestNamesViaCapability();
@@ -553,13 +553,13 @@ void LLAvatarNameCache::idle()
LL_WARNS_ONCE("AvNameCache") << "LLAvatarNameCache still using legacy api" << LL_ENDL;
requestNamesViaLegacy();
}
- }
+ }
- if (mAskQueue.empty())
- {
- // cleared the list, reset the request timer.
- sRequestTimer.resetWithExpiry(SECS_BETWEEN_REQUESTS);
- }
+ if (mAskQueue.empty())
+ {
+ // cleared the list, reset the request timer.
+ sRequestTimer.resetWithExpiry(SECS_BETWEEN_REQUESTS);
+ }
// erase anything that has not been refreshed for more than MAX_UNREFRESHED_TIME
eraseUnrefreshed();
@@ -567,23 +567,23 @@ void LLAvatarNameCache::idle()
bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
{
- bool isPending = false;
- const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+ bool isPending = false;
+ const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
- pending_queue_t::const_iterator it = mPendingQueue.find(agent_id);
- if (it != mPendingQueue.end())
- {
- // in the list of requests in flight, retry if too old
- F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
- isPending = (it->second > expire_time);
- }
- return isPending;
+ pending_queue_t::const_iterator it = mPendingQueue.find(agent_id);
+ if (it != mPendingQueue.end())
+ {
+ // in the list of requests in flight, retry if too old
+ F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
+ isPending = (it->second > expire_time);
+ }
+ return isPending;
}
void LLAvatarNameCache::eraseUnrefreshed()
{
- F64 now = LLFrameTimer::getTotalSeconds();
- F64 max_unrefreshed = now - MAX_UNREFRESHED_TIME;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ F64 max_unrefreshed = now - MAX_UNREFRESHED_TIME;
if (!mLastExpireCheck || mLastExpireCheck < max_unrefreshed)
{
@@ -594,21 +594,21 @@ void LLAvatarNameCache::eraseUnrefreshed()
const LLAvatarName& av_name = it->second;
if (av_name.mExpires < max_unrefreshed)
{
- LL_DEBUGS("AvNameCacheExpired") << "LLAvatarNameCache " << it->first
+ LL_DEBUGS("AvNameCacheExpired") << "LLAvatarNameCache " << it->first
<< " user '" << av_name.getAccountName() << "' "
<< "expired " << now - av_name.mExpires << " secs ago"
<< LL_ENDL;
mCache.erase(it++);
expired++;
}
- else
- {
- ++it;
- }
+ else
+ {
+ ++it;
+ }
}
LL_INFOS("AvNameCache") << "LLAvatarNameCache expired " << expired << " cached avatar names, "
<< mCache.size() << " remaining" << LL_ENDL;
- }
+ }
}
//static, wrapper
@@ -620,45 +620,45 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
// returns bool specifying if av_name was filled, false otherwise
bool LLAvatarNameCache::getName(const LLUUID& agent_id, LLAvatarName *av_name)
{
- if (mRunning)
- {
- // ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
- if (it != mCache.end())
- {
- *av_name = it->second;
-
- // re-request name if entry is expired
- if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
- {
- if (!isRequestPending(agent_id))
- {
- LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id
- << LL_ENDL;
- mAskQueue.insert(agent_id);
- }
- }
-
- return true;
- }
- }
-
- if (!isRequestPending(agent_id))
- {
- LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL;
- mAskQueue.insert(agent_id);
- }
-
- return false;
+ if (mRunning)
+ {
+ // ...only do immediate lookups when cache is running
+ std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ if (it != mCache.end())
+ {
+ *av_name = it->second;
+
+ // re-request name if entry is expired
+ if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
+ {
+ if (!isRequestPending(agent_id))
+ {
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id
+ << LL_ENDL;
+ mAskQueue.insert(agent_id);
+ }
+ }
+
+ return true;
+ }
+ }
+
+ if (!isRequestPending(agent_id))
+ {
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL;
+ mAskQueue.insert(agent_id);
+ }
+
+ return false;
}
void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
- const callback_slot_t& slot,
- const LLAvatarName& av_name)
+ const callback_slot_t& slot,
+ const LLAvatarName& av_name)
{
- callback_signal_t signal;
- signal.connect(slot);
- signal(agent_id, av_name);
+ callback_signal_t signal;
+ signal.connect(slot);
+ signal(agent_id, av_name);
}
// static, wrapper
@@ -669,78 +669,78 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag
LLAvatarNameCache::callback_connection_t LLAvatarNameCache::getNameCallback(const LLUUID& agent_id, callback_slot_t slot)
{
- callback_connection_t connection;
-
- if (mRunning)
- {
- // ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
- if (it != mCache.end())
- {
- const LLAvatarName& av_name = it->second;
-
- if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
- {
- // ...name already exists in cache, fire callback now
- fireSignal(agent_id, slot, av_name);
- return connection;
- }
- }
- }
-
- // schedule a request
- if (!isRequestPending(agent_id))
- {
- mAskQueue.insert(agent_id);
- }
-
- // always store additional callback, even if request is pending
- signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
- if (sig_it == mSignalMap.end())
- {
- // ...new callback for this id
- callback_signal_t* signal = new callback_signal_t();
- connection = signal->connect(slot);
- mSignalMap[agent_id] = signal;
- }
- else
- {
- // ...existing callback, bind additional slot
- callback_signal_t* signal = sig_it->second;
- connection = signal->connect(slot);
- }
-
- return connection;
+ callback_connection_t connection;
+
+ if (mRunning)
+ {
+ // ...only do immediate lookups when cache is running
+ std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ if (it != mCache.end())
+ {
+ const LLAvatarName& av_name = it->second;
+
+ if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
+ {
+ // ...name already exists in cache, fire callback now
+ fireSignal(agent_id, slot, av_name);
+ return connection;
+ }
+ }
+ }
+
+ // schedule a request
+ if (!isRequestPending(agent_id))
+ {
+ mAskQueue.insert(agent_id);
+ }
+
+ // always store additional callback, even if request is pending
+ signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
+ if (sig_it == mSignalMap.end())
+ {
+ // ...new callback for this id
+ callback_signal_t* signal = new callback_signal_t();
+ connection = signal->connect(slot);
+ mSignalMap[agent_id] = signal;
+ }
+ else
+ {
+ // ...existing callback, bind additional slot
+ callback_signal_t* signal = sig_it->second;
+ connection = signal->connect(slot);
+ }
+
+ return connection;
}
void LLAvatarNameCache::setUseDisplayNames(bool use)
{
- if (use != LLAvatarName::useDisplayNames())
- {
- LLAvatarName::setUseDisplayNames(use);
- mUseDisplayNamesSignal();
- }
+ if (use != LLAvatarName::useDisplayNames())
+ {
+ LLAvatarName::setUseDisplayNames(use);
+ mUseDisplayNamesSignal();
+ }
}
void LLAvatarNameCache::setUseUsernames(bool use)
{
- if (use != LLAvatarName::useUsernames())
- {
- LLAvatarName::setUseUsernames(use);
- mUseDisplayNamesSignal();
- }
+ if (use != LLAvatarName::useUsernames())
+ {
+ LLAvatarName::setUseUsernames(use);
+ mUseDisplayNamesSignal();
+ }
}
void LLAvatarNameCache::erase(const LLUUID& agent_id)
{
- mCache.erase(agent_id);
+ mCache.erase(agent_id);
}
void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
{
- // *TODO: update timestamp if zero?
- mCache[agent_id] = av_name;
+ // *TODO: update timestamp if zero?
+ mCache[agent_id] = av_name;
}
LLUUID LLAvatarNameCache::findIdByName(const std::string& name)
@@ -789,7 +789,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers,
// Allow the header to override the default
const std::string *cache_control;
-
+
cache_control = headers->find(HTTP_IN_HEADER_CACHE_CONTROL);
if (cache_control && !cache_control->empty())
@@ -811,53 +811,53 @@ bool LLAvatarNameCache::expirationFromCacheControl(LLCore::HttpHeaders *headers,
#else
F64 LLAvatarNameCache::nameExpirationFromHeaders(const LLSD& headers)
{
- F64 expires = 0.0;
- if (expirationFromCacheControl(headers, &expires))
- {
- return expires;
- }
- else
- {
- // With no expiration info, default to an hour
- const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
- F64 now = LLFrameTimer::getTotalSeconds();
- return now + DEFAULT_EXPIRES;
- }
+ F64 expires = 0.0;
+ if (expirationFromCacheControl(headers, &expires))
+ {
+ return expires;
+ }
+ else
+ {
+ // With no expiration info, default to an hour
+ const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ return now + DEFAULT_EXPIRES;
+ }
}
bool LLAvatarNameCache::expirationFromCacheControl(const LLSD& headers, F64 *expires)
{
- bool fromCacheControl = false;
- F64 now = LLFrameTimer::getTotalSeconds();
-
- // Allow the header to override the default
- std::string cache_control;
- if (headers.has(HTTP_IN_HEADER_CACHE_CONTROL))
- {
- cache_control = headers[HTTP_IN_HEADER_CACHE_CONTROL].asString();
- }
-
- if (!cache_control.empty())
- {
- S32 max_age = 0;
- if (max_age_from_cache_control(cache_control, &max_age))
- {
- *expires = now + (F64)max_age;
- fromCacheControl = true;
- }
- }
- LL_DEBUGS("AvNameCache") << "LLAvatarNameCache "
- << ( fromCacheControl ? "expires based on cache control " : "default expiration " )
- << "in " << *expires - now << " seconds"
- << LL_ENDL;
-
- return fromCacheControl;
+ bool fromCacheControl = false;
+ F64 now = LLFrameTimer::getTotalSeconds();
+
+ // Allow the header to override the default
+ std::string cache_control;
+ if (headers.has(HTTP_IN_HEADER_CACHE_CONTROL))
+ {
+ cache_control = headers[HTTP_IN_HEADER_CACHE_CONTROL].asString();
+ }
+
+ if (!cache_control.empty())
+ {
+ S32 max_age = 0;
+ if (max_age_from_cache_control(cache_control, &max_age))
+ {
+ *expires = now + (F64)max_age;
+ fromCacheControl = true;
+ }
+ }
+ LL_DEBUGS("AvNameCache") << "LLAvatarNameCache "
+ << ( fromCacheControl ? "expires based on cache control " : "default expiration " )
+ << "in " << *expires - now << " seconds"
+ << LL_ENDL;
+
+ return fromCacheControl;
}
#endif
-void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb)
-{
- mUseDisplayNamesSignal.connect(cb);
+void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb)
+{
+ mUseDisplayNamesSignal.connect(cb);
}
@@ -867,55 +867,55 @@ static const boost::char_separator<char> COMMA_SEPARATOR(",");
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
{
- // Split the string on "," to get a list of directives
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- tokenizer directives(cache_control, COMMA_SEPARATOR);
-
- tokenizer::iterator token_it = directives.begin();
- for ( ; token_it != directives.end(); ++token_it)
- {
- // Tokens may have leading or trailing whitespace
- std::string token = *token_it;
- LLStringUtil::trim(token);
-
- if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
- {
- // ...this token starts with max-age, so let's chop it up by "="
- tokenizer subtokens(token, EQUALS_SEPARATOR);
- tokenizer::iterator subtoken_it = subtokens.begin();
-
- // Must have a token
- if (subtoken_it == subtokens.end()) return false;
- std::string subtoken = *subtoken_it;
-
- // Must exactly equal "max-age"
- LLStringUtil::trim(subtoken);
- if (subtoken != MAX_AGE) return false;
-
- // Must have another token
- ++subtoken_it;
- if (subtoken_it == subtokens.end()) return false;
- subtoken = *subtoken_it;
-
- // Must be a valid integer
- // *NOTE: atoi() returns 0 for invalid values, so we have to
- // check the string first.
- // *TODO: Do servers ever send "0000" for zero? We don't handle it
- LLStringUtil::trim(subtoken);
- if (subtoken == "0")
- {
- *max_age = 0;
- return true;
- }
- S32 val = atoi( subtoken.c_str() );
- if (val > 0 && val < S32_MAX)
- {
- *max_age = val;
- return true;
- }
- return false;
- }
- }
- return false;
+ // Split the string on "," to get a list of directives
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ tokenizer directives(cache_control, COMMA_SEPARATOR);
+
+ tokenizer::iterator token_it = directives.begin();
+ for ( ; token_it != directives.end(); ++token_it)
+ {
+ // Tokens may have leading or trailing whitespace
+ std::string token = *token_it;
+ LLStringUtil::trim(token);
+
+ if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+ {
+ // ...this token starts with max-age, so let's chop it up by "="
+ tokenizer subtokens(token, EQUALS_SEPARATOR);
+ tokenizer::iterator subtoken_it = subtokens.begin();
+
+ // Must have a token
+ if (subtoken_it == subtokens.end()) return false;
+ std::string subtoken = *subtoken_it;
+
+ // Must exactly equal "max-age"
+ LLStringUtil::trim(subtoken);
+ if (subtoken != MAX_AGE) return false;
+
+ // Must have another token
+ ++subtoken_it;
+ if (subtoken_it == subtokens.end()) return false;
+ subtoken = *subtoken_it;
+
+ // Must be a valid integer
+ // *NOTE: atoi() returns 0 for invalid values, so we have to
+ // check the string first.
+ // *TODO: Do servers ever send "0000" for zero? We don't handle it
+ LLStringUtil::trim(subtoken);
+ if (subtoken == "0")
+ {
+ *max_age = 0;
+ return true;
+ }
+ S32 val = atoi( subtoken.c_str() );
+ if (val > 0 && val < S32_MAX)
+ {
+ *max_age = val;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
}
diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h
index 549d1703fa..fe51355207 100644
--- a/indra/llmessage/llavatarnamecache.h
+++ b/indra/llmessage/llavatarnamecache.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llavatarnamecache.h
* @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
* ("James Cook") from avatar UUIDs.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,7 +28,7 @@
#ifndef LLAVATARNAMECACHE_H
#define LLAVATARNAMECACHE_H
-#include "llavatarname.h" // for convenience
+#include "llavatarname.h" // for convenience
#include "llsingleton.h"
#include <boost/signals2.hpp>
#include <set>
@@ -38,71 +38,71 @@ class LLUUID;
class LLAvatarNameCache : public LLSingleton<LLAvatarNameCache>
{
- LLSINGLETON(LLAvatarNameCache);
- ~LLAvatarNameCache();
+ LLSINGLETON(LLAvatarNameCache);
+ ~LLAvatarNameCache();
public:
- typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
- typedef boost::function<void (const LLUUID id, const LLAvatarName& av_name)> account_name_changed_callback_t;
-
- // Import/export the name cache to file.
- bool importFile(std::istream& istr);
- void exportFile(std::ostream& ostr);
-
- // On the viewer, usually a simulator capabilities.
- // If empty, name cache will fall back to using legacy name lookup system.
- void setNameLookupURL(const std::string& name_lookup_url);
-
- // Do we have a valid lookup URL, i.e. are we trying to use the
- // more recent display name lookup system?
- bool hasNameLookupURL();
- void setUsePeopleAPI(bool use_api);
- bool usePeopleAPI();
-
- // Periodically makes a batch request for display names not already in
- // cache. Called once per frame.
- void idle();
-
- // If name is in cache, returns true and fills in provided LLAvatarName
- // otherwise returns false.
- static bool get(const LLUUID& agent_id, LLAvatarName *av_name);
- bool getName(const LLUUID& agent_id, LLAvatarName *av_name);
-
- // Callback types for get() below
- typedef boost::signals2::signal<
- void (const LLUUID& agent_id, const LLAvatarName& av_name)>
- callback_signal_t;
- typedef callback_signal_t::slot_type callback_slot_t;
- typedef boost::signals2::connection callback_connection_t;
-
- // Fetches name information and calls callbacks.
- // If name information is in cache, callbacks will be called immediately.
- static callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot);
- callback_connection_t getNameCallback(const LLUUID& agent_id, callback_slot_t slot);
-
- // Set display name: flips the switch and triggers the callbacks.
- void setUseDisplayNames(bool use);
-
- void setUseUsernames(bool use);
-
- void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
- void erase(const LLUUID& agent_id);
-
- // A way to find agent id by UUID, very slow, also unreliable
- // since it doesn't request names, just serch exsisting ones
- // that are likely not in cache.
- //
- // Todo: Find a way to remove this.
- // Curently this method is used for chat history and in some cases notices.
- LLUUID findIdByName(const std::string& name);
-
- /// Provide some fallback for agents that return errors.
- void handleAgentError(const LLUUID& agent_id);
-
- // Compute name expiration time from HTTP Cache-Control header,
- // or return default value, in seconds from epoch.
+ typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
+ typedef boost::function<void (const LLUUID id, const LLAvatarName& av_name)> account_name_changed_callback_t;
+
+ // Import/export the name cache to file.
+ bool importFile(std::istream& istr);
+ void exportFile(std::ostream& ostr);
+
+ // On the viewer, usually a simulator capabilities.
+ // If empty, name cache will fall back to using legacy name lookup system.
+ void setNameLookupURL(const std::string& name_lookup_url);
+
+ // Do we have a valid lookup URL, i.e. are we trying to use the
+ // more recent display name lookup system?
+ bool hasNameLookupURL();
+ void setUsePeopleAPI(bool use_api);
+ bool usePeopleAPI();
+
+ // Periodically makes a batch request for display names not already in
+ // cache. Called once per frame.
+ void idle();
+
+ // If name is in cache, returns true and fills in provided LLAvatarName
+ // otherwise returns false.
+ static bool get(const LLUUID& agent_id, LLAvatarName *av_name);
+ bool getName(const LLUUID& agent_id, LLAvatarName *av_name);
+
+ // Callback types for get() below
+ typedef boost::signals2::signal<
+ void (const LLUUID& agent_id, const LLAvatarName& av_name)>
+ callback_signal_t;
+ typedef callback_signal_t::slot_type callback_slot_t;
+ typedef boost::signals2::connection callback_connection_t;
+
+ // Fetches name information and calls callbacks.
+ // If name information is in cache, callbacks will be called immediately.
+ static callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot);
+ callback_connection_t getNameCallback(const LLUUID& agent_id, callback_slot_t slot);
+
+ // Set display name: flips the switch and triggers the callbacks.
+ void setUseDisplayNames(bool use);
+
+ void setUseUsernames(bool use);
+
+ void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
+ void erase(const LLUUID& agent_id);
+
+ // A way to find agent id by UUID, very slow, also unreliable
+ // since it doesn't request names, just serch exsisting ones
+ // that are likely not in cache.
+ //
+ // Todo: Find a way to remove this.
+ // Curently this method is used for chat history and in some cases notices.
+ LLUUID findIdByName(const std::string& name);
+
+ /// Provide some fallback for agents that return errors.
+ void handleAgentError(const LLUUID& agent_id);
+
+ // Compute name expiration time from HTTP Cache-Control header,
+ // or return default value, in seconds from epoch.
F64 nameExpirationFromHeaders(const LLSD& headers);
- void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
+ void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
void setAccountNameChangedCallback(const account_name_changed_callback_t& cb) { mAccountNameChangedCallback = cb; }
diff --git a/indra/llmessage/llblowfishcipher.cpp b/indra/llmessage/llblowfishcipher.cpp
index 949d4cc0c7..ed036e396d 100644
--- a/indra/llmessage/llblowfishcipher.cpp
+++ b/indra/llmessage/llblowfishcipher.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llblowfishcipher.cpp
* @brief Wrapper around OpenSSL Blowfish encryption algorithm.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,28 +30,28 @@
LLBlowfishCipher::LLBlowfishCipher(const U8* secret, size_t secret_size)
-: LLCipher()
+: LLCipher()
{
- llassert(secret);
+ llassert(secret);
- mSecretSize = secret_size;
- mSecret = new U8[mSecretSize];
- memcpy(mSecret, secret, mSecretSize);
+ mSecretSize = secret_size;
+ mSecret = new U8[mSecretSize];
+ memcpy(mSecret, secret, mSecretSize);
}
LLBlowfishCipher::~LLBlowfishCipher()
{
- delete [] mSecret;
- mSecret = NULL;
+ delete [] mSecret;
+ mSecret = NULL;
}
// virtual
U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
{
- if (!src || !src_len || !dst || !dst_len) return 0;
- if (src_len > dst_len) return 0;
+ if (!src || !src_len || !dst || !dst_len) return 0;
+ if (src_len > dst_len) return 0;
- // OpenSSL uses "cipher contexts" to hold encryption parameters.
+ // OpenSSL uses "cipher contexts" to hold encryption parameters.
EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
if (!context)
{
@@ -59,71 +59,71 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
return 0;
}
- // We want a blowfish cyclic block chain cipher, but need to set
- // the key length before we pass in a key, so call EncryptInit
- // first with NULLs.
- EVP_EncryptInit_ex(context, EVP_bf_cbc(), NULL, NULL, NULL);
- EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize);
-
- // Complete initialization. Per EVP_EncryptInit man page, the
- // cipher pointer must be NULL. Apparently initial_vector must
- // be 8 bytes for blowfish, as this is the block size.
+ // We want a blowfish cyclic block chain cipher, but need to set
+ // the key length before we pass in a key, so call EncryptInit
+ // first with NULLs.
+ EVP_EncryptInit_ex(context, EVP_bf_cbc(), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize);
+
+ // Complete initialization. Per EVP_EncryptInit man page, the
+ // cipher pointer must be NULL. Apparently initial_vector must
+ // be 8 bytes for blowfish, as this is the block size.
unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- EVP_EncryptInit_ex(context, NULL, NULL, mSecret, initial_vector);
+ EVP_EncryptInit_ex(context, NULL, NULL, mSecret, initial_vector);
int blocksize = EVP_CIPHER_CTX_block_size(context);
int keylen = EVP_CIPHER_CTX_key_length(context);
int iv_length = EVP_CIPHER_CTX_iv_length(context);
LL_DEBUGS() << "LLBlowfishCipher blocksize " << blocksize
- << " keylen " << keylen
- << " iv_len " << iv_length
- << LL_ENDL;
-
- int output_len = 0;
- int temp_len = 0;
- if (!EVP_EncryptUpdate(context,
- dst,
- &output_len,
- src,
- src_len))
- {
- LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << LL_ENDL;
- goto ERROR;
- }
-
- // There may be some final data left to encrypt if the input is
- // not an exact multiple of the block size.
- if (!EVP_EncryptFinal_ex(context, (unsigned char*)(dst + output_len), &temp_len))
- {
- LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << LL_ENDL;
- goto ERROR;
- }
- output_len += temp_len;
-
- EVP_CIPHER_CTX_free(context);
- return output_len;
+ << " keylen " << keylen
+ << " iv_len " << iv_length
+ << LL_ENDL;
+
+ int output_len = 0;
+ int temp_len = 0;
+ if (!EVP_EncryptUpdate(context,
+ dst,
+ &output_len,
+ src,
+ src_len))
+ {
+ LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptUpdate failure" << LL_ENDL;
+ goto ERROR;
+ }
+
+ // There may be some final data left to encrypt if the input is
+ // not an exact multiple of the block size.
+ if (!EVP_EncryptFinal_ex(context, (unsigned char*)(dst + output_len), &temp_len))
+ {
+ LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << LL_ENDL;
+ goto ERROR;
+ }
+ output_len += temp_len;
+
+ EVP_CIPHER_CTX_free(context);
+ return output_len;
ERROR:
- EVP_CIPHER_CTX_free(context);
- return 0;
+ EVP_CIPHER_CTX_free(context);
+ return 0;
}
// virtual
U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
{
- LL_ERRS() << "LLBlowfishCipher decrypt unsupported" << LL_ENDL;
- return 0;
+ LL_ERRS() << "LLBlowfishCipher decrypt unsupported" << LL_ENDL;
+ return 0;
}
// virtual
U32 LLBlowfishCipher::requiredEncryptionSpace(U32 len) const
{
- // *HACK: We know blowfish uses an 8 byte block size.
- // Oddly, sometimes EVP_Encrypt produces an extra block
- // if the input is an exact multiple of the block size.
- // So round up.
- const U32 BLOCK_SIZE = 8;
- len += BLOCK_SIZE;
- len -= (len % BLOCK_SIZE);
- return len;
+ // *HACK: We know blowfish uses an 8 byte block size.
+ // Oddly, sometimes EVP_Encrypt produces an extra block
+ // if the input is an exact multiple of the block size.
+ // So round up.
+ const U32 BLOCK_SIZE = 8;
+ len += BLOCK_SIZE;
+ len -= (len % BLOCK_SIZE);
+ return len;
}
diff --git a/indra/llmessage/llblowfishcipher.h b/indra/llmessage/llblowfishcipher.h
index 65228df11f..59d6f159c5 100644
--- a/indra/llmessage/llblowfishcipher.h
+++ b/indra/llmessage/llblowfishcipher.h
@@ -1,57 +1,57 @@
-/**
- * @file llblowfishcipher.h
- * @brief A symmetric block cipher, designed in 1993 by Bruce Schneier.
- * We use it because it has an 8 byte block size, allowing encryption of
- * two UUIDs and a timestamp (16x2 + 4 = 36 bytes) with only 40 bytes of
- * output. AES has a block size of 32 bytes, so this would require 64 bytes.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LLBLOWFISHCIPHER_H
-#define LLBLOWFISHCIPHER_H
-
-#include "llcipher.h"
-
-
-class LLBlowfishCipher : public LLCipher
-{
-public:
- // Secret may be up to 56 bytes in length per Blowfish spec.
- LLBlowfishCipher(const U8* secret, size_t secret_size);
- virtual ~LLBlowfishCipher();
-
- // See llcipher.h for documentation.
- /*virtual*/ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
- /*virtual*/ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
- /*virtual*/ U32 requiredEncryptionSpace(U32 src_len) const;
-
-#ifdef _DEBUG
- static bool testHarness();
-#endif
-
-private:
- U8* mSecret;
- size_t mSecretSize;
-};
-
-#endif // LL_LLCRYPTO_H
+/**
+ * @file llblowfishcipher.h
+ * @brief A symmetric block cipher, designed in 1993 by Bruce Schneier.
+ * We use it because it has an 8 byte block size, allowing encryption of
+ * two UUIDs and a timestamp (16x2 + 4 = 36 bytes) with only 40 bytes of
+ * output. AES has a block size of 32 bytes, so this would require 64 bytes.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLBLOWFISHCIPHER_H
+#define LLBLOWFISHCIPHER_H
+
+#include "llcipher.h"
+
+
+class LLBlowfishCipher : public LLCipher
+{
+public:
+ // Secret may be up to 56 bytes in length per Blowfish spec.
+ LLBlowfishCipher(const U8* secret, size_t secret_size);
+ virtual ~LLBlowfishCipher();
+
+ // See llcipher.h for documentation.
+ /*virtual*/ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
+ /*virtual*/ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
+ /*virtual*/ U32 requiredEncryptionSpace(U32 src_len) const;
+
+#ifdef _DEBUG
+ static bool testHarness();
+#endif
+
+private:
+ U8* mSecret;
+ size_t mSecretSize;
+};
+
+#endif // LL_LLCRYPTO_H
diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp
index cfe38605ad..dc7115b167 100644
--- a/indra/llmessage/llbuffer.cpp
+++ b/indra/llmessage/llbuffer.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbuffer.cpp
* @author Phoenix
* @date 2005-09-20
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,20 +37,20 @@
#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED() llassert(!mMutexp || mMutexp->isSelfLocked())
-/**
+/**
* LLSegment
*/
LLSegment::LLSegment() :
- mChannel(0),
- mData(NULL),
- mSize(0)
+ mChannel(0),
+ mData(NULL),
+ mSize(0)
{
}
LLSegment::LLSegment(S32 channel, U8* data, S32 data_len) :
- mChannel(channel),
- mData(data),
- mSize(data_len)
+ mChannel(channel),
+ mData(data),
+ mSize(data_len)
{
}
@@ -60,849 +60,849 @@ LLSegment::~LLSegment()
bool LLSegment::isOnChannel(S32 channel) const
{
- return (mChannel == channel);
+ return (mChannel == channel);
}
S32 LLSegment::getChannel() const
{
- return mChannel;
+ return mChannel;
}
void LLSegment::setChannel(S32 channel)
{
- mChannel = channel;
+ mChannel = channel;
}
U8* LLSegment::data() const
{
- return mData;
+ return mData;
}
S32 LLSegment::size() const
{
- return mSize;
+ return mSize;
}
bool LLSegment::operator==(const LLSegment& rhs) const
{
- if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
- {
- return false;
- }
- return true;
+ if((mData != rhs.mData)||(mSize != rhs.mSize)||(mChannel != rhs.mChannel))
+ {
+ return false;
+ }
+ return true;
}
-/**
+/**
* LLHeapBuffer
*/
LLHeapBuffer::LLHeapBuffer() :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
- allocate(DEFAULT_HEAP_BUFFER_SIZE);
+ const S32 DEFAULT_HEAP_BUFFER_SIZE = 16384;
+ allocate(DEFAULT_HEAP_BUFFER_SIZE);
}
LLHeapBuffer::LLHeapBuffer(S32 size) :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- allocate(size);
+ allocate(size);
}
LLHeapBuffer::LLHeapBuffer(const U8* src, S32 len) :
- mBuffer(NULL),
- mSize(0),
- mNextFree(NULL),
- mReclaimedBytes(0)
+ mBuffer(NULL),
+ mSize(0),
+ mNextFree(NULL),
+ mReclaimedBytes(0)
{
- if((len > 0) && src)
- {
- allocate(len);
- if(mBuffer)
- {
- memcpy(mBuffer, src, len); /*Flawfinder: ignore*/
- }
- }
+ if((len > 0) && src)
+ {
+ allocate(len);
+ if(mBuffer)
+ {
+ memcpy(mBuffer, src, len); /*Flawfinder: ignore*/
+ }
+ }
}
// virtual
LLHeapBuffer::~LLHeapBuffer()
{
- delete[] mBuffer;
- mBuffer = NULL;
- mSize = 0;
- mNextFree = NULL;
+ delete[] mBuffer;
+ mBuffer = NULL;
+ mSize = 0;
+ mNextFree = NULL;
}
S32 LLHeapBuffer::bytesLeft() const
{
- return (mSize - (mNextFree - mBuffer));
+ return (mSize - (mNextFree - mBuffer));
}
// virtual
bool LLHeapBuffer::createSegment(
- S32 channel,
- S32 size,
- LLSegment& segment)
+ S32 channel,
+ S32 size,
+ LLSegment& segment)
{
- // get actual size of the segment.
- S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
+ // get actual size of the segment.
+ S32 actual_size = llmin(size, (mSize - S32(mNextFree - mBuffer)));
- // bail if we cannot build a valid segment
- if(actual_size <= 0)
- {
- return false;
- }
+ // bail if we cannot build a valid segment
+ if(actual_size <= 0)
+ {
+ return false;
+ }
- // Yay, we're done.
- segment = LLSegment(channel, mNextFree, actual_size);
- mNextFree += actual_size;
- return true;
+ // Yay, we're done.
+ segment = LLSegment(channel, mNextFree, actual_size);
+ mNextFree += actual_size;
+ return true;
}
// virtual
bool LLHeapBuffer::reclaimSegment(const LLSegment& segment)
{
- if(containsSegment(segment))
- {
- mReclaimedBytes += segment.size();
- if(mReclaimedBytes == mSize)
- {
- // We have reclaimed all of the memory from this
- // buffer. Therefore, we can reset the mNextFree to the
- // start of the buffer, and reset the reclaimed bytes.
- mReclaimedBytes = 0;
- mNextFree = mBuffer;
- }
- else if(mReclaimedBytes > mSize)
- {
- LL_WARNS() << "LLHeapBuffer reclaimed more memory than allocated."
- << " This is probably programmer error." << LL_ENDL;
- }
- return true;
- }
- return false;
+ if(containsSegment(segment))
+ {
+ mReclaimedBytes += segment.size();
+ if(mReclaimedBytes == mSize)
+ {
+ // We have reclaimed all of the memory from this
+ // buffer. Therefore, we can reset the mNextFree to the
+ // start of the buffer, and reset the reclaimed bytes.
+ mReclaimedBytes = 0;
+ mNextFree = mBuffer;
+ }
+ else if(mReclaimedBytes > mSize)
+ {
+ LL_WARNS() << "LLHeapBuffer reclaimed more memory than allocated."
+ << " This is probably programmer error." << LL_ENDL;
+ }
+ return true;
+ }
+ return false;
}
// virtual
bool LLHeapBuffer::containsSegment(const LLSegment& segment) const
{
- // *NOTE: this check is fairly simple because heap buffers are
- // simple contiguous chunks of heap memory.
- if((mBuffer > segment.data())
- || ((mBuffer + mSize) < (segment.data() + segment.size())))
- {
- return false;
- }
- return true;
+ // *NOTE: this check is fairly simple because heap buffers are
+ // simple contiguous chunks of heap memory.
+ if((mBuffer > segment.data())
+ || ((mBuffer + mSize) < (segment.data() + segment.size())))
+ {
+ return false;
+ }
+ return true;
}
void LLHeapBuffer::allocate(S32 size)
{
- mReclaimedBytes = 0;
- mBuffer = new U8[size];
- if(mBuffer)
- {
- mSize = size;
- mNextFree = mBuffer;
- }
+ mReclaimedBytes = 0;
+ mBuffer = new U8[size];
+ if(mBuffer)
+ {
+ mSize = size;
+ mNextFree = mBuffer;
+ }
}
-/**
+/**
* LLBufferArray
*/
LLBufferArray::LLBufferArray() :
- mNextBaseChannel(0),
- mMutexp(NULL)
+ mNextBaseChannel(0),
+ mMutexp(NULL)
{
}
LLBufferArray::~LLBufferArray()
{
- std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
- mBuffers.clear();
- delete mMutexp;
+ std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer());
+ mBuffers.clear();
+ delete mMutexp;
}
// static
LLChannelDescriptors LLBufferArray::makeChannelConsumer(
- const LLChannelDescriptors& channels)
+ const LLChannelDescriptors& channels)
{
- LLChannelDescriptors rv(channels.out());
- return rv;
+ LLChannelDescriptors rv(channels.out());
+ return rv;
}
void LLBufferArray::lock()
{
- if(mMutexp)
- {
- mMutexp->lock() ;
- }
+ if(mMutexp)
+ {
+ mMutexp->lock() ;
+ }
}
void LLBufferArray::unlock()
{
- if(mMutexp)
- {
- mMutexp->unlock() ;
- }
+ if(mMutexp)
+ {
+ mMutexp->unlock() ;
+ }
}
LLMutex* LLBufferArray::getMutex()
{
- return mMutexp ;
+ return mMutexp ;
}
void LLBufferArray::setThreaded(bool threaded)
{
- if(threaded)
- {
- if(!mMutexp)
- {
- mMutexp = new LLMutex();
- }
- }
- else
- {
- if(mMutexp)
- {
- delete mMutexp ;
- mMutexp = NULL ;
- }
- }
+ if(threaded)
+ {
+ if(!mMutexp)
+ {
+ mMutexp = new LLMutex();
+ }
+ }
+ else
+ {
+ if(mMutexp)
+ {
+ delete mMutexp ;
+ mMutexp = NULL ;
+ }
+ }
}
LLChannelDescriptors LLBufferArray::nextChannel()
{
- LLChannelDescriptors rv(mNextBaseChannel++);
- return rv;
+ LLChannelDescriptors rv(mNextBaseChannel++);
+ return rv;
}
//mMutexp should be locked before calling this.
S32 LLBufferArray::capacity() const
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- S32 total = 0;
- const_buffer_iterator_t iter = mBuffers.begin();
- const_buffer_iterator_t end = mBuffers.end();
- for(; iter != end; ++iter)
- {
- total += (*iter)->capacity();
- }
- return total;
+ S32 total = 0;
+ const_buffer_iterator_t iter = mBuffers.begin();
+ const_buffer_iterator_t end = mBuffers.end();
+ for(; iter != end; ++iter)
+ {
+ total += (*iter)->capacity();
+ }
+ return total;
}
bool LLBufferArray::append(S32 channel, const U8* src, S32 len)
{
- LLMutexLock lock(mMutexp) ;
+ LLMutexLock lock(mMutexp) ;
- std::vector<LLSegment> segments;
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(mSegments.end(), segments.begin(), segments.end());
- return true;
- }
- return false;
+ std::vector<LLSegment> segments;
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(mSegments.end(), segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- std::vector<LLSegment> segments;
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
- return true;
- }
- return false;
+ std::vector<LLSegment> segments;
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(mSegments.begin(), segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
bool LLBufferArray::insertAfter(
- segment_iterator_t segment,
- S32 channel,
- const U8* src,
- S32 len)
-{
- std::vector<LLSegment> segments;
-
- LLMutexLock lock(mMutexp) ;
- if(mSegments.end() != segment)
- {
- ++segment;
- }
- if(copyIntoBuffers(channel, src, len, segments))
- {
- mSegments.insert(segment, segments.begin(), segments.end());
- return true;
- }
- return false;
+ segment_iterator_t segment,
+ S32 channel,
+ const U8* src,
+ S32 len)
+{
+ std::vector<LLSegment> segments;
+
+ LLMutexLock lock(mMutexp) ;
+ if(mSegments.end() != segment)
+ {
+ ++segment;
+ }
+ if(copyIntoBuffers(channel, src, len, segments))
+ {
+ mSegments.insert(segment, segments.begin(), segments.end());
+ return true;
+ }
+ return false;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
-
- segment_iterator_t end = mSegments.end();
- segment_iterator_t it = getSegment(address);
- if(it == end)
- {
- return end;
- }
-
- // We have the location and the segment.
- U8* base = (*it).data();
- S32 size = (*it).size();
- if(address == (base + size))
- {
- // No need to split, since this is the last byte of the
- // segment. We do not want to have zero length segments, since
- // that will only incur processing overhead with no advantage.
- return it;
- }
- S32 channel = (*it).getChannel();
- LLSegment segment1(channel, base, (address - base) + 1);
- *it = segment1;
- segment_iterator_t rv = it;
- ++it;
- LLSegment segment2(channel, address + 1, size - (address - base) - 1);
- mSegments.insert(it, segment2);
- return rv;
-}
-
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
+ segment_iterator_t end = mSegments.end();
+ segment_iterator_t it = getSegment(address);
+ if(it == end)
+ {
+ return end;
+ }
+
+ // We have the location and the segment.
+ U8* base = (*it).data();
+ S32 size = (*it).size();
+ if(address == (base + size))
+ {
+ // No need to split, since this is the last byte of the
+ // segment. We do not want to have zero length segments, since
+ // that will only incur processing overhead with no advantage.
+ return it;
+ }
+ S32 channel = (*it).getChannel();
+ LLSegment segment1(channel, base, (address - base) + 1);
+ *it = segment1;
+ segment_iterator_t rv = it;
+ ++it;
+ LLSegment segment2(channel, address + 1, size - (address - base) - 1);
+ mSegments.insert(it, segment2);
+ return rv;
+}
+
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- return mSegments.begin();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ return mSegments.begin();
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::endSegment()
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- return mSegments.end();
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ return mSegments.end();
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(
- U8* address,
- LLSegment& segment)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- segment_iterator_t rv = mSegments.begin();
- segment_iterator_t end = mSegments.end();
- if(!address)
- {
- if(rv != end)
- {
- segment = (*rv);
- }
- }
- else
- {
- // we have an address - find the segment it is in.
- for( ; rv != end; ++rv)
- {
- if((address >= (*rv).data())
- && (address < ((*rv).data() + (*rv).size())))
- {
- if((++address) < ((*rv).data() + (*rv).size()))
- {
- // it's in this segment - construct an appropriate
- // sub-segment.
- segment = LLSegment(
- (*rv).getChannel(),
- address,
- (*rv).size() - (address - (*rv).data()));
- }
- else
- {
- ++rv;
- if(rv != end)
- {
- segment = (*rv);
- }
- }
- break;
- }
- }
- }
- if(rv == end)
- {
- segment = LLSegment();
- }
- return rv;
+ U8* address,
+ LLSegment& segment)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ segment_iterator_t rv = mSegments.begin();
+ segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ if(rv != end)
+ {
+ segment = (*rv);
+ }
+ }
+ else
+ {
+ // we have an address - find the segment it is in.
+ for( ; rv != end; ++rv)
+ {
+ if((address >= (*rv).data())
+ && (address < ((*rv).data() + (*rv).size())))
+ {
+ if((++address) < ((*rv).data() + (*rv).size()))
+ {
+ // it's in this segment - construct an appropriate
+ // sub-segment.
+ segment = LLSegment(
+ (*rv).getChannel(),
+ address,
+ (*rv).size() - (address - (*rv).data()));
+ }
+ else
+ {
+ ++rv;
+ if(rv != end)
+ {
+ segment = (*rv);
+ }
+ }
+ break;
+ }
+ }
+ }
+ if(rv == end)
+ {
+ segment = LLSegment();
+ }
+ return rv;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- segment_iterator_t end = mSegments.end();
- if(!address)
- {
- return end;
- }
- segment_iterator_t it = mSegments.begin();
- for( ; it != end; ++it)
- {
- if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
- {
- // found it.
- return it;
- }
- }
- return end;
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ return end;
+ }
+ segment_iterator_t it = mSegments.begin();
+ for( ; it != end; ++it)
+ {
+ if((address >= (*it).data())&&(address < (*it).data() + (*it).size()))
+ {
+ // found it.
+ return it;
+ }
+ }
+ return end;
}
//mMutexp should be locked before calling this.
LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(
- U8* address) const
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- const_segment_iterator_t end = mSegments.end();
- if(!address)
- {
- return end;
- }
- const_segment_iterator_t it = mSegments.begin();
- for( ; it != end; ++it)
- {
- if((address >= (*it).data())
- && (address < (*it).data() + (*it).size()))
- {
- // found it.
- return it;
- }
- }
- return end;
+ U8* address) const
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ const_segment_iterator_t end = mSegments.end();
+ if(!address)
+ {
+ return end;
+ }
+ const_segment_iterator_t it = mSegments.begin();
+ for( ; it != end; ++it)
+ {
+ if((address >= (*it).data())
+ && (address < (*it).data() + (*it).size()))
+ {
+ // found it.
+ return it;
+ }
+ }
+ return end;
}
/*
-U8* LLBufferArray::getAddressAfter(U8* address)
-{
- U8* rv = NULL;
- segment_iterator_t it = getSegment(address);
- segment_iterator_t end = mSegments.end();
- if(it != end)
- {
- if(++address < ((*it).data() + (*it).size()))
- {
- // it's in the same segment
- rv = address;
- }
- else
- {
- // it's in the next segment
- if(++it != end)
- {
- rv = (*it).data();
- }
- }
- }
- return rv;
+U8* LLBufferArray::getAddressAfter(U8* address)
+{
+ U8* rv = NULL;
+ segment_iterator_t it = getSegment(address);
+ segment_iterator_t end = mSegments.end();
+ if(it != end)
+ {
+ if(++address < ((*it).data() + (*it).size()))
+ {
+ // it's in the same segment
+ rv = address;
+ }
+ else
+ {
+ // it's in the next segment
+ if(++it != end)
+ {
+ rv = (*it).data();
+ }
+ }
+ }
+ return rv;
}
*/
S32 LLBufferArray::countAfter(S32 channel, U8* start) const
{
- S32 count = 0;
- S32 offset = 0;
- const_segment_iterator_t it;
-
- LLMutexLock lock(mMutexp) ;
- const_segment_iterator_t end = mSegments.end();
- if(start)
- {
- it = getSegment(start);
- if(it == end)
- {
- return count;
- }
- if(++start < ((*it).data() + (*it).size()))
- {
- // it's in the same segment
- offset = start - (*it).data();
- }
- else if(++it == end)
- {
- // it's in the next segment
- return count;
- }
- }
- else
- {
- it = mSegments.begin();
- }
- while(it != end)
- {
- if((*it).isOnChannel(channel))
- {
- count += (*it).size() - offset;
- }
- offset = 0;
- ++it;
- }
- return count;
+ S32 count = 0;
+ S32 offset = 0;
+ const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
+ const_segment_iterator_t end = mSegments.end();
+ if(start)
+ {
+ it = getSegment(start);
+ if(it == end)
+ {
+ return count;
+ }
+ if(++start < ((*it).data() + (*it).size()))
+ {
+ // it's in the same segment
+ offset = start - (*it).data();
+ }
+ else if(++it == end)
+ {
+ // it's in the next segment
+ return count;
+ }
+ }
+ else
+ {
+ it = mSegments.begin();
+ }
+ while(it != end)
+ {
+ if((*it).isOnChannel(channel))
+ {
+ count += (*it).size() - offset;
+ }
+ offset = 0;
+ ++it;
+ }
+ return count;
}
U8* LLBufferArray::readAfter(
- S32 channel,
- U8* start,
- U8* dest,
- S32& len) const
-{
- U8* rv = start;
- if(!dest || len <= 0)
- {
- return rv;
- }
- S32 bytes_left = len;
- len = 0;
- S32 bytes_to_copy = 0;
- const_segment_iterator_t it;
-
- LLMutexLock lock(mMutexp) ;
- const_segment_iterator_t end = mSegments.end();
- if(start)
- {
- it = getSegment(start);
- if(it == end)
- {
- return rv;
- }
- if((++start < ((*it).data() + (*it).size()))
- && (*it).isOnChannel(channel))
- {
- // copy the data out of this segment
- S32 bytes_in_segment = (*it).size() - (start - (*it).data());
- bytes_to_copy = llmin(bytes_left, bytes_in_segment);
- memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/
- len += bytes_to_copy;
- bytes_left -= bytes_to_copy;
- rv = start + bytes_to_copy - 1;
- ++it;
- }
- else
- {
- ++it;
- }
- }
- else
- {
- it = mSegments.begin();
- }
- while(bytes_left && (it != end))
- {
- if(!((*it).isOnChannel(channel)))
- {
- ++it;
- continue;
- }
- bytes_to_copy = llmin(bytes_left, (*it).size());
- memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/
- len += bytes_to_copy;
- bytes_left -= bytes_to_copy;
- rv = (*it).data() + bytes_to_copy - 1;
- ++it;
- }
- return rv;
+ S32 channel,
+ U8* start,
+ U8* dest,
+ S32& len) const
+{
+ U8* rv = start;
+ if(!dest || len <= 0)
+ {
+ return rv;
+ }
+ S32 bytes_left = len;
+ len = 0;
+ S32 bytes_to_copy = 0;
+ const_segment_iterator_t it;
+
+ LLMutexLock lock(mMutexp) ;
+ const_segment_iterator_t end = mSegments.end();
+ if(start)
+ {
+ it = getSegment(start);
+ if(it == end)
+ {
+ return rv;
+ }
+ if((++start < ((*it).data() + (*it).size()))
+ && (*it).isOnChannel(channel))
+ {
+ // copy the data out of this segment
+ S32 bytes_in_segment = (*it).size() - (start - (*it).data());
+ bytes_to_copy = llmin(bytes_left, bytes_in_segment);
+ memcpy(dest, start, bytes_to_copy); /*Flawfinder: ignore*/
+ len += bytes_to_copy;
+ bytes_left -= bytes_to_copy;
+ rv = start + bytes_to_copy - 1;
+ ++it;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+ else
+ {
+ it = mSegments.begin();
+ }
+ while(bytes_left && (it != end))
+ {
+ if(!((*it).isOnChannel(channel)))
+ {
+ ++it;
+ continue;
+ }
+ bytes_to_copy = llmin(bytes_left, (*it).size());
+ memcpy(dest + len, (*it).data(), bytes_to_copy); /*Flawfinder: ignore*/
+ len += bytes_to_copy;
+ bytes_left -= bytes_to_copy;
+ rv = (*it).data() + bytes_to_copy - 1;
+ ++it;
+ }
+ return rv;
}
U8* LLBufferArray::seek(
- S32 channel,
- U8* start,
- S32 delta) const
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- const_segment_iterator_t it;
- const_segment_iterator_t end = mSegments.end();
- U8* rv = start;
- if(0 == delta)
- {
- if((U8*)npos == start)
- {
- // someone is looking for end of data.
- segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
- segment_list_t::const_reverse_iterator rend = mSegments.rend();
- while(rit != rend)
- {
- if(!((*rit).isOnChannel(channel)))
- {
- ++rit;
- continue;
- }
- rv = (*rit).data() + (*rit).size();
- break;
- }
- }
- else if(start)
- {
- // This is sort of a weird case - check if zero bytes away
- // from current position is on channel and return start if
- // that is true. Otherwise, return NULL.
- it = getSegment(start);
- if((it == end) || !(*it).isOnChannel(channel))
- {
- rv = NULL;
- }
- }
- else
- {
- // Start is NULL, so return the very first byte on the
- // channel, or NULL.
- it = mSegments.begin();
- while((it != end) && !(*it).isOnChannel(channel))
- {
- ++it;
- }
- if(it != end)
- {
- rv = (*it).data();
- }
- }
- return rv;
- }
- if(start)
- {
- it = getSegment(start);
- if((it != end) && (*it).isOnChannel(channel))
- {
- if(delta > 0)
- {
- S32 bytes_in_segment = (*it).size() - (start - (*it).data());
- S32 local_delta = llmin(delta, bytes_in_segment);
- rv += local_delta;
- delta -= local_delta;
- ++it;
- }
- else
- {
- S32 bytes_in_segment = start - (*it).data();
- S32 local_delta = llmin(llabs(delta), bytes_in_segment);
- rv -= local_delta;
- delta += local_delta;
- }
- }
- }
- else if(delta < 0)
- {
- // start is NULL, and delta indicates seeking backwards -
- // return NULL.
- return NULL;
- }
- else
- {
- // start is NULL and delta > 0
- it = mSegments.begin();
- }
- if(delta > 0)
- {
- // At this point, we have an iterator into the segments, and
- // are seeking forward until delta is zero or we run out
- while(delta && (it != end))
- {
- if(!((*it).isOnChannel(channel)))
- {
- ++it;
- continue;
- }
- if(delta <= (*it).size())
- {
- // it's in this segment
- rv = (*it).data() + delta;
- }
- delta -= (*it).size();
- ++it;
- }
- if(delta && (it == end))
- {
- // Whoops - sought past end.
- rv = NULL;
- }
- }
- else //if(delta < 0)
- {
- // We are at the beginning of a segment, and need to search
- // backwards.
- segment_list_t::const_reverse_iterator rit(it);
- segment_list_t::const_reverse_iterator rend = mSegments.rend();
- while(delta && (rit != rend))
- {
- if(!((*rit).isOnChannel(channel)))
- {
- ++rit;
- continue;
- }
- if(llabs(delta) <= (*rit).size())
- {
- // it's in this segment.
- rv = (*rit).data() + (*rit).size() + delta;
- delta = 0;
- }
- else
- {
- delta += (*rit).size();
- }
- ++rit;
- }
- if(delta && (rit == rend))
- {
- // sought past the beginning.
- rv = NULL;
- }
- }
- return rv;
+ S32 channel,
+ U8* start,
+ S32 delta) const
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ const_segment_iterator_t it;
+ const_segment_iterator_t end = mSegments.end();
+ U8* rv = start;
+ if(0 == delta)
+ {
+ if((U8*)npos == start)
+ {
+ // someone is looking for end of data.
+ segment_list_t::const_reverse_iterator rit = mSegments.rbegin();
+ segment_list_t::const_reverse_iterator rend = mSegments.rend();
+ while(rit != rend)
+ {
+ if(!((*rit).isOnChannel(channel)))
+ {
+ ++rit;
+ continue;
+ }
+ rv = (*rit).data() + (*rit).size();
+ break;
+ }
+ }
+ else if(start)
+ {
+ // This is sort of a weird case - check if zero bytes away
+ // from current position is on channel and return start if
+ // that is true. Otherwise, return NULL.
+ it = getSegment(start);
+ if((it == end) || !(*it).isOnChannel(channel))
+ {
+ rv = NULL;
+ }
+ }
+ else
+ {
+ // Start is NULL, so return the very first byte on the
+ // channel, or NULL.
+ it = mSegments.begin();
+ while((it != end) && !(*it).isOnChannel(channel))
+ {
+ ++it;
+ }
+ if(it != end)
+ {
+ rv = (*it).data();
+ }
+ }
+ return rv;
+ }
+ if(start)
+ {
+ it = getSegment(start);
+ if((it != end) && (*it).isOnChannel(channel))
+ {
+ if(delta > 0)
+ {
+ S32 bytes_in_segment = (*it).size() - (start - (*it).data());
+ S32 local_delta = llmin(delta, bytes_in_segment);
+ rv += local_delta;
+ delta -= local_delta;
+ ++it;
+ }
+ else
+ {
+ S32 bytes_in_segment = start - (*it).data();
+ S32 local_delta = llmin(llabs(delta), bytes_in_segment);
+ rv -= local_delta;
+ delta += local_delta;
+ }
+ }
+ }
+ else if(delta < 0)
+ {
+ // start is NULL, and delta indicates seeking backwards -
+ // return NULL.
+ return NULL;
+ }
+ else
+ {
+ // start is NULL and delta > 0
+ it = mSegments.begin();
+ }
+ if(delta > 0)
+ {
+ // At this point, we have an iterator into the segments, and
+ // are seeking forward until delta is zero or we run out
+ while(delta && (it != end))
+ {
+ if(!((*it).isOnChannel(channel)))
+ {
+ ++it;
+ continue;
+ }
+ if(delta <= (*it).size())
+ {
+ // it's in this segment
+ rv = (*it).data() + delta;
+ }
+ delta -= (*it).size();
+ ++it;
+ }
+ if(delta && (it == end))
+ {
+ // Whoops - sought past end.
+ rv = NULL;
+ }
+ }
+ else //if(delta < 0)
+ {
+ // We are at the beginning of a segment, and need to search
+ // backwards.
+ segment_list_t::const_reverse_iterator rit(it);
+ segment_list_t::const_reverse_iterator rend = mSegments.rend();
+ while(delta && (rit != rend))
+ {
+ if(!((*rit).isOnChannel(channel)))
+ {
+ ++rit;
+ continue;
+ }
+ if(llabs(delta) <= (*rit).size())
+ {
+ // it's in this segment.
+ rv = (*rit).data() + (*rit).size() + delta;
+ delta = 0;
+ }
+ else
+ {
+ delta += (*rit).size();
+ }
+ ++rit;
+ }
+ if(delta && (rit == rend))
+ {
+ // sought past the beginning.
+ rv = NULL;
+ }
+ }
+ return rv;
}
//test use only
bool LLBufferArray::takeContents(LLBufferArray& source)
{
- LLMutexLock lock(mMutexp);
- source.lock();
+ LLMutexLock lock(mMutexp);
+ source.lock();
- std::copy(
- source.mBuffers.begin(),
- source.mBuffers.end(),
- std::back_insert_iterator<buffer_list_t>(mBuffers));
- source.mBuffers.clear();
- std::copy(
- source.mSegments.begin(),
- source.mSegments.end(),
- std::back_insert_iterator<segment_list_t>(mSegments));
- source.mSegments.clear();
- source.mNextBaseChannel = 0;
- source.unlock();
+ std::copy(
+ source.mBuffers.begin(),
+ source.mBuffers.end(),
+ std::back_insert_iterator<buffer_list_t>(mBuffers));
+ source.mBuffers.clear();
+ std::copy(
+ source.mSegments.begin(),
+ source.mSegments.end(),
+ std::back_insert_iterator<segment_list_t>(mSegments));
+ source.mSegments.clear();
+ source.mNextBaseChannel = 0;
+ source.unlock();
- return true;
+ return true;
}
//mMutexp should be locked before calling this.
LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(
- S32 channel,
- S32 len)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- // start at the end of the buffers, because it is the most likely
- // to have free space.
- LLSegment segment;
- buffer_list_t::reverse_iterator it = mBuffers.rbegin();
- buffer_list_t::reverse_iterator end = mBuffers.rend();
- bool made_segment = false;
- for(; it != end; ++it)
- {
- if((*it)->createSegment(channel, len, segment))
- {
- made_segment = true;
- break;
- }
- }
- segment_iterator_t send = mSegments.end();
- if(!made_segment)
- {
- LLBuffer* buf = new LLHeapBuffer;
- mBuffers.push_back(buf);
- if(!buf->createSegment(channel, len, segment))
- {
- // failed. this should never happen.
- return send;
- }
- }
-
- // store and return the newly made segment
- mSegments.insert(send, segment);
- std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
- ++rv;
- send = rv.base();
- return send;
+ S32 channel,
+ S32 len)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ // start at the end of the buffers, because it is the most likely
+ // to have free space.
+ LLSegment segment;
+ buffer_list_t::reverse_iterator it = mBuffers.rbegin();
+ buffer_list_t::reverse_iterator end = mBuffers.rend();
+ bool made_segment = false;
+ for(; it != end; ++it)
+ {
+ if((*it)->createSegment(channel, len, segment))
+ {
+ made_segment = true;
+ break;
+ }
+ }
+ segment_iterator_t send = mSegments.end();
+ if(!made_segment)
+ {
+ LLBuffer* buf = new LLHeapBuffer;
+ mBuffers.push_back(buf);
+ if(!buf->createSegment(channel, len, segment))
+ {
+ // failed. this should never happen.
+ return send;
+ }
+ }
+
+ // store and return the newly made segment
+ mSegments.insert(send, segment);
+ std::list<LLSegment>::reverse_iterator rv = mSegments.rbegin();
+ ++rv;
+ send = rv.base();
+ return send;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)
{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
-
- // Find out which buffer contains the segment, and if it is found,
- // ask it to reclaim the memory.
- bool rv = false;
- LLSegment segment(*erase_iter);
- buffer_iterator_t iter = mBuffers.begin();
- buffer_iterator_t end = mBuffers.end();
- for(; iter != end; ++iter)
- {
- // We can safely call reclaimSegment on every buffer, and once
- // it returns true, the segment was found.
- if((*iter)->reclaimSegment(segment))
- {
- rv = true;
- break;
- }
- }
-
- // No need to get the return value since we are not interested in
- // the interator retured by the call.
- (void)mSegments.erase(erase_iter);
- return rv;
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+
+ // Find out which buffer contains the segment, and if it is found,
+ // ask it to reclaim the memory.
+ bool rv = false;
+ LLSegment segment(*erase_iter);
+ buffer_iterator_t iter = mBuffers.begin();
+ buffer_iterator_t end = mBuffers.end();
+ for(; iter != end; ++iter)
+ {
+ // We can safely call reclaimSegment on every buffer, and once
+ // it returns true, the segment was found.
+ if((*iter)->reclaimSegment(segment))
+ {
+ rv = true;
+ break;
+ }
+ }
+
+ // No need to get the return value since we are not interested in
+ // the interator retured by the call.
+ (void)mSegments.erase(erase_iter);
+ return rv;
}
//mMutexp should be locked before calling this.
bool LLBufferArray::copyIntoBuffers(
- S32 channel,
- const U8* src,
- S32 len,
- std::vector<LLSegment>& segments)
-{
- ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
- if(!src || !len) return false;
- S32 copied = 0;
- LLSegment segment;
- buffer_iterator_t it = mBuffers.begin();
- buffer_iterator_t end = mBuffers.end();
- for(; it != end;)
- {
- if(!(*it)->createSegment(channel, len, segment))
- {
- ++it;
- continue;
- }
- segments.push_back(segment);
- S32 bytes = llmin(segment.size(), len);
- memcpy(segment.data(), src + copied, bytes); /* Flawfinder: Ignore */
- copied += bytes;
- len -= bytes;
- if(0 == len)
- {
- break;
- }
- }
- while(len)
- {
- LLBuffer* buf = new LLHeapBuffer;
- mBuffers.push_back(buf);
- if(!buf->createSegment(channel, len, segment))
- {
- // this totally failed - bail. This is the weird corner
- // case were we 'leak' memory. No worries about an actual
- // leak - we will still reclaim the memory later, but this
- // particular buffer array is hosed for some reason.
- // This should never happen.
- return false;
- }
- segments.push_back(segment);
- memcpy(segment.data(), src + copied, segment.size()); /*Flawfinder: ignore*/
- copied += segment.size();
- len -= segment.size();
- }
- return true;
+ S32 channel,
+ const U8* src,
+ S32 len,
+ std::vector<LLSegment>& segments)
+{
+ ASSERT_LLBUFFERARRAY_MUTEX_LOCKED();
+ if(!src || !len) return false;
+ S32 copied = 0;
+ LLSegment segment;
+ buffer_iterator_t it = mBuffers.begin();
+ buffer_iterator_t end = mBuffers.end();
+ for(; it != end;)
+ {
+ if(!(*it)->createSegment(channel, len, segment))
+ {
+ ++it;
+ continue;
+ }
+ segments.push_back(segment);
+ S32 bytes = llmin(segment.size(), len);
+ memcpy(segment.data(), src + copied, bytes); /* Flawfinder: Ignore */
+ copied += bytes;
+ len -= bytes;
+ if(0 == len)
+ {
+ break;
+ }
+ }
+ while(len)
+ {
+ LLBuffer* buf = new LLHeapBuffer;
+ mBuffers.push_back(buf);
+ if(!buf->createSegment(channel, len, segment))
+ {
+ // this totally failed - bail. This is the weird corner
+ // case were we 'leak' memory. No worries about an actual
+ // leak - we will still reclaim the memory later, but this
+ // particular buffer array is hosed for some reason.
+ // This should never happen.
+ return false;
+ }
+ segments.push_back(segment);
+ memcpy(segment.data(), src + copied, segment.size()); /*Flawfinder: ignore*/
+ copied += segment.size();
+ len -= segment.size();
+ }
+ return true;
}
diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h
index ccdb9fa7ee..89229ea9d1 100644
--- a/indra/llmessage/llbuffer.h
+++ b/indra/llmessage/llbuffer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbuffer.h
* @author Phoenix
* @date 2005-09-20
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,26 +40,26 @@
#include <vector>
class LLMutex;
-/**
+/**
* @class LLChannelDescriptors
* @brief A way simple interface to accesss channels inside a buffer
*/
class LLChannelDescriptors
{
public:
- // enumeration for segmenting the channel information
- enum { E_CHANNEL_COUNT = 3 };
- LLChannelDescriptors() : mBaseChannel(0) {}
- explicit LLChannelDescriptors(S32 base) : mBaseChannel(base) {}
- S32 in() const { return mBaseChannel; }
- S32 out() const { return mBaseChannel + 1; }
- //S32 err() const { return mBaseChannel + 2; }
+ // enumeration for segmenting the channel information
+ enum { E_CHANNEL_COUNT = 3 };
+ LLChannelDescriptors() : mBaseChannel(0) {}
+ explicit LLChannelDescriptors(S32 base) : mBaseChannel(base) {}
+ S32 in() const { return mBaseChannel; }
+ S32 out() const { return mBaseChannel + 1; }
+ //S32 err() const { return mBaseChannel + 2; }
protected:
- S32 mBaseChannel;
+ S32 mBaseChannel;
};
-/**
+/**
* @class LLSegment
* @brief A segment is a single, contiguous chunk of memory in a buffer
*
@@ -70,62 +70,62 @@ protected:
* as necessary.
* This is the preferred interface for working with memory blocks,
* since it is the only way to safely, inexpensively, and directly
- * access linear blocks of memory.
+ * access linear blocks of memory.
*/
class LLSegment
{
public:
- LLSegment();
- LLSegment(S32 channel, U8* data, S32 data_len);
- ~LLSegment();
-
- /**
- * @brief Check if this segment is on the given channel.
- *
- */
- bool isOnChannel(S32 channel) const;
-
- /**
- * @brief Get the channel
- */
- S32 getChannel() const;
-
- /**
- * @brief Set the channel
- */
- void setChannel(S32 channel);
-
- /**
- * @brief Return a raw pointer to the current data set.
- *
- * The pointer returned can be used for reading or even adjustment
- * if you are a bit crazy up to size() bytes into memory.
- * @return A potentially NULL pointer to the raw buffer data
- */
- U8* data() const;
-
- /**
- * @brief Return the size of the segment
- */
- S32 size() const;
-
- /**
- * @brief Check if two segments are the same.
- *
- * Two segments are considered equal if they are on the same
- * channel and cover the exact same address range.
- * @param rhs the segment to compare with this segment.
- * @return Returns true if they are equal.
- */
- bool operator==(const LLSegment& rhs) const;
+ LLSegment();
+ LLSegment(S32 channel, U8* data, S32 data_len);
+ ~LLSegment();
+
+ /**
+ * @brief Check if this segment is on the given channel.
+ *
+ */
+ bool isOnChannel(S32 channel) const;
+
+ /**
+ * @brief Get the channel
+ */
+ S32 getChannel() const;
+
+ /**
+ * @brief Set the channel
+ */
+ void setChannel(S32 channel);
+
+ /**
+ * @brief Return a raw pointer to the current data set.
+ *
+ * The pointer returned can be used for reading or even adjustment
+ * if you are a bit crazy up to size() bytes into memory.
+ * @return A potentially NULL pointer to the raw buffer data
+ */
+ U8* data() const;
+
+ /**
+ * @brief Return the size of the segment
+ */
+ S32 size() const;
+
+ /**
+ * @brief Check if two segments are the same.
+ *
+ * Two segments are considered equal if they are on the same
+ * channel and cover the exact same address range.
+ * @param rhs the segment to compare with this segment.
+ * @return Returns true if they are equal.
+ */
+ bool operator==(const LLSegment& rhs) const;
protected:
- S32 mChannel;
- U8* mData;
- S32 mSize;
+ S32 mChannel;
+ U8* mData;
+ S32 mSize;
};
-/**
+/**
* @class LLBuffer
* @brief Abstract base class for buffers
*
@@ -136,58 +136,58 @@ protected:
class LLBuffer
{
public:
- /**
- * @brief The buffer base class should have no responsibilities
- * other than an interface.
- */
- virtual ~LLBuffer() {}
-
- /**
- * @brief Generate a segment for this buffer.
- *
- * The segment returned is always contiguous memory. This call can
- * fail if no contiguous memory is available, eg, offset is past
- * the end. The segment returned may be smaller than the requested
- * size. The segment will never be larger than the requested size.
- * @param channel The channel for the segment.
- * @param offset The offset from zero in the buffer.
- * @param size The requested size of the segment.
- * @param segment[out] The out-value from the operation
- * @return Returns true if a segment was found.
- */
- virtual bool createSegment(S32 channel, S32 size, LLSegment& segment) = 0;
-
- /**
- * @brief Reclaim a segment from this buffer.
- *
- * This method is called on a buffer object when a caller is done
- * with a contiguous segment of memory inside this buffer. Since
- * segments can be cut arbitrarily outside of the control of the
- * buffer, this segment may not match any segment returned from
- * <code>createSegment()</code>.
- * @param segment The contiguous buffer segment to reclaim.
- * @return Returns true if the call was successful.
- */
- virtual bool reclaimSegment(const LLSegment& segment) = 0;
-
- /**
- * @brief Test if a segment is inside this buffer.
- *
- * @param segment The contiguous buffer segment to test.
- * @return Returns true if the segment is in the bufffer.
- */
- virtual bool containsSegment(const LLSegment& segment) const = 0;
-
- /**
- * @brief Return the current number of bytes allocated.
- *
- * This was implemented as a debugging tool, and it is not
- * necessarily a good idea to use it for anything else.
- */
- virtual S32 capacity() const = 0;
+ /**
+ * @brief The buffer base class should have no responsibilities
+ * other than an interface.
+ */
+ virtual ~LLBuffer() {}
+
+ /**
+ * @brief Generate a segment for this buffer.
+ *
+ * The segment returned is always contiguous memory. This call can
+ * fail if no contiguous memory is available, eg, offset is past
+ * the end. The segment returned may be smaller than the requested
+ * size. The segment will never be larger than the requested size.
+ * @param channel The channel for the segment.
+ * @param offset The offset from zero in the buffer.
+ * @param size The requested size of the segment.
+ * @param segment[out] The out-value from the operation
+ * @return Returns true if a segment was found.
+ */
+ virtual bool createSegment(S32 channel, S32 size, LLSegment& segment) = 0;
+
+ /**
+ * @brief Reclaim a segment from this buffer.
+ *
+ * This method is called on a buffer object when a caller is done
+ * with a contiguous segment of memory inside this buffer. Since
+ * segments can be cut arbitrarily outside of the control of the
+ * buffer, this segment may not match any segment returned from
+ * <code>createSegment()</code>.
+ * @param segment The contiguous buffer segment to reclaim.
+ * @return Returns true if the call was successful.
+ */
+ virtual bool reclaimSegment(const LLSegment& segment) = 0;
+
+ /**
+ * @brief Test if a segment is inside this buffer.
+ *
+ * @param segment The contiguous buffer segment to test.
+ * @return Returns true if the segment is in the bufffer.
+ */
+ virtual bool containsSegment(const LLSegment& segment) const = 0;
+
+ /**
+ * @brief Return the current number of bytes allocated.
+ *
+ * This was implemented as a debugging tool, and it is not
+ * necessarily a good idea to use it for anything else.
+ */
+ virtual S32 capacity() const = 0;
};
-/**
+/**
* @class LLHeapBuffer
* @brief A large contiguous buffer allocated on the heap with new[].
*
@@ -198,99 +198,99 @@ public:
class LLHeapBuffer : public LLBuffer
{
public:
- /**
- * @brief Construct a heap buffer with a reasonable default size.
- */
- LLHeapBuffer();
-
- /**
- * @brief Construct a heap buffer with a specified size.
- *
- * @param size The minimum size of the buffer.
- */
- explicit LLHeapBuffer(S32 size);
-
- /**
- * @brief Construct a heap buffer of minimum size len, and copy from src.
- *
- * @param src The source of the data to be copied.
- * @param len The minimum size of the buffer.
- */
- LLHeapBuffer(const U8* src, S32 len);
-
- /**
- * @brief Simple destruction.
- */
- virtual ~LLHeapBuffer();
-
- /**
- * @brief Get the number of bytes left in the buffer.
- *
- * Note that this is not a virtual function, and only available in
- * the LLHeapBuffer as a debugging aid.
- * @return Returns the number of bytes left.
- */
- S32 bytesLeft() const;
-
- /**
- * @brief Generate a segment for this buffer.
- *
- * The segment returned is always contiguous memory. This call can
- * fail if no contiguous memory is available, eg, offset is past
- * the end. The segment returned may be smaller than the requested
- * size. It is up to the caller to delete the segment returned.
- * @param channel The channel for the segment.
- * @param offset The offset from zero in the buffer
- * @param size The requested size of the segment
- * @param segment[out] The out-value from the operation
- * @return Returns true if a segment was found.
- */
- virtual bool createSegment(S32 channel, S32 size, LLSegment& segment);
-
- /**
- * @brief reclaim a segment from this buffer.
- *
- * This method is called on a buffer object when a caller is done
- * with a contiguous segment of memory inside this buffer. Since
- * segments can be cut arbitrarily outside of the control of the
- * buffer, this segment may not match any segment returned from
- * <code>createSegment()</code>.
- * This call will fail if the segment passed in is note completely
- * inside the buffer, eg, if the segment starts before this buffer
- * in memory or ends after it.
- * @param segment The contiguous buffer segment to reclaim.
- * @return Returns true if the call was successful.
- */
- virtual bool reclaimSegment(const LLSegment& segment);
-
- /**
- * @brief Test if a segment is inside this buffer.
- *
- * @param segment The contiguous buffer segment to test.
- * @return Returns true if the segment is in the bufffer.
- */
- virtual bool containsSegment(const LLSegment& segment) const;
-
- /**
- * @brief Return the current number of bytes allocated.
- */
- virtual S32 capacity() const { return mSize; }
+ /**
+ * @brief Construct a heap buffer with a reasonable default size.
+ */
+ LLHeapBuffer();
+
+ /**
+ * @brief Construct a heap buffer with a specified size.
+ *
+ * @param size The minimum size of the buffer.
+ */
+ explicit LLHeapBuffer(S32 size);
+
+ /**
+ * @brief Construct a heap buffer of minimum size len, and copy from src.
+ *
+ * @param src The source of the data to be copied.
+ * @param len The minimum size of the buffer.
+ */
+ LLHeapBuffer(const U8* src, S32 len);
+
+ /**
+ * @brief Simple destruction.
+ */
+ virtual ~LLHeapBuffer();
+
+ /**
+ * @brief Get the number of bytes left in the buffer.
+ *
+ * Note that this is not a virtual function, and only available in
+ * the LLHeapBuffer as a debugging aid.
+ * @return Returns the number of bytes left.
+ */
+ S32 bytesLeft() const;
+
+ /**
+ * @brief Generate a segment for this buffer.
+ *
+ * The segment returned is always contiguous memory. This call can
+ * fail if no contiguous memory is available, eg, offset is past
+ * the end. The segment returned may be smaller than the requested
+ * size. It is up to the caller to delete the segment returned.
+ * @param channel The channel for the segment.
+ * @param offset The offset from zero in the buffer
+ * @param size The requested size of the segment
+ * @param segment[out] The out-value from the operation
+ * @return Returns true if a segment was found.
+ */
+ virtual bool createSegment(S32 channel, S32 size, LLSegment& segment);
+
+ /**
+ * @brief reclaim a segment from this buffer.
+ *
+ * This method is called on a buffer object when a caller is done
+ * with a contiguous segment of memory inside this buffer. Since
+ * segments can be cut arbitrarily outside of the control of the
+ * buffer, this segment may not match any segment returned from
+ * <code>createSegment()</code>.
+ * This call will fail if the segment passed in is note completely
+ * inside the buffer, eg, if the segment starts before this buffer
+ * in memory or ends after it.
+ * @param segment The contiguous buffer segment to reclaim.
+ * @return Returns true if the call was successful.
+ */
+ virtual bool reclaimSegment(const LLSegment& segment);
+
+ /**
+ * @brief Test if a segment is inside this buffer.
+ *
+ * @param segment The contiguous buffer segment to test.
+ * @return Returns true if the segment is in the bufffer.
+ */
+ virtual bool containsSegment(const LLSegment& segment) const;
+
+ /**
+ * @brief Return the current number of bytes allocated.
+ */
+ virtual S32 capacity() const { return mSize; }
protected:
- U8* mBuffer;
- S32 mSize;
- U8* mNextFree;
- S32 mReclaimedBytes;
+ U8* mBuffer;
+ S32 mSize;
+ U8* mNextFree;
+ S32 mReclaimedBytes;
private:
- /**
- * @brief Helper method to allocate a buffer and correctly set
- * intertnal state of this buffer.
- */
- void allocate(S32 size);
+ /**
+ * @brief Helper method to allocate a buffer and correctly set
+ * intertnal state of this buffer.
+ */
+ void allocate(S32 size);
};
-/**
+/**
* @class LLBufferArray
* @brief Class to represent scattered memory buffers and in-order segments
* of that buffered data.
@@ -300,326 +300,326 @@ private:
class LLBufferArray
{
public:
- typedef std::vector<LLBuffer*> buffer_list_t;
- typedef buffer_list_t::iterator buffer_iterator_t;
- typedef buffer_list_t::const_iterator const_buffer_iterator_t;
- typedef std::list<LLSegment> segment_list_t;
- typedef segment_list_t::const_iterator const_segment_iterator_t;
- typedef segment_list_t::iterator segment_iterator_t;
- enum { npos = 0xffffffff };
-
- LLBufferArray();
- ~LLBufferArray();
-
- /* @name Channel methods
- */
- //@{
- /**
- * @brief Generate the a channel descriptor which consumes the
- * output for the channel passed in.
- */
- static LLChannelDescriptors makeChannelConsumer(
- const LLChannelDescriptors& channels);
-
- /**
- * @brief Generate the next channel descriptor for this buffer array.
- *
- * The channel descriptor interface is how the buffer array
- * clients can know where to read and write data. Use this
- * interface to get the 'next' channel set for usage. This is a
- * bit of a simple hack until it's utility indicates it should be
- * extended.
- * @return Returns a valid channel descriptor set for input and output.
- */
- LLChannelDescriptors nextChannel();
- //@}
-
- /* @name Data methods
- */
- //@{
-
- /**
- * @brief Return the sum of all allocated bytes.
- */
- S32 capacity() const;
-
- // These methods will be useful once there is any kind of buffer
- // besides a heap buffer.
- //bool append(EBufferChannel channel, LLBuffer* data);
- //bool prepend(EBufferChannel channel, LLBuffer* data);
- //bool insertAfter(
- // segment_iterator_t segment,
- // EBufferChannel channel,
- // LLBuffer* data);
-
- /**
- * @brief Put data on a channel at the end of this buffer array.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put on the end of the array. This
- * object will internally allocate new buffers if necessary.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool append(S32 channel, const U8* src, S32 len);
-
- /**
- * @brief Put data on a channel at the front of this buffer array.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put in the front of the array. This
- * object will internally allocate new buffers if necessary.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool prepend(S32 channel, const U8* src, S32 len);
-
- /**
- * @brief Insert data into a buffer array after a particular segment.
- *
- * The data is copied from src into the buffer array. At least one
- * new segment is created and put in the array. This object will
- * internally allocate new buffers if necessary.
- * @param segment The segment in front of the new segments location
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @return Returns true if the method worked.
- */
- bool insertAfter(
- segment_iterator_t segment,
- S32 channel,
- const U8* src,
- S32 len);
-
- /**
- * @brief Count bytes in the buffer array on the specified channel
- *
- * @param channel The channel to count.
- * @param start The start address in the array for counting. You
- * can specify NULL to start at the beginning.
- * @return Returns the number of bytes in the channel after start
- */
- S32 countAfter(S32 channel, U8* start) const;
-
- /**
- * @brief Count all bytes on channel.
- *
- * Helper method which just calls countAfter().
- * @param channel The channel to count.
- * @return Returns the number of bytes in the channel.
- */
- S32 count(S32 channel) const
- {
- return countAfter(channel, NULL);
- }
-
- /**
- * @brief Read bytes in the buffer array on the specified channel
- *
- * You should prefer iterating over segments is possible since
- * this method requires you to allocate large buffers - precisely
- * what this class is trying to prevent. This method will skip
- * any segments which are not on the given channel, so this method
- * would usually be used to read a channel and copy that to a log
- * or a socket buffer or something.
- * @param channel The channel to read.
- * @param start The start address in the array for reading. You
- * can specify NULL to start at the beginning.
- * @param dest The destination of the data read. This must be at
- * least len bytes long.
- * @param len[in,out] <b>in</b> How many bytes to read. <b>out</b> How
- * many bytes were read.
- * @return Returns the address of the last read byte.
- */
- U8* readAfter(S32 channel, U8* start, U8* dest, S32& len) const;
-
- /**
- * @brief Find an address in a buffer array
- *
- * @param channel The channel to seek in.
- * @param start The start address in the array for the seek
- * operation. You can specify NULL to start the seek at the
- * beginning, or pass in npos to start at the end.
- * @param delta How many bytes to seek through the array.
- * @return Returns the address of the last read byte.
- */
- U8* seek(S32 channel, U8* start, S32 delta) const;
- //@}
-
- /* @name Buffer interaction
- */
- //@{
- /**
- * @brief Take the contents of another buffer array
- *
- * This method simply strips the contents out of the source
- * buffery array - segments, buffers, etc, and appends them to
- * this instance. After this operation, the source is empty and
- * ready for reuse.
- * @param source The source buffer
- * @return Returns true if the operation succeeded.
- */
- bool takeContents(LLBufferArray& source);
- //@}
-
- /* @name Segment methods
- */
- //@{
- /**
- * @brief Split a segments so that address is the last address of
- * one segment, and the rest of the original segment becomes
- * another segment on the same channel.
- *
- * After this method call,
- * <code>getLastSegmentAddress(*getSegment(address)) ==
- * address</code> should be true. This call will only create a new
- * segment if the statement above is false before the call. Since
- * you usually call splitAfter() to change a segment property, use
- * getSegment() to perform those operations.
- * @param address The address which will become the last address
- * of the segment it is in.
- * @return Returns an iterator to the segment which contains
- * <code>address</code> which is <code>endSegment()</code> on
- * failure.
- */
- segment_iterator_t splitAfter(U8* address);
-
- /**
- * @brief Get the first segment in the buffer array.
- *
- * @return Returns the segment if there is one.
- */
- segment_iterator_t beginSegment();
-
- /**
- * @brief Get the one-past-the-end segment in the buffer array
- *
- * @return Returns the iterator for an invalid segment location.
- */
- segment_iterator_t endSegment();
-
- /**
- * @brief Get the segment which holds the given address.
- *
- * As opposed to some methods, passing a NULL will result in
- * returning the end segment.
- * @param address An address in the middle of the sought segment.
- * @return Returns the iterator for the segment or endSegment() on
- * failure.
- */
- const_segment_iterator_t getSegment(U8* address) const;
-
- /**
- * @brief Get the segment which holds the given address.
- *
- * As opposed to some methods, passing a NULL will result in
- * returning the end segment.
- * @param address An address in the middle of the sought segment.
- * @return Returns the iterator for the segment or endSegment() on
- * failure.
- */
- segment_iterator_t getSegment(U8* address);
-
- /**
- * @brief Get a segment iterator after address, and a constructed
- * segment to represent the next linear block of memory.
- *
- * This method is a helper by giving you the largest segment
- * possible in the out-value param after the address provided. The
- * iterator will be useful for iteration, while the segment can be
- * used for direct access to memory after address if the return
- * values isnot end. Passing in NULL will return beginSegment()
- * which may be endSegment(). The segment returned will only be
- * zero length if the return value equals end.
- * This is really just a helper method, since all the information
- * returned could be constructed through other methods.
- * @param address An address in the middle of the sought segment.
- * @param segment[out] segment to be used for reading or writing
- * @return Returns an iterator which contains at least segment or
- * endSegment() on failure.
- */
- segment_iterator_t constructSegmentAfter(U8* address, LLSegment& segment);
-
- /**
- * @brief Make a new segment at the end of buffer array
- *
- * This method will attempt to create a new and empty segment of
- * the specified length. The segment created may be shorter than
- * requested.
- * @param channel[in] The channel for the newly created segment.
- * @param length[in] The requested length of the segment.
- * @return Returns an iterator which contains at least segment or
- * endSegment() on failure.
- */
- segment_iterator_t makeSegment(S32 channel, S32 length);
-
- /**
- * @brief Erase the segment if it is in the buffer array.
- *
- * @param iter An iterator referring to the segment to erase.
- * @return Returns true on success.
- */
- bool eraseSegment(const segment_iterator_t& iter);
-
- /**
- * @brief Lock the mutex if it exists
- * This method locks mMutexp to make accessing LLBufferArray thread-safe
- */
- void lock();
-
- /**
- * @brief Unlock the mutex if it exists
- */
- void unlock();
-
- /**
- * @brief Return mMutexp
- */
- LLMutex* getMutex();
-
- /**
- * @brief Set LLBufferArray to be shared across threads or not
- * This method is to create mMutexp if is threaded.
- * @param threaded Indicates this LLBufferArray instance is shared across threads if true.
- */
- void setThreaded(bool threaded);
- //@}
+ typedef std::vector<LLBuffer*> buffer_list_t;
+ typedef buffer_list_t::iterator buffer_iterator_t;
+ typedef buffer_list_t::const_iterator const_buffer_iterator_t;
+ typedef std::list<LLSegment> segment_list_t;
+ typedef segment_list_t::const_iterator const_segment_iterator_t;
+ typedef segment_list_t::iterator segment_iterator_t;
+ enum { npos = 0xffffffff };
+
+ LLBufferArray();
+ ~LLBufferArray();
+
+ /* @name Channel methods
+ */
+ //@{
+ /**
+ * @brief Generate the a channel descriptor which consumes the
+ * output for the channel passed in.
+ */
+ static LLChannelDescriptors makeChannelConsumer(
+ const LLChannelDescriptors& channels);
+
+ /**
+ * @brief Generate the next channel descriptor for this buffer array.
+ *
+ * The channel descriptor interface is how the buffer array
+ * clients can know where to read and write data. Use this
+ * interface to get the 'next' channel set for usage. This is a
+ * bit of a simple hack until it's utility indicates it should be
+ * extended.
+ * @return Returns a valid channel descriptor set for input and output.
+ */
+ LLChannelDescriptors nextChannel();
+ //@}
+
+ /* @name Data methods
+ */
+ //@{
+
+ /**
+ * @brief Return the sum of all allocated bytes.
+ */
+ S32 capacity() const;
+
+ // These methods will be useful once there is any kind of buffer
+ // besides a heap buffer.
+ //bool append(EBufferChannel channel, LLBuffer* data);
+ //bool prepend(EBufferChannel channel, LLBuffer* data);
+ //bool insertAfter(
+ // segment_iterator_t segment,
+ // EBufferChannel channel,
+ // LLBuffer* data);
+
+ /**
+ * @brief Put data on a channel at the end of this buffer array.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put on the end of the array. This
+ * object will internally allocate new buffers if necessary.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool append(S32 channel, const U8* src, S32 len);
+
+ /**
+ * @brief Put data on a channel at the front of this buffer array.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put in the front of the array. This
+ * object will internally allocate new buffers if necessary.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool prepend(S32 channel, const U8* src, S32 len);
+
+ /**
+ * @brief Insert data into a buffer array after a particular segment.
+ *
+ * The data is copied from src into the buffer array. At least one
+ * new segment is created and put in the array. This object will
+ * internally allocate new buffers if necessary.
+ * @param segment The segment in front of the new segments location
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @return Returns true if the method worked.
+ */
+ bool insertAfter(
+ segment_iterator_t segment,
+ S32 channel,
+ const U8* src,
+ S32 len);
+
+ /**
+ * @brief Count bytes in the buffer array on the specified channel
+ *
+ * @param channel The channel to count.
+ * @param start The start address in the array for counting. You
+ * can specify NULL to start at the beginning.
+ * @return Returns the number of bytes in the channel after start
+ */
+ S32 countAfter(S32 channel, U8* start) const;
+
+ /**
+ * @brief Count all bytes on channel.
+ *
+ * Helper method which just calls countAfter().
+ * @param channel The channel to count.
+ * @return Returns the number of bytes in the channel.
+ */
+ S32 count(S32 channel) const
+ {
+ return countAfter(channel, NULL);
+ }
+
+ /**
+ * @brief Read bytes in the buffer array on the specified channel
+ *
+ * You should prefer iterating over segments is possible since
+ * this method requires you to allocate large buffers - precisely
+ * what this class is trying to prevent. This method will skip
+ * any segments which are not on the given channel, so this method
+ * would usually be used to read a channel and copy that to a log
+ * or a socket buffer or something.
+ * @param channel The channel to read.
+ * @param start The start address in the array for reading. You
+ * can specify NULL to start at the beginning.
+ * @param dest The destination of the data read. This must be at
+ * least len bytes long.
+ * @param len[in,out] <b>in</b> How many bytes to read. <b>out</b> How
+ * many bytes were read.
+ * @return Returns the address of the last read byte.
+ */
+ U8* readAfter(S32 channel, U8* start, U8* dest, S32& len) const;
+
+ /**
+ * @brief Find an address in a buffer array
+ *
+ * @param channel The channel to seek in.
+ * @param start The start address in the array for the seek
+ * operation. You can specify NULL to start the seek at the
+ * beginning, or pass in npos to start at the end.
+ * @param delta How many bytes to seek through the array.
+ * @return Returns the address of the last read byte.
+ */
+ U8* seek(S32 channel, U8* start, S32 delta) const;
+ //@}
+
+ /* @name Buffer interaction
+ */
+ //@{
+ /**
+ * @brief Take the contents of another buffer array
+ *
+ * This method simply strips the contents out of the source
+ * buffery array - segments, buffers, etc, and appends them to
+ * this instance. After this operation, the source is empty and
+ * ready for reuse.
+ * @param source The source buffer
+ * @return Returns true if the operation succeeded.
+ */
+ bool takeContents(LLBufferArray& source);
+ //@}
+
+ /* @name Segment methods
+ */
+ //@{
+ /**
+ * @brief Split a segments so that address is the last address of
+ * one segment, and the rest of the original segment becomes
+ * another segment on the same channel.
+ *
+ * After this method call,
+ * <code>getLastSegmentAddress(*getSegment(address)) ==
+ * address</code> should be true. This call will only create a new
+ * segment if the statement above is false before the call. Since
+ * you usually call splitAfter() to change a segment property, use
+ * getSegment() to perform those operations.
+ * @param address The address which will become the last address
+ * of the segment it is in.
+ * @return Returns an iterator to the segment which contains
+ * <code>address</code> which is <code>endSegment()</code> on
+ * failure.
+ */
+ segment_iterator_t splitAfter(U8* address);
+
+ /**
+ * @brief Get the first segment in the buffer array.
+ *
+ * @return Returns the segment if there is one.
+ */
+ segment_iterator_t beginSegment();
+
+ /**
+ * @brief Get the one-past-the-end segment in the buffer array
+ *
+ * @return Returns the iterator for an invalid segment location.
+ */
+ segment_iterator_t endSegment();
+
+ /**
+ * @brief Get the segment which holds the given address.
+ *
+ * As opposed to some methods, passing a NULL will result in
+ * returning the end segment.
+ * @param address An address in the middle of the sought segment.
+ * @return Returns the iterator for the segment or endSegment() on
+ * failure.
+ */
+ const_segment_iterator_t getSegment(U8* address) const;
+
+ /**
+ * @brief Get the segment which holds the given address.
+ *
+ * As opposed to some methods, passing a NULL will result in
+ * returning the end segment.
+ * @param address An address in the middle of the sought segment.
+ * @return Returns the iterator for the segment or endSegment() on
+ * failure.
+ */
+ segment_iterator_t getSegment(U8* address);
+
+ /**
+ * @brief Get a segment iterator after address, and a constructed
+ * segment to represent the next linear block of memory.
+ *
+ * This method is a helper by giving you the largest segment
+ * possible in the out-value param after the address provided. The
+ * iterator will be useful for iteration, while the segment can be
+ * used for direct access to memory after address if the return
+ * values isnot end. Passing in NULL will return beginSegment()
+ * which may be endSegment(). The segment returned will only be
+ * zero length if the return value equals end.
+ * This is really just a helper method, since all the information
+ * returned could be constructed through other methods.
+ * @param address An address in the middle of the sought segment.
+ * @param segment[out] segment to be used for reading or writing
+ * @return Returns an iterator which contains at least segment or
+ * endSegment() on failure.
+ */
+ segment_iterator_t constructSegmentAfter(U8* address, LLSegment& segment);
+
+ /**
+ * @brief Make a new segment at the end of buffer array
+ *
+ * This method will attempt to create a new and empty segment of
+ * the specified length. The segment created may be shorter than
+ * requested.
+ * @param channel[in] The channel for the newly created segment.
+ * @param length[in] The requested length of the segment.
+ * @return Returns an iterator which contains at least segment or
+ * endSegment() on failure.
+ */
+ segment_iterator_t makeSegment(S32 channel, S32 length);
+
+ /**
+ * @brief Erase the segment if it is in the buffer array.
+ *
+ * @param iter An iterator referring to the segment to erase.
+ * @return Returns true on success.
+ */
+ bool eraseSegment(const segment_iterator_t& iter);
+
+ /**
+ * @brief Lock the mutex if it exists
+ * This method locks mMutexp to make accessing LLBufferArray thread-safe
+ */
+ void lock();
+
+ /**
+ * @brief Unlock the mutex if it exists
+ */
+ void unlock();
+
+ /**
+ * @brief Return mMutexp
+ */
+ LLMutex* getMutex();
+
+ /**
+ * @brief Set LLBufferArray to be shared across threads or not
+ * This method is to create mMutexp if is threaded.
+ * @param threaded Indicates this LLBufferArray instance is shared across threads if true.
+ */
+ void setThreaded(bool threaded);
+ //@}
protected:
- /**
- * @brief Optimally put data in buffers, and reutrn segments.
- *
- * This is an internal function used to create buffers as
- * necessary, and sequence the segments appropriately for the
- * various ways to copy data from src into this.
- * If this method fails, it may actually leak some space inside
- * buffers, but I am not too worried about the slim possibility
- * that we may have some 'dead' space which will be recovered when
- * the buffer (which we will not lose) is deleted. Addressing this
- * weakness will make the buffers almost as complex as a general
- * memory management system.
- * @param channel The channel for this data
- * @param src The start of memory for the data to be copied
- * @param len The number of bytes of data to copy
- * @param segments Out-value for the segments created.
- * @return Returns true if the method worked.
- */
- bool copyIntoBuffers(
- S32 channel,
- const U8* src,
- S32 len,
- std::vector<LLSegment>& segments);
+ /**
+ * @brief Optimally put data in buffers, and reutrn segments.
+ *
+ * This is an internal function used to create buffers as
+ * necessary, and sequence the segments appropriately for the
+ * various ways to copy data from src into this.
+ * If this method fails, it may actually leak some space inside
+ * buffers, but I am not too worried about the slim possibility
+ * that we may have some 'dead' space which will be recovered when
+ * the buffer (which we will not lose) is deleted. Addressing this
+ * weakness will make the buffers almost as complex as a general
+ * memory management system.
+ * @param channel The channel for this data
+ * @param src The start of memory for the data to be copied
+ * @param len The number of bytes of data to copy
+ * @param segments Out-value for the segments created.
+ * @return Returns true if the method worked.
+ */
+ bool copyIntoBuffers(
+ S32 channel,
+ const U8* src,
+ S32 len,
+ std::vector<LLSegment>& segments);
protected:
- S32 mNextBaseChannel;
- buffer_list_t mBuffers;
- segment_list_t mSegments;
- LLMutex* mMutexp;
+ S32 mNextBaseChannel;
+ buffer_list_t mBuffers;
+ segment_list_t mSegments;
+ LLMutex* mMutexp;
};
#endif // LL_LLBUFFER_H
diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp
index 39508c1c52..e51b489813 100644
--- a/indra/llmessage/llbufferstream.cpp
+++ b/indra/llmessage/llbufferstream.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbufferstream.cpp
* @author Phoenix
* @date 2005-10-10
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,291 +39,291 @@ static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4;
* LLBufferStreamBuf
*/
LLBufferStreamBuf::LLBufferStreamBuf(
- const LLChannelDescriptors& channels,
- LLBufferArray* buffer) :
- mChannels(channels),
- mBuffer(buffer)
+ const LLChannelDescriptors& channels,
+ LLBufferArray* buffer) :
+ mChannels(channels),
+ mBuffer(buffer)
{
}
LLBufferStreamBuf::~LLBufferStreamBuf()
{
- sync();
+ sync();
}
// virtual
int LLBufferStreamBuf::underflow()
{
- //LL_DEBUGS() << "LLBufferStreamBuf::underflow()" << LL_ENDL;
- if(!mBuffer)
- {
- return EOF;
- }
+ //LL_DEBUGS() << "LLBufferStreamBuf::underflow()" << LL_ENDL;
+ if(!mBuffer)
+ {
+ return EOF;
+ }
- LLMutexLock lock(mBuffer->getMutex());
- LLBufferArray::segment_iterator_t iter;
- LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
- U8* last_pos = (U8*)gptr();
- LLSegment segment;
- if(last_pos)
- {
- // Back up into a piece of memory we know that we have
- // allocated so that calls for the next segment based on
- // 'after' will succeed.
- --last_pos;
- iter = mBuffer->splitAfter(last_pos);
- if(iter != end)
- {
- // We need to clear the read segment just in case we have
- // an early exit in the function and never collect the
- // next segment. Calling eraseSegment() with the same
- // segment twice is just like double deleting -- nothing
- // good comes from it.
- mBuffer->eraseSegment(iter++);
- if(iter != end) segment = (*iter);
- }
- else
- {
- // This should never really happen, but somehow, the
- // istream is telling the buf that it just finished
- // reading memory that is not in the buf. I think this
- // would only happen if there were a bug in the c++ stream
- // class. Just bail.
- // *TODO: can we set the fail bit on the stream somehow?
- return EOF;
- }
- }
- else
- {
- // Get iterator to full segment containing last_pos
- // and construct sub-segment starting at last_pos.
- // Note: segment may != *it at this point
- iter = mBuffer->constructSegmentAfter(last_pos, segment);
- }
- if(iter == end)
- {
- return EOF;
- }
+ LLMutexLock lock(mBuffer->getMutex());
+ LLBufferArray::segment_iterator_t iter;
+ LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
+ U8* last_pos = (U8*)gptr();
+ LLSegment segment;
+ if(last_pos)
+ {
+ // Back up into a piece of memory we know that we have
+ // allocated so that calls for the next segment based on
+ // 'after' will succeed.
+ --last_pos;
+ iter = mBuffer->splitAfter(last_pos);
+ if(iter != end)
+ {
+ // We need to clear the read segment just in case we have
+ // an early exit in the function and never collect the
+ // next segment. Calling eraseSegment() with the same
+ // segment twice is just like double deleting -- nothing
+ // good comes from it.
+ mBuffer->eraseSegment(iter++);
+ if(iter != end) segment = (*iter);
+ }
+ else
+ {
+ // This should never really happen, but somehow, the
+ // istream is telling the buf that it just finished
+ // reading memory that is not in the buf. I think this
+ // would only happen if there were a bug in the c++ stream
+ // class. Just bail.
+ // *TODO: can we set the fail bit on the stream somehow?
+ return EOF;
+ }
+ }
+ else
+ {
+ // Get iterator to full segment containing last_pos
+ // and construct sub-segment starting at last_pos.
+ // Note: segment may != *it at this point
+ iter = mBuffer->constructSegmentAfter(last_pos, segment);
+ }
+ if(iter == end)
+ {
+ return EOF;
+ }
- // Iterate through segments to find a non-empty segment on input channel.
- while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0)))
- {
- ++iter;
- if(iter == end)
- {
- return EOF;
- }
+ // Iterate through segments to find a non-empty segment on input channel.
+ while((!segment.isOnChannel(mChannels.in()) || (segment.size() == 0)))
+ {
+ ++iter;
+ if(iter == end)
+ {
+ return EOF;
+ }
- segment = *(iter);
- }
+ segment = *(iter);
+ }
- // set up the stream to read from the next segment.
- char* start = (char*)segment.data();
- setg(start, start, start + segment.size());
- return *gptr();
+ // set up the stream to read from the next segment.
+ char* start = (char*)segment.data();
+ setg(start, start, start + segment.size());
+ return *gptr();
}
// virtual
int LLBufferStreamBuf::overflow(int c)
{
- if(!mBuffer)
- {
- return EOF;
- }
- if(EOF == c)
- {
- // if someone puts an EOF, I suppose we should sync and return
- // success.
- if(0 == sync())
- {
- return 1;
- }
- else
- {
- return EOF;
- }
- }
+ if(!mBuffer)
+ {
+ return EOF;
+ }
+ if(EOF == c)
+ {
+ // if someone puts an EOF, I suppose we should sync and return
+ // success.
+ if(0 == sync())
+ {
+ return 1;
+ }
+ else
+ {
+ return EOF;
+ }
+ }
- // since we got here, we have a buffer, and we have a character to
- // put on it.
- LLBufferArray::segment_iterator_t it;
- LLMutexLock lock(mBuffer->getMutex());
- it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);
- if(it != mBuffer->endSegment())
- {
- char* start = (char*)(*it).data();
- (*start) = (char)(c);
- setp(start + 1, start + (*it).size());
- return c;
- }
- else
- {
- return EOF;
- }
+ // since we got here, we have a buffer, and we have a character to
+ // put on it.
+ LLBufferArray::segment_iterator_t it;
+ LLMutexLock lock(mBuffer->getMutex());
+ it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);
+ if(it != mBuffer->endSegment())
+ {
+ char* start = (char*)(*it).data();
+ (*start) = (char)(c);
+ setp(start + 1, start + (*it).size());
+ return c;
+ }
+ else
+ {
+ return EOF;
+ }
}
// virtual
int LLBufferStreamBuf::sync()
{
- int return_value = -1;
- if(!mBuffer)
- {
- return return_value;
- }
+ int return_value = -1;
+ if(!mBuffer)
+ {
+ return return_value;
+ }
- // This chunk of code is not necessary because typically, users of
- // the stream will read until EOF. Therefore, underflow was called
- // and the segment was discarded before the sync() was called in
- // the destructor. Theoretically, we could keep some more data
- // around and detect the rare case where an istream was deleted
- // before reading to the end, but that will only leave behind some
- // unavailable but still referenced memory. Also, if another
- // istream is constructed, it will re-read that segment, and then
- // discard it.
- //U8* last_pos = (U8*)gptr();
- //if(last_pos)
- //{
- // // Looks like we read something. Discard what we have read.
- // // gptr() actually returns the currrent position, but we call
- // // it last_pos because of how it is used in the split call
- // // below.
- // --last_pos;
- // LLBufferArray::segment_iterator_t iter;
- // iter = mBuffer->splitAfter(last_pos);
- // if(iter != mBuffer->endSegment())
- // {
- // // We need to clear the read segment just in case we have
- // // an early exit in the function and never collect the
- // // next segment. Calling eraseSegment() with the same
- // // segment twice is just like double deleting -- nothing
- // // good comes from it.
- // mBuffer->eraseSegment(iter);
- // }
- //}
+ // This chunk of code is not necessary because typically, users of
+ // the stream will read until EOF. Therefore, underflow was called
+ // and the segment was discarded before the sync() was called in
+ // the destructor. Theoretically, we could keep some more data
+ // around and detect the rare case where an istream was deleted
+ // before reading to the end, but that will only leave behind some
+ // unavailable but still referenced memory. Also, if another
+ // istream is constructed, it will re-read that segment, and then
+ // discard it.
+ //U8* last_pos = (U8*)gptr();
+ //if(last_pos)
+ //{
+ // // Looks like we read something. Discard what we have read.
+ // // gptr() actually returns the currrent position, but we call
+ // // it last_pos because of how it is used in the split call
+ // // below.
+ // --last_pos;
+ // LLBufferArray::segment_iterator_t iter;
+ // iter = mBuffer->splitAfter(last_pos);
+ // if(iter != mBuffer->endSegment())
+ // {
+ // // We need to clear the read segment just in case we have
+ // // an early exit in the function and never collect the
+ // // next segment. Calling eraseSegment() with the same
+ // // segment twice is just like double deleting -- nothing
+ // // good comes from it.
+ // mBuffer->eraseSegment(iter);
+ // }
+ //}
- // set the put pointer so that we force an overflow on the next
- // write.
- U8* address = (U8*)pptr();
- setp(NULL, NULL);
+ // set the put pointer so that we force an overflow on the next
+ // write.
+ U8* address = (U8*)pptr();
+ setp(NULL, NULL);
- // *NOTE: I bet we could just --address if address is not NULL.
- // Need to think about that.
- LLMutexLock lock(mBuffer->getMutex());
- address = mBuffer->seek(mChannels.out(), address, -1);
- if(address)
- {
- LLBufferArray::segment_iterator_t it;
- it = mBuffer->splitAfter(address);
- LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
- if(it != end)
- {
- ++it;
- if(it != end)
- {
- mBuffer->eraseSegment(it);
- }
- return_value = 0;
- }
- }
- else
- {
- // nothing was put on the buffer, so the sync() is a no-op.
- return_value = 0;
- }
- return return_value;
+ // *NOTE: I bet we could just --address if address is not NULL.
+ // Need to think about that.
+ LLMutexLock lock(mBuffer->getMutex());
+ address = mBuffer->seek(mChannels.out(), address, -1);
+ if(address)
+ {
+ LLBufferArray::segment_iterator_t it;
+ it = mBuffer->splitAfter(address);
+ LLBufferArray::segment_iterator_t end = mBuffer->endSegment();
+ if(it != end)
+ {
+ ++it;
+ if(it != end)
+ {
+ mBuffer->eraseSegment(it);
+ }
+ return_value = 0;
+ }
+ }
+ else
+ {
+ // nothing was put on the buffer, so the sync() is a no-op.
+ return_value = 0;
+ }
+ return return_value;
}
// virtual
#if( LL_WINDOWS || __GNUC__ > 2)
LLBufferStreamBuf::pos_type LLBufferStreamBuf::seekoff(
- LLBufferStreamBuf::off_type off,
- std::ios::seekdir way,
- std::ios::openmode which)
+ LLBufferStreamBuf::off_type off,
+ std::ios::seekdir way,
+ std::ios::openmode which)
#else
streampos LLBufferStreamBuf::seekoff(
- streamoff off,
- std::ios::seekdir way,
- std::ios::openmode which)
+ streamoff off,
+ std::ios::seekdir way,
+ std::ios::openmode which)
#endif
{
- if(!mBuffer
- || ((way == std::ios::beg) && (off < 0))
- || ((way == std::ios::end) && (off > 0)))
- {
- return -1;
- }
- U8* address = NULL;
- if(which & std::ios::in)
- {
- U8* base_addr = NULL;
- switch(way)
- {
- case std::ios::end:
- base_addr = (U8*)LLBufferArray::npos;
- break;
- case std::ios::cur:
- // get the current get pointer and adjust it for buffer
- // array semantics.
- base_addr = (U8*)gptr();
- break;
- case std::ios::beg:
- default:
- // NULL is fine
- break;
- }
+ if(!mBuffer
+ || ((way == std::ios::beg) && (off < 0))
+ || ((way == std::ios::end) && (off > 0)))
+ {
+ return -1;
+ }
+ U8* address = NULL;
+ if(which & std::ios::in)
+ {
+ U8* base_addr = NULL;
+ switch(way)
+ {
+ case std::ios::end:
+ base_addr = (U8*)LLBufferArray::npos;
+ break;
+ case std::ios::cur:
+ // get the current get pointer and adjust it for buffer
+ // array semantics.
+ base_addr = (U8*)gptr();
+ break;
+ case std::ios::beg:
+ default:
+ // NULL is fine
+ break;
+ }
- LLMutexLock lock(mBuffer->getMutex());
- address = mBuffer->seek(mChannels.in(), base_addr, off);
- if(address)
- {
- LLBufferArray::segment_iterator_t iter;
- iter = mBuffer->getSegment(address);
- char* start = (char*)(*iter).data();
- setg(start, (char*)address, start + (*iter).size());
- }
- else
- {
- address = (U8*)(-1);
- }
- }
- if(which & std::ios::out)
- {
- U8* base_addr = NULL;
- switch(way)
- {
- case std::ios::end:
- base_addr = (U8*)LLBufferArray::npos;
- break;
- case std::ios::cur:
- // get the current put pointer and adjust it for buffer
- // array semantics.
- base_addr = (U8*)pptr();
- break;
- case std::ios::beg:
- default:
- // NULL is fine
- break;
- }
+ LLMutexLock lock(mBuffer->getMutex());
+ address = mBuffer->seek(mChannels.in(), base_addr, off);
+ if(address)
+ {
+ LLBufferArray::segment_iterator_t iter;
+ iter = mBuffer->getSegment(address);
+ char* start = (char*)(*iter).data();
+ setg(start, (char*)address, start + (*iter).size());
+ }
+ else
+ {
+ address = (U8*)(-1);
+ }
+ }
+ if(which & std::ios::out)
+ {
+ U8* base_addr = NULL;
+ switch(way)
+ {
+ case std::ios::end:
+ base_addr = (U8*)LLBufferArray::npos;
+ break;
+ case std::ios::cur:
+ // get the current put pointer and adjust it for buffer
+ // array semantics.
+ base_addr = (U8*)pptr();
+ break;
+ case std::ios::beg:
+ default:
+ // NULL is fine
+ break;
+ }
- LLMutexLock lock(mBuffer->getMutex());
- address = mBuffer->seek(mChannels.out(), base_addr, off);
- if(address)
- {
- LLBufferArray::segment_iterator_t iter;
- iter = mBuffer->getSegment(address);
- setp((char*)address, (char*)(*iter).data() + (*iter).size());
- }
- else
- {
- address = (U8*)(-1);
- }
- }
+ LLMutexLock lock(mBuffer->getMutex());
+ address = mBuffer->seek(mChannels.out(), base_addr, off);
+ if(address)
+ {
+ LLBufferArray::segment_iterator_t iter;
+ iter = mBuffer->getSegment(address);
+ setp((char*)address, (char*)(*iter).data() + (*iter).size());
+ }
+ else
+ {
+ address = (U8*)(-1);
+ }
+ }
#if( LL_WINDOWS || __GNUC__ > 2 )
- S32 rv = (S32)(intptr_t)address;
- return (pos_type)rv;
+ S32 rv = (S32)(intptr_t)address;
+ return (pos_type)rv;
#else
- return (streampos)address;
+ return (streampos)address;
#endif
}
@@ -332,10 +332,10 @@ streampos LLBufferStreamBuf::seekoff(
* LLBufferStream
*/
LLBufferStream::LLBufferStream(
- const LLChannelDescriptors& channels,
- LLBufferArray* buffer) :
- std::iostream(&mStreamBuf),
- mStreamBuf(channels, buffer)
+ const LLChannelDescriptors& channels,
+ LLBufferArray* buffer) :
+ std::iostream(&mStreamBuf),
+ mStreamBuf(channels, buffer)
{
}
diff --git a/indra/llmessage/llbufferstream.h b/indra/llmessage/llbufferstream.h
index 19749612f3..ac1aa49e81 100644
--- a/indra/llmessage/llbufferstream.h
+++ b/indra/llmessage/llbufferstream.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llbufferstream.h
* @author Phoenix
* @date 2005-10-10
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,7 +33,7 @@
#include <iostream>
#include "llbuffer.h"
-/**
+/**
* @class LLBufferStreamBuf
* @brief This implements the buffer wrapper for an istream
*
@@ -42,92 +42,92 @@
class LLBufferStreamBuf : public std::streambuf
{
public:
- LLBufferStreamBuf(
- const LLChannelDescriptors& channels,
- LLBufferArray* buffer);
- virtual ~LLBufferStreamBuf();
+ LLBufferStreamBuf(
+ const LLChannelDescriptors& channels,
+ LLBufferArray* buffer);
+ virtual ~LLBufferStreamBuf();
protected:
#if( LL_WINDOWS || __GNUC__ > 2 )
- typedef std::streambuf::pos_type pos_type;
- typedef std::streambuf::off_type off_type;
+ typedef std::streambuf::pos_type pos_type;
+ typedef std::streambuf::off_type off_type;
#endif
- /* @name streambuf vrtual implementations
- */
- //@{
- /*
- * @brief called when we hit the end of input
- *
- * @return Returns the character at the current position or EOF.
- */
- virtual int underflow();
-
- /*
- * @brief called when we hit the end of output
- *
- * @param c The character to store at the current put position
- * @return Returns EOF if the function failed. Any other value on success.
- */
- virtual int overflow(int c);
-
- /*
- * @brief synchronize the buffer
- *
- * @return Returns 0 on success or -1 on failure.
- */
- virtual int sync();
-
- /*
- * @brief Seek to an offset position in a stream.
- *
- * @param off Offset value relative to way paramter
- * @param way The seek direction. One of ios::beg, ios::cur, and ios::end.
- * @param which Which pointer to modify. One of ios::in, ios::out,
- * or both masked together.
- * @return Returns the new position or an invalid position on failure.
- */
+ /* @name streambuf vrtual implementations
+ */
+ //@{
+ /*
+ * @brief called when we hit the end of input
+ *
+ * @return Returns the character at the current position or EOF.
+ */
+ virtual int underflow();
+
+ /*
+ * @brief called when we hit the end of output
+ *
+ * @param c The character to store at the current put position
+ * @return Returns EOF if the function failed. Any other value on success.
+ */
+ virtual int overflow(int c);
+
+ /*
+ * @brief synchronize the buffer
+ *
+ * @return Returns 0 on success or -1 on failure.
+ */
+ virtual int sync();
+
+ /*
+ * @brief Seek to an offset position in a stream.
+ *
+ * @param off Offset value relative to way paramter
+ * @param way The seek direction. One of ios::beg, ios::cur, and ios::end.
+ * @param which Which pointer to modify. One of ios::in, ios::out,
+ * or both masked together.
+ * @return Returns the new position or an invalid position on failure.
+ */
#if( LL_WINDOWS || __GNUC__ > 2)
- virtual pos_type seekoff(
- off_type off,
- std::ios::seekdir way,
- std::ios::openmode which);
+ virtual pos_type seekoff(
+ off_type off,
+ std::ios::seekdir way,
+ std::ios::openmode which);
#else
- virtual streampos seekoff(
- streamoff off,
- std::ios::seekdir way,
- std::ios::openmode which);
+ virtual streampos seekoff(
+ streamoff off,
+ std::ios::seekdir way,
+ std::ios::openmode which);
#endif
- /*
- * @brief Get s sequence of characters from the input
- *
- * @param dst Pointer to a block of memory to accept the characters
- * @param length Number of characters to be read
- * @return Returns the number of characters read
- */
- //virtual streamsize xsgetn(char* dst, streamsize length);
-
- /*
- * @brief Write some characters to output
- *
- * @param src Pointer to a sequence of characters to be output
- * @param length Number of characters to be put
- * @return Returns the number of characters written
- */
- //virtual streamsize xsputn(char* src, streamsize length);
- //@}
+ /*
+ * @brief Get s sequence of characters from the input
+ *
+ * @param dst Pointer to a block of memory to accept the characters
+ * @param length Number of characters to be read
+ * @return Returns the number of characters read
+ */
+ //virtual streamsize xsgetn(char* dst, streamsize length);
+
+ /*
+ * @brief Write some characters to output
+ *
+ * @param src Pointer to a sequence of characters to be output
+ * @param length Number of characters to be put
+ * @return Returns the number of characters written
+ */
+ //virtual streamsize xsputn(char* src, streamsize length);
+ //@}
protected:
- // This channels we are working on.
- LLChannelDescriptors mChannels;
+ // This channels we are working on.
+ LLChannelDescriptors mChannels;
- // The buffer we work on
- LLBufferArray* mBuffer;
+ // The buffer we work on
+ LLBufferArray* mBuffer;
};
-/**
+/**
* @class LLBufferStream
* @brief This implements an istream based wrapper around an LLBufferArray.
*
@@ -139,13 +139,13 @@ protected:
class LLBufferStream : public std::iostream
{
public:
- LLBufferStream(
- const LLChannelDescriptors& channels,
- LLBufferArray* buffer);
- ~LLBufferStream();
+ LLBufferStream(
+ const LLChannelDescriptors& channels,
+ LLBufferArray* buffer);
+ ~LLBufferStream();
protected:
- LLBufferStreamBuf mStreamBuf;
+ LLBufferStreamBuf mStreamBuf;
};
diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp
index 5b4f9aded7..cb654f5a30 100644
--- a/indra/llmessage/llcachename.cpp
+++ b/indra/llmessage/llcachename.cpp
@@ -1,1021 +1,1021 @@
-/**
- * @file llcachename.cpp
- * @brief A hierarchical cache of first and last names queried based on UUID.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llcachename.h"
-
-// linden library includes
-#include "lldbstrings.h"
-#include "llframetimer.h"
-#include "llhost.h"
-#include "llrand.h"
-#include "llsdserialize.h"
-#include "lluuid.h"
-#include "message.h"
-
-#include <boost/regex.hpp>
-
-// llsd serialization constants
-static const std::string AGENTS("agents");
-static const std::string GROUPS("groups");
-static const std::string CTIME("ctime");
-static const std::string FIRST("first");
-static const std::string LAST("last");
-static const std::string NAME("name");
-
-// We track name requests in flight for up to this long.
-// We won't re-request a name during this time
-const U32 PENDING_TIMEOUT_SECS = 5 * 60;
-
-// Globals
-LLCacheName* gCacheName = NULL;
-std::map<std::string, std::string> LLCacheName::sCacheName;
-
-/// ---------------------------------------------------------------------------
-/// class LLCacheNameEntry
-/// ---------------------------------------------------------------------------
-
-class LLCacheNameEntry
-{
-public:
- LLCacheNameEntry();
-
-public:
- bool mIsGroup;
- U32 mCreateTime; // unix time_t
- // IDEVO TODO collapse names to one field, which will eliminate
- // many string compares on "Resident"
- std::string mFirstName;
- std::string mLastName;
- std::string mGroupName;
-};
-
-LLCacheNameEntry::LLCacheNameEntry()
- : mIsGroup(false),
- mCreateTime(0)
-{
-}
-
-
-class PendingReply
-{
-public:
- LLUUID mID;
- LLCacheNameSignal mSignal;
- LLHost mHost;
-
- PendingReply(const LLUUID& id, const LLHost& host)
- : mID(id), mHost(host)
- {
- }
-
- boost::signals2::connection setCallback(const LLCacheNameCallback& cb)
- {
- return mSignal.connect(cb);
- }
-
- void done() { mID.setNull(); }
- bool isDone() const { return mID.isNull(); }
-};
-
-class ReplySender
-{
-public:
- ReplySender(LLMessageSystem* msg);
- ~ReplySender();
-
- void send(const LLUUID& id,
- const LLCacheNameEntry& entry, const LLHost& host);
-
-private:
- void flush();
-
- LLMessageSystem* mMsg;
- bool mPending;
- bool mCurrIsGroup;
- LLHost mCurrHost;
-};
-
-ReplySender::ReplySender(LLMessageSystem* msg)
- : mMsg(msg), mPending(false), mCurrIsGroup(false)
-{ }
-
-ReplySender::~ReplySender()
-{
- flush();
-}
-
-void ReplySender::send(const LLUUID& id,
- const LLCacheNameEntry& entry, const LLHost& host)
-{
- if (mPending)
- {
- if (mCurrIsGroup != entry.mIsGroup
- || mCurrHost != host)
- {
- flush();
- }
- }
-
- if (!mPending)
- {
- mPending = true;
- mCurrIsGroup = entry.mIsGroup;
- mCurrHost = host;
-
- if(mCurrIsGroup)
- mMsg->newMessageFast(_PREHASH_UUIDGroupNameReply);
- else
- mMsg->newMessageFast(_PREHASH_UUIDNameReply);
- }
-
- mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
- mMsg->addUUIDFast(_PREHASH_ID, id);
- if(mCurrIsGroup)
- {
- mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName);
- }
- else
- {
- mMsg->addStringFast(_PREHASH_FirstName, entry.mFirstName);
- mMsg->addStringFast(_PREHASH_LastName, entry.mLastName);
- }
-
- if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
- {
- flush();
- }
-}
-
-void ReplySender::flush()
-{
- if (mPending)
- {
- mMsg->sendReliable(mCurrHost);
- mPending = false;
- }
-}
-
-
-typedef std::set<LLUUID> AskQueue;
-typedef std::list<PendingReply*> ReplyQueue;
-typedef std::map<LLUUID,U32> PendingQueue;
-typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
-typedef std::map<std::string, LLUUID> ReverseCache;
-
-class LLCacheName::Impl
-{
-public:
- LLMessageSystem* mMsg;
- LLHost mUpstreamHost;
-
- Cache mCache;
- // the map of UUIDs to names
- ReverseCache mReverseCache;
- // map of names to UUIDs
-
- AskQueue mAskNameQueue;
- AskQueue mAskGroupQueue;
- // UUIDs to ask our upstream host about
-
- PendingQueue mPendingQueue;
- // UUIDs that have been requested but are not in cache yet.
-
- ReplyQueue mReplyQueue;
- // requests awaiting replies from us
-
- LLCacheNameSignal mSignal;
-
- LLFrameTimer mProcessTimer;
-
- Impl(LLMessageSystem* msg);
- ~Impl();
-
- bool getName(const LLUUID& id, std::string& first, std::string& last);
-
- boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
- void addPending(const LLUUID& id, const LLHost& host);
-
- void processPendingAsks();
- void processPendingReplies();
- void sendRequest(const char* msg_name, const AskQueue& queue);
- bool isRequestPending(const LLUUID& id);
-
- // Message system callbacks.
- void processUUIDRequest(LLMessageSystem* msg, bool isGroup);
- void processUUIDReply(LLMessageSystem* msg, bool isGroup);
-
- static void handleUUIDNameRequest(LLMessageSystem* msg, void** userdata);
- static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata);
- static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata);
- static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata);
-};
-
-
-/// --------------------------------------------------------------------------
-/// class LLCacheName
-/// ---------------------------------------------------------------------------
-
-LLCacheName::LLCacheName(LLMessageSystem* msg)
- : impl(* new Impl(msg))
- { }
-
-LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host)
- : impl(* new Impl(msg))
-{
- sCacheName["waiting"] = "(Loading...)";
- sCacheName["nobody"] = "(nobody)";
- sCacheName["none"] = "(none)";
- setUpstream(upstream_host);
-}
-
-LLCacheName::~LLCacheName()
-{
- delete &impl;
-}
-
-LLCacheName::Impl::Impl(LLMessageSystem* msg)
- : mMsg(msg), mUpstreamHost(LLHost())
-{
- mMsg->setHandlerFuncFast(
- _PREHASH_UUIDNameRequest, handleUUIDNameRequest, (void**)this);
- mMsg->setHandlerFuncFast(
- _PREHASH_UUIDNameReply, handleUUIDNameReply, (void**)this);
- mMsg->setHandlerFuncFast(
- _PREHASH_UUIDGroupNameRequest, handleUUIDGroupNameRequest, (void**)this);
- mMsg->setHandlerFuncFast(
- _PREHASH_UUIDGroupNameReply, handleUUIDGroupNameReply, (void**)this);
-}
-
-
-LLCacheName::Impl::~Impl()
-{
- for_each(mCache.begin(), mCache.end(), DeletePairedPointer());
- mCache.clear();
- for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer());
- mReplyQueue.clear();
-}
-
-boost::signals2::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback)
-{
- PendingReply* reply = new PendingReply(id, LLHost());
- boost::signals2::connection res = reply->setCallback(callback);
- mReplyQueue.push_back(reply);
- return res;
-}
-
-void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host)
-{
- PendingReply* reply = new PendingReply(id, host);
- mReplyQueue.push_back(reply);
-}
-
-void LLCacheName::setUpstream(const LLHost& upstream_host)
-{
- impl.mUpstreamHost = upstream_host;
-}
-
-boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& callback)
-{
- return impl.mSignal.connect(callback);
-}
-
-bool LLCacheName::importFile(std::istream& istr)
-{
- LLSD data;
- if(LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
- {
- return false;
- }
-
- // We'll expire entries more than a week old
- U32 now = (U32)time(NULL);
- const U32 SECS_PER_DAY = 60 * 60 * 24;
- U32 delete_before_time = now - (7 * SECS_PER_DAY);
-
- // iterate over the agents
- S32 count = 0;
- LLSD agents = data[AGENTS];
- LLSD::map_iterator iter = agents.beginMap();
- LLSD::map_iterator end = agents.endMap();
- for( ; iter != end; ++iter)
- {
- LLUUID id((*iter).first);
- LLSD agent = (*iter).second;
- U32 ctime = (U32)agent[CTIME].asInteger();
- if(ctime < delete_before_time) continue;
-
- LLCacheNameEntry* entry = new LLCacheNameEntry();
- entry->mIsGroup = false;
- entry->mCreateTime = ctime;
- entry->mFirstName = agent[FIRST].asString();
- entry->mLastName = agent[LAST].asString();
- impl.mCache[id] = entry;
- std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
- impl.mReverseCache[fullname] = id;
-
- ++count;
- }
- LL_INFOS() << "LLCacheName loaded " << count << " agent names" << LL_ENDL;
-
- count = 0;
- LLSD groups = data[GROUPS];
- iter = groups.beginMap();
- end = groups.endMap();
- for( ; iter != end; ++iter)
- {
- LLUUID id((*iter).first);
- LLSD group = (*iter).second;
- U32 ctime = (U32)group[CTIME].asInteger();
- if(ctime < delete_before_time) continue;
-
- LLCacheNameEntry* entry = new LLCacheNameEntry();
- entry->mIsGroup = true;
- entry->mCreateTime = ctime;
- entry->mGroupName = group[NAME].asString();
- impl.mCache[id] = entry;
- impl.mReverseCache[entry->mGroupName] = id;
- ++count;
- }
- LL_INFOS() << "LLCacheName loaded " << count << " group names" << LL_ENDL;
- return true;
-}
-
-void LLCacheName::exportFile(std::ostream& ostr)
-{
- LLSD data;
- Cache::iterator iter = impl.mCache.begin();
- Cache::iterator end = impl.mCache.end();
- for( ; iter != end; ++iter)
- {
- // Only write entries for which we have valid data.
- LLCacheNameEntry* entry = iter->second;
- if(!entry
- || (std::string::npos != entry->mFirstName.find('?'))
- || (std::string::npos != entry->mGroupName.find('?')))
- {
- continue;
- }
-
- // store it
- LLUUID id = iter->first;
- std::string id_str = id.asString();
- // IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
- if(!entry->mFirstName.empty() && !entry->mLastName.empty())
- {
- data[AGENTS][id_str][FIRST] = entry->mFirstName;
- data[AGENTS][id_str][LAST] = entry->mLastName;
- data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
- }
- else if(entry->mIsGroup && !entry->mGroupName.empty())
- {
- data[GROUPS][id_str][NAME] = entry->mGroupName;
- data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
- }
- }
-
- LLSDSerialize::toPrettyXML(data, ostr);
-}
-
-
-bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
-{
- if(id.isNull())
- {
- first = sCacheName["nobody"];
- last.clear();
- return true;
- }
-
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
- if (entry)
- {
- first = entry->mFirstName;
- last = entry->mLastName;
- return true;
- }
- else
- {
- first = sCacheName["waiting"];
- last.clear();
- if (!isRequestPending(id))
- {
- mAskNameQueue.insert(id);
- }
- return false;
- }
-
-}
-
-// static
-void LLCacheName::localizeCacheName(std::string key, std::string value)
-{
- if (key!="" && value!= "" )
- sCacheName[key]=value;
- else
- LL_WARNS()<< " Error localizing cache key " << key << " To "<< value<<LL_ENDL;
-}
-
-bool LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
-{
- std::string first_name, last_name;
- bool res = impl.getName(id, first_name, last_name);
- fullname = buildFullName(first_name, last_name);
- return res;
-}
-
-
-
-bool LLCacheName::getGroupName(const LLUUID& id, std::string& group)
-{
- if(id.isNull())
- {
- group = sCacheName["none"];
- return true;
- }
-
- LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id);
- if (entry && entry->mGroupName.empty())
- {
- // COUNTER-HACK to combat James' HACK in exportFile()...
- // this group name was loaded from a name cache that did not
- // bother to save the group name ==> we must ask for it
- LL_DEBUGS() << "LLCacheName queuing HACK group request: " << id << LL_ENDL;
- entry = NULL;
- }
-
- if (entry)
- {
- group = entry->mGroupName;
- return true;
- }
- else
- {
- group = sCacheName["waiting"];
- if (!impl.isRequestPending(id))
- {
- impl.mAskGroupQueue.insert(id);
- }
- return false;
- }
-}
-
-bool LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
-{
- std::string full_name = buildFullName(first, last);
- return getUUID(full_name, id);
-}
-
-bool LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
-{
- ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
- if (iter != impl.mReverseCache.end())
- {
- id = iter->second;
- return true;
- }
- else
- {
- return false;
- }
-}
-
-//static
-std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
-{
- std::string fullname = first;
- if (!last.empty()
- && last != "Resident")
- {
- fullname += ' ';
- fullname += last;
- }
- return fullname;
-}
-
-//static
-std::string LLCacheName::cleanFullName(const std::string& full_name)
-{
- return full_name.substr(0, full_name.find(" Resident"));
-}
-
-//static
-// Transform hard-coded name provided by server to a more legible username
-std::string LLCacheName::buildUsername(const std::string& full_name)
-{
- // rare, but handle hard-coded error names returned from server
- if (full_name == "(\?\?\?) (\?\?\?)")
- {
- return "(\?\?\?)";
- }
-
- std::string::size_type index = full_name.find(' ');
-
- if (index != std::string::npos)
- {
- std::string username;
- username = full_name.substr(0, index);
- std::string lastname = full_name.substr(index+1);
-
- if (lastname != "Resident")
- {
- username = username + "." + lastname;
- }
-
- LLStringUtil::toLower(username);
- return username;
- }
-
- // if the input wasn't a correctly formatted legacy name, just return it
- // cleaned up from a potential terminal "Resident"
- std::string clean_name = cleanFullName(full_name);
- LLStringUtil::toLower(clean_name);
- return clean_name;
-}
-
-//static
-std::string LLCacheName::buildLegacyName(const std::string& complete_name)
-{
- //boost::regexp was showing up in the crashreporter, so doing
- //painfully manual parsing using substr. LF
- S32 open_paren = complete_name.rfind(" (");
- S32 close_paren = complete_name.rfind(')');
-
- if (open_paren != std::string::npos &&
- close_paren == complete_name.length()-1)
- {
- S32 length = close_paren - open_paren - 2;
- std::string legacy_name = complete_name.substr(open_paren+2, length);
-
- if (legacy_name.length() > 0)
- {
- std::string cap_letter = legacy_name.substr(0, 1);
- LLStringUtil::toUpper(cap_letter);
- legacy_name = cap_letter + legacy_name.substr(1);
-
- S32 separator = legacy_name.find('.');
-
- if (separator != std::string::npos)
- {
- std::string last_name = legacy_name.substr(separator+1);
- legacy_name = legacy_name.substr(0, separator);
-
- if (last_name.length() > 0)
- {
- cap_letter = last_name.substr(0, 1);
- LLStringUtil::toUpper(cap_letter);
- legacy_name = legacy_name + " " + cap_letter + last_name.substr(1);
- }
- }
-
- return legacy_name;
- }
- }
-
- return complete_name;
-}
-
-// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
-// The reason it is a slot is so that the legacy get() function below can bind an old callback
-// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
-// doesn't get lost. As a result, we have to bind the slot to a signal to call it, even when
-// we call it immediately. -Steve
-// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
-// potential need for any parsing should any code need to handle first and last name independently.
-boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
-{
- boost::signals2::connection res;
-
- if(id.isNull())
- {
- LLCacheNameSignal signal;
- signal.connect(callback);
- signal(id, sCacheName["nobody"], is_group);
- return res;
- }
-
- LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
- if (entry)
- {
- LLCacheNameSignal signal;
- signal.connect(callback);
- // id found in map therefore we can call the callback immediately.
- if (entry->mIsGroup)
- {
- signal(id, entry->mGroupName, entry->mIsGroup);
- }
- else
- {
- std::string fullname =
- buildFullName(entry->mFirstName, entry->mLastName);
- signal(id, fullname, entry->mIsGroup);
- }
- }
- else
- {
- // id not found in map so we must queue the callback call until available.
- if (!impl.isRequestPending(id))
- {
- if (is_group)
- {
- impl.mAskGroupQueue.insert(id);
- }
- else
- {
- impl.mAskNameQueue.insert(id);
- }
- }
- res = impl.addPending(id, callback);
- }
- return res;
-}
-
-boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
- const LLCacheNameCallback& callback)
-{
- return get(group_id, true, callback);
-}
-
-boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
-{
- return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
-}
-
-void LLCacheName::processPending()
-{
- const F32 SECS_BETWEEN_PROCESS = 0.1f;
- if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS))
- {
- return;
- }
-
- if(!impl.mUpstreamHost.isOk())
- {
- LL_DEBUGS() << "LLCacheName::processPending() - bad upstream host."
- << LL_ENDL;
- return;
- }
-
- impl.processPendingAsks();
- impl.processPendingReplies();
-}
-
-void LLCacheName::deleteEntriesOlderThan(S32 secs)
-{
- U32 now = (U32)time(NULL);
- U32 expire_time = now - secs;
- for(Cache::iterator iter = impl.mCache.begin(); iter != impl.mCache.end(); )
- {
- Cache::iterator curiter = iter++;
- LLCacheNameEntry* entry = curiter->second;
- if (entry->mCreateTime < expire_time)
- {
- delete entry;
- impl.mCache.erase(curiter);
- }
- }
-
- // These are pending requests that we never heard back from.
- U32 pending_expire_time = now - PENDING_TIMEOUT_SECS;
- for(PendingQueue::iterator p_iter = impl.mPendingQueue.begin();
- p_iter != impl.mPendingQueue.end(); )
- {
- PendingQueue::iterator p_curitor = p_iter++;
-
- if (p_curitor->second < pending_expire_time)
- {
- impl.mPendingQueue.erase(p_curitor);
- }
- }
-}
-
-
-void LLCacheName::dump()
-{
- for (Cache::iterator iter = impl.mCache.begin(),
- end = impl.mCache.end();
- iter != end; iter++)
- {
- LLCacheNameEntry* entry = iter->second;
- if (entry->mIsGroup)
- {
- LL_INFOS()
- << iter->first << " = (group) "
- << entry->mGroupName
- << " @ " << entry->mCreateTime
- << LL_ENDL;
- }
- else
- {
- LL_INFOS()
- << iter->first << " = "
- << buildFullName(entry->mFirstName, entry->mLastName)
- << " @ " << entry->mCreateTime
- << LL_ENDL;
- }
- }
-}
-
-void LLCacheName::dumpStats()
-{
- LL_INFOS() << "Queue sizes: "
- << " Cache=" << impl.mCache.size()
- << " AskName=" << impl.mAskNameQueue.size()
- << " AskGroup=" << impl.mAskGroupQueue.size()
- << " Pending=" << impl.mPendingQueue.size()
- << " Reply=" << impl.mReplyQueue.size()
-// << " Observers=" << impl.mSignal.size()
- << LL_ENDL;
-}
-
-void LLCacheName::clear()
-{
- for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
- impl.mCache.clear();
-}
-
-//static
-std::string LLCacheName::getDefaultName()
-{
- return sCacheName["waiting"];
-}
-
-//static
-std::string LLCacheName::getDefaultLastName()
-{
- return "Resident";
-}
-
-void LLCacheName::Impl::processPendingAsks()
-{
- sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
- sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue);
- mAskNameQueue.clear();
- mAskGroupQueue.clear();
-}
-
-void LLCacheName::Impl::processPendingReplies()
-{
- // First call all the callbacks, because they might send messages.
- for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
- {
- PendingReply* reply = *it;
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
- if(!entry) continue;
-
- if (!entry->mIsGroup)
- {
- std::string fullname =
- LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
- (reply->mSignal)(reply->mID, fullname, false);
- }
- else
- {
- (reply->mSignal)(reply->mID, entry->mGroupName, true);
- }
- }
-
- // Forward on all replies, if needed.
- ReplySender sender(mMsg);
- for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
- {
- PendingReply* reply = *it;
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
- if(!entry) continue;
-
- if (reply->mHost.isOk())
- {
- sender.send(reply->mID, *entry, reply->mHost);
- }
-
- reply->done();
- }
-
- for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); )
- {
- ReplyQueue::iterator curit = it++;
- PendingReply* reply = *curit;
- if (reply->isDone())
- {
- delete reply;
- mReplyQueue.erase(curit);
- }
- }
-}
-
-
-void LLCacheName::Impl::sendRequest(
- const char* msg_name,
- const AskQueue& queue)
-{
- if(queue.empty())
- {
- return;
- }
-
- bool start_new_message = true;
- AskQueue::const_iterator it = queue.begin();
- AskQueue::const_iterator end = queue.end();
- for(; it != end; ++it)
- {
- if(start_new_message)
- {
- start_new_message = false;
- mMsg->newMessageFast(msg_name);
- }
- mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
- mMsg->addUUIDFast(_PREHASH_ID, (*it));
-
- if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
- {
- start_new_message = true;
- mMsg->sendReliable(mUpstreamHost);
- }
- }
- if(!start_new_message)
- {
- mMsg->sendReliable(mUpstreamHost);
- }
-}
-
-bool LLCacheName::Impl::isRequestPending(const LLUUID& id)
-{
- U32 now = (U32)time(NULL);
- U32 expire_time = now - PENDING_TIMEOUT_SECS;
-
- PendingQueue::iterator iter = mPendingQueue.find(id);
-
- if (iter == mPendingQueue.end()
- || (iter->second < expire_time) )
- {
- mPendingQueue[id] = now;
- return false;
- }
-
- return true;
-}
-
-void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
-{
- // You should only get this message if the cache is at the simulator
- // level, hence having an upstream provider.
- if (!mUpstreamHost.isOk())
- {
- LL_WARNS() << "LLCacheName - got UUID name/group request, but no upstream provider!" << LL_ENDL;
- return;
- }
-
- LLHost fromHost = msg->getSender();
- ReplySender sender(msg);
-
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_UUIDNameBlock);
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID id;
- msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
- if(entry)
- {
- if (isGroup != entry->mIsGroup)
- {
- LL_WARNS() << "LLCacheName - Asked for "
- << (isGroup ? "group" : "user") << " name, "
- << "but found "
- << (entry->mIsGroup ? "group" : "user")
- << ": " << id << LL_ENDL;
- }
- else
- {
- // ...it's in the cache, so send it as the reply
- sender.send(id, *entry, fromHost);
- }
- }
- else
- {
- if (!isRequestPending(id))
- {
- if (isGroup)
- {
- mAskGroupQueue.insert(id);
- }
- else
- {
- mAskNameQueue.insert(id);
- }
- }
-
- addPending(id, fromHost);
- }
- }
-}
-
-
-
-void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
-{
- S32 count = msg->getNumberOfBlocksFast(_PREHASH_UUIDNameBlock);
- for(S32 i = 0; i < count; ++i)
- {
- LLUUID id;
- msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
- LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
- if (!entry)
- {
- entry = new LLCacheNameEntry;
- mCache[id] = entry;
- }
-
- mPendingQueue.erase(id);
-
- entry->mIsGroup = isGroup;
- entry->mCreateTime = (U32)time(NULL);
- if (!isGroup)
- {
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i);
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, entry->mLastName, i);
- }
- else
- { // is group
- msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i);
- LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR);
- }
-
- if (!isGroup)
- {
- // NOTE: Very occasionally the server sends down a full name
- // in the first name field with an empty last name, for example,
- // first = "Ladanie1 Resident", last = "".
- // I cannot reproduce this, nor can I find a bug in the server code.
- // Ensure "Resident" does not appear via cleanFullName, because
- // buildFullName only checks last name. JC
- std::string full_name;
- if (entry->mLastName.empty())
- {
- full_name = cleanFullName(entry->mFirstName);
-
- //fix what we are putting in the cache
- entry->mFirstName = full_name;
- entry->mLastName = "Resident";
- }
- else
- {
- full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
- }
- mSignal(id, full_name, false);
- mReverseCache[full_name] = id;
- }
- else
- {
- mSignal(id, entry->mGroupName, true);
- mReverseCache[entry->mGroupName] = id;
- }
- }
-}
-
-
-
-// static call back functions
-
-void LLCacheName::Impl::handleUUIDNameReply(LLMessageSystem* msg, void** userData)
-{
- ((LLCacheName::Impl*)userData)->processUUIDReply(msg, false);
-}
-
-void LLCacheName::Impl::handleUUIDNameRequest(LLMessageSystem* msg, void** userData)
-{
- ((LLCacheName::Impl*)userData)->processUUIDRequest(msg, false);
-}
-
-void LLCacheName::Impl::handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userData)
-{
- ((LLCacheName::Impl*)userData)->processUUIDRequest(msg, true);
-}
-
-void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** userData)
-{
- ((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
-}
+/**
+ * @file llcachename.cpp
+ * @brief A hierarchical cache of first and last names queried based on UUID.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llcachename.h"
+
+// linden library includes
+#include "lldbstrings.h"
+#include "llframetimer.h"
+#include "llhost.h"
+#include "llrand.h"
+#include "llsdserialize.h"
+#include "lluuid.h"
+#include "message.h"
+
+#include <boost/regex.hpp>
+
+// llsd serialization constants
+static const std::string AGENTS("agents");
+static const std::string GROUPS("groups");
+static const std::string CTIME("ctime");
+static const std::string FIRST("first");
+static const std::string LAST("last");
+static const std::string NAME("name");
+
+// We track name requests in flight for up to this long.
+// We won't re-request a name during this time
+const U32 PENDING_TIMEOUT_SECS = 5 * 60;
+
+// Globals
+LLCacheName* gCacheName = NULL;
+std::map<std::string, std::string> LLCacheName::sCacheName;
+
+/// ---------------------------------------------------------------------------
+/// class LLCacheNameEntry
+/// ---------------------------------------------------------------------------
+
+class LLCacheNameEntry
+{
+public:
+ LLCacheNameEntry();
+
+public:
+ bool mIsGroup;
+ U32 mCreateTime; // unix time_t
+ // IDEVO TODO collapse names to one field, which will eliminate
+ // many string compares on "Resident"
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mGroupName;
+};
+
+LLCacheNameEntry::LLCacheNameEntry()
+ : mIsGroup(false),
+ mCreateTime(0)
+{
+}
+
+
+class PendingReply
+{
+public:
+ LLUUID mID;
+ LLCacheNameSignal mSignal;
+ LLHost mHost;
+
+ PendingReply(const LLUUID& id, const LLHost& host)
+ : mID(id), mHost(host)
+ {
+ }
+
+ boost::signals2::connection setCallback(const LLCacheNameCallback& cb)
+ {
+ return mSignal.connect(cb);
+ }
+
+ void done() { mID.setNull(); }
+ bool isDone() const { return mID.isNull(); }
+};
+
+class ReplySender
+{
+public:
+ ReplySender(LLMessageSystem* msg);
+ ~ReplySender();
+
+ void send(const LLUUID& id,
+ const LLCacheNameEntry& entry, const LLHost& host);
+
+private:
+ void flush();
+
+ LLMessageSystem* mMsg;
+ bool mPending;
+ bool mCurrIsGroup;
+ LLHost mCurrHost;
+};
+
+ReplySender::ReplySender(LLMessageSystem* msg)
+ : mMsg(msg), mPending(false), mCurrIsGroup(false)
+{ }
+
+ReplySender::~ReplySender()
+{
+ flush();
+}
+
+void ReplySender::send(const LLUUID& id,
+ const LLCacheNameEntry& entry, const LLHost& host)
+{
+ if (mPending)
+ {
+ if (mCurrIsGroup != entry.mIsGroup
+ || mCurrHost != host)
+ {
+ flush();
+ }
+ }
+
+ if (!mPending)
+ {
+ mPending = true;
+ mCurrIsGroup = entry.mIsGroup;
+ mCurrHost = host;
+
+ if(mCurrIsGroup)
+ mMsg->newMessageFast(_PREHASH_UUIDGroupNameReply);
+ else
+ mMsg->newMessageFast(_PREHASH_UUIDNameReply);
+ }
+
+ mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
+ mMsg->addUUIDFast(_PREHASH_ID, id);
+ if(mCurrIsGroup)
+ {
+ mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName);
+ }
+ else
+ {
+ mMsg->addStringFast(_PREHASH_FirstName, entry.mFirstName);
+ mMsg->addStringFast(_PREHASH_LastName, entry.mLastName);
+ }
+
+ if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
+ {
+ flush();
+ }
+}
+
+void ReplySender::flush()
+{
+ if (mPending)
+ {
+ mMsg->sendReliable(mCurrHost);
+ mPending = false;
+ }
+}
+
+
+typedef std::set<LLUUID> AskQueue;
+typedef std::list<PendingReply*> ReplyQueue;
+typedef std::map<LLUUID,U32> PendingQueue;
+typedef std::map<LLUUID, LLCacheNameEntry*> Cache;
+typedef std::map<std::string, LLUUID> ReverseCache;
+
+class LLCacheName::Impl
+{
+public:
+ LLMessageSystem* mMsg;
+ LLHost mUpstreamHost;
+
+ Cache mCache;
+ // the map of UUIDs to names
+ ReverseCache mReverseCache;
+ // map of names to UUIDs
+
+ AskQueue mAskNameQueue;
+ AskQueue mAskGroupQueue;
+ // UUIDs to ask our upstream host about
+
+ PendingQueue mPendingQueue;
+ // UUIDs that have been requested but are not in cache yet.
+
+ ReplyQueue mReplyQueue;
+ // requests awaiting replies from us
+
+ LLCacheNameSignal mSignal;
+
+ LLFrameTimer mProcessTimer;
+
+ Impl(LLMessageSystem* msg);
+ ~Impl();
+
+ bool getName(const LLUUID& id, std::string& first, std::string& last);
+
+ boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
+ void addPending(const LLUUID& id, const LLHost& host);
+
+ void processPendingAsks();
+ void processPendingReplies();
+ void sendRequest(const char* msg_name, const AskQueue& queue);
+ bool isRequestPending(const LLUUID& id);
+
+ // Message system callbacks.
+ void processUUIDRequest(LLMessageSystem* msg, bool isGroup);
+ void processUUIDReply(LLMessageSystem* msg, bool isGroup);
+
+ static void handleUUIDNameRequest(LLMessageSystem* msg, void** userdata);
+ static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata);
+ static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata);
+ static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata);
+};
+
+
+/// --------------------------------------------------------------------------
+/// class LLCacheName
+/// ---------------------------------------------------------------------------
+
+LLCacheName::LLCacheName(LLMessageSystem* msg)
+ : impl(* new Impl(msg))
+ { }
+
+LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host)
+ : impl(* new Impl(msg))
+{
+ sCacheName["waiting"] = "(Loading...)";
+ sCacheName["nobody"] = "(nobody)";
+ sCacheName["none"] = "(none)";
+ setUpstream(upstream_host);
+}
+
+LLCacheName::~LLCacheName()
+{
+ delete &impl;
+}
+
+LLCacheName::Impl::Impl(LLMessageSystem* msg)
+ : mMsg(msg), mUpstreamHost(LLHost())
+{
+ mMsg->setHandlerFuncFast(
+ _PREHASH_UUIDNameRequest, handleUUIDNameRequest, (void**)this);
+ mMsg->setHandlerFuncFast(
+ _PREHASH_UUIDNameReply, handleUUIDNameReply, (void**)this);
+ mMsg->setHandlerFuncFast(
+ _PREHASH_UUIDGroupNameRequest, handleUUIDGroupNameRequest, (void**)this);
+ mMsg->setHandlerFuncFast(
+ _PREHASH_UUIDGroupNameReply, handleUUIDGroupNameReply, (void**)this);
+}
+
+
+LLCacheName::Impl::~Impl()
+{
+ for_each(mCache.begin(), mCache.end(), DeletePairedPointer());
+ mCache.clear();
+ for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer());
+ mReplyQueue.clear();
+}
+
+boost::signals2::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback)
+{
+ PendingReply* reply = new PendingReply(id, LLHost());
+ boost::signals2::connection res = reply->setCallback(callback);
+ mReplyQueue.push_back(reply);
+ return res;
+}
+
+void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host)
+{
+ PendingReply* reply = new PendingReply(id, host);
+ mReplyQueue.push_back(reply);
+}
+
+void LLCacheName::setUpstream(const LLHost& upstream_host)
+{
+ impl.mUpstreamHost = upstream_host;
+}
+
+boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& callback)
+{
+ return impl.mSignal.connect(callback);
+}
+
+bool LLCacheName::importFile(std::istream& istr)
+{
+ LLSD data;
+ if(LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
+ {
+ return false;
+ }
+
+ // We'll expire entries more than a week old
+ U32 now = (U32)time(NULL);
+ const U32 SECS_PER_DAY = 60 * 60 * 24;
+ U32 delete_before_time = now - (7 * SECS_PER_DAY);
+
+ // iterate over the agents
+ S32 count = 0;
+ LLSD agents = data[AGENTS];
+ LLSD::map_iterator iter = agents.beginMap();
+ LLSD::map_iterator end = agents.endMap();
+ for( ; iter != end; ++iter)
+ {
+ LLUUID id((*iter).first);
+ LLSD agent = (*iter).second;
+ U32 ctime = (U32)agent[CTIME].asInteger();
+ if(ctime < delete_before_time) continue;
+
+ LLCacheNameEntry* entry = new LLCacheNameEntry();
+ entry->mIsGroup = false;
+ entry->mCreateTime = ctime;
+ entry->mFirstName = agent[FIRST].asString();
+ entry->mLastName = agent[LAST].asString();
+ impl.mCache[id] = entry;
+ std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
+ impl.mReverseCache[fullname] = id;
+
+ ++count;
+ }
+ LL_INFOS() << "LLCacheName loaded " << count << " agent names" << LL_ENDL;
+
+ count = 0;
+ LLSD groups = data[GROUPS];
+ iter = groups.beginMap();
+ end = groups.endMap();
+ for( ; iter != end; ++iter)
+ {
+ LLUUID id((*iter).first);
+ LLSD group = (*iter).second;
+ U32 ctime = (U32)group[CTIME].asInteger();
+ if(ctime < delete_before_time) continue;
+
+ LLCacheNameEntry* entry = new LLCacheNameEntry();
+ entry->mIsGroup = true;
+ entry->mCreateTime = ctime;
+ entry->mGroupName = group[NAME].asString();
+ impl.mCache[id] = entry;
+ impl.mReverseCache[entry->mGroupName] = id;
+ ++count;
+ }
+ LL_INFOS() << "LLCacheName loaded " << count << " group names" << LL_ENDL;
+ return true;
+}
+
+void LLCacheName::exportFile(std::ostream& ostr)
+{
+ LLSD data;
+ Cache::iterator iter = impl.mCache.begin();
+ Cache::iterator end = impl.mCache.end();
+ for( ; iter != end; ++iter)
+ {
+ // Only write entries for which we have valid data.
+ LLCacheNameEntry* entry = iter->second;
+ if(!entry
+ || (std::string::npos != entry->mFirstName.find('?'))
+ || (std::string::npos != entry->mGroupName.find('?')))
+ {
+ continue;
+ }
+
+ // store it
+ LLUUID id = iter->first;
+ std::string id_str = id.asString();
+ // IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
+ if(!entry->mFirstName.empty() && !entry->mLastName.empty())
+ {
+ data[AGENTS][id_str][FIRST] = entry->mFirstName;
+ data[AGENTS][id_str][LAST] = entry->mLastName;
+ data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;
+ }
+ else if(entry->mIsGroup && !entry->mGroupName.empty())
+ {
+ data[GROUPS][id_str][NAME] = entry->mGroupName;
+ data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime;
+ }
+ }
+
+ LLSDSerialize::toPrettyXML(data, ostr);
+}
+
+
+bool LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
+{
+ if(id.isNull())
+ {
+ first = sCacheName["nobody"];
+ last.clear();
+ return true;
+ }
+
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
+ if (entry)
+ {
+ first = entry->mFirstName;
+ last = entry->mLastName;
+ return true;
+ }
+ else
+ {
+ first = sCacheName["waiting"];
+ last.clear();
+ if (!isRequestPending(id))
+ {
+ mAskNameQueue.insert(id);
+ }
+ return false;
+ }
+
+}
+
+// static
+void LLCacheName::localizeCacheName(std::string key, std::string value)
+{
+ if (key!="" && value!= "" )
+ sCacheName[key]=value;
+ else
+ LL_WARNS()<< " Error localizing cache key " << key << " To "<< value<<LL_ENDL;
+}
+
+bool LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
+{
+ std::string first_name, last_name;
+ bool res = impl.getName(id, first_name, last_name);
+ fullname = buildFullName(first_name, last_name);
+ return res;
+}
+
+
+
+bool LLCacheName::getGroupName(const LLUUID& id, std::string& group)
+{
+ if(id.isNull())
+ {
+ group = sCacheName["none"];
+ return true;
+ }
+
+ LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id);
+ if (entry && entry->mGroupName.empty())
+ {
+ // COUNTER-HACK to combat James' HACK in exportFile()...
+ // this group name was loaded from a name cache that did not
+ // bother to save the group name ==> we must ask for it
+ LL_DEBUGS() << "LLCacheName queuing HACK group request: " << id << LL_ENDL;
+ entry = NULL;
+ }
+
+ if (entry)
+ {
+ group = entry->mGroupName;
+ return true;
+ }
+ else
+ {
+ group = sCacheName["waiting"];
+ if (!impl.isRequestPending(id))
+ {
+ impl.mAskGroupQueue.insert(id);
+ }
+ return false;
+ }
+}
+
+bool LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
+{
+ std::string full_name = buildFullName(first, last);
+ return getUUID(full_name, id);
+}
+
+bool LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
+{
+ ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
+ if (iter != impl.mReverseCache.end())
+ {
+ id = iter->second;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+//static
+std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
+{
+ std::string fullname = first;
+ if (!last.empty()
+ && last != "Resident")
+ {
+ fullname += ' ';
+ fullname += last;
+ }
+ return fullname;
+}
+
+//static
+std::string LLCacheName::cleanFullName(const std::string& full_name)
+{
+ return full_name.substr(0, full_name.find(" Resident"));
+}
+
+//static
+// Transform hard-coded name provided by server to a more legible username
+std::string LLCacheName::buildUsername(const std::string& full_name)
+{
+ // rare, but handle hard-coded error names returned from server
+ if (full_name == "(\?\?\?) (\?\?\?)")
+ {
+ return "(\?\?\?)";
+ }
+
+ std::string::size_type index = full_name.find(' ');
+
+ if (index != std::string::npos)
+ {
+ std::string username;
+ username = full_name.substr(0, index);
+ std::string lastname = full_name.substr(index+1);
+
+ if (lastname != "Resident")
+ {
+ username = username + "." + lastname;
+ }
+
+ LLStringUtil::toLower(username);
+ return username;
+ }
+
+ // if the input wasn't a correctly formatted legacy name, just return it
+ // cleaned up from a potential terminal "Resident"
+ std::string clean_name = cleanFullName(full_name);
+ LLStringUtil::toLower(clean_name);
+ return clean_name;
+}
+
+//static
+std::string LLCacheName::buildLegacyName(const std::string& complete_name)
+{
+ //boost::regexp was showing up in the crashreporter, so doing
+ //painfully manual parsing using substr. LF
+ S32 open_paren = complete_name.rfind(" (");
+ S32 close_paren = complete_name.rfind(')');
+
+ if (open_paren != std::string::npos &&
+ close_paren == complete_name.length()-1)
+ {
+ S32 length = close_paren - open_paren - 2;
+ std::string legacy_name = complete_name.substr(open_paren+2, length);
+
+ if (legacy_name.length() > 0)
+ {
+ std::string cap_letter = legacy_name.substr(0, 1);
+ LLStringUtil::toUpper(cap_letter);
+ legacy_name = cap_letter + legacy_name.substr(1);
+
+ S32 separator = legacy_name.find('.');
+
+ if (separator != std::string::npos)
+ {
+ std::string last_name = legacy_name.substr(separator+1);
+ legacy_name = legacy_name.substr(0, separator);
+
+ if (last_name.length() > 0)
+ {
+ cap_letter = last_name.substr(0, 1);
+ LLStringUtil::toUpper(cap_letter);
+ legacy_name = legacy_name + " " + cap_letter + last_name.substr(1);
+ }
+ }
+
+ return legacy_name;
+ }
+ }
+
+ return complete_name;
+}
+
+// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
+// The reason it is a slot is so that the legacy get() function below can bind an old callback
+// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
+// doesn't get lost. As a result, we have to bind the slot to a signal to call it, even when
+// we call it immediately. -Steve
+// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
+// potential need for any parsing should any code need to handle first and last name independently.
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
+{
+ boost::signals2::connection res;
+
+ if(id.isNull())
+ {
+ LLCacheNameSignal signal;
+ signal.connect(callback);
+ signal(id, sCacheName["nobody"], is_group);
+ return res;
+ }
+
+ LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
+ if (entry)
+ {
+ LLCacheNameSignal signal;
+ signal.connect(callback);
+ // id found in map therefore we can call the callback immediately.
+ if (entry->mIsGroup)
+ {
+ signal(id, entry->mGroupName, entry->mIsGroup);
+ }
+ else
+ {
+ std::string fullname =
+ buildFullName(entry->mFirstName, entry->mLastName);
+ signal(id, fullname, entry->mIsGroup);
+ }
+ }
+ else
+ {
+ // id not found in map so we must queue the callback call until available.
+ if (!impl.isRequestPending(id))
+ {
+ if (is_group)
+ {
+ impl.mAskGroupQueue.insert(id);
+ }
+ else
+ {
+ impl.mAskNameQueue.insert(id);
+ }
+ }
+ res = impl.addPending(id, callback);
+ }
+ return res;
+}
+
+boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
+ const LLCacheNameCallback& callback)
+{
+ return get(group_id, true, callback);
+}
+
+boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
+{
+ return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
+}
+
+void LLCacheName::processPending()
+{
+ const F32 SECS_BETWEEN_PROCESS = 0.1f;
+ if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS))
+ {
+ return;
+ }
+
+ if(!impl.mUpstreamHost.isOk())
+ {
+ LL_DEBUGS() << "LLCacheName::processPending() - bad upstream host."
+ << LL_ENDL;
+ return;
+ }
+
+ impl.processPendingAsks();
+ impl.processPendingReplies();
+}
+
+void LLCacheName::deleteEntriesOlderThan(S32 secs)
+{
+ U32 now = (U32)time(NULL);
+ U32 expire_time = now - secs;
+ for(Cache::iterator iter = impl.mCache.begin(); iter != impl.mCache.end(); )
+ {
+ Cache::iterator curiter = iter++;
+ LLCacheNameEntry* entry = curiter->second;
+ if (entry->mCreateTime < expire_time)
+ {
+ delete entry;
+ impl.mCache.erase(curiter);
+ }
+ }
+
+ // These are pending requests that we never heard back from.
+ U32 pending_expire_time = now - PENDING_TIMEOUT_SECS;
+ for(PendingQueue::iterator p_iter = impl.mPendingQueue.begin();
+ p_iter != impl.mPendingQueue.end(); )
+ {
+ PendingQueue::iterator p_curitor = p_iter++;
+
+ if (p_curitor->second < pending_expire_time)
+ {
+ impl.mPendingQueue.erase(p_curitor);
+ }
+ }
+}
+
+
+void LLCacheName::dump()
+{
+ for (Cache::iterator iter = impl.mCache.begin(),
+ end = impl.mCache.end();
+ iter != end; iter++)
+ {
+ LLCacheNameEntry* entry = iter->second;
+ if (entry->mIsGroup)
+ {
+ LL_INFOS()
+ << iter->first << " = (group) "
+ << entry->mGroupName
+ << " @ " << entry->mCreateTime
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS()
+ << iter->first << " = "
+ << buildFullName(entry->mFirstName, entry->mLastName)
+ << " @ " << entry->mCreateTime
+ << LL_ENDL;
+ }
+ }
+}
+
+void LLCacheName::dumpStats()
+{
+ LL_INFOS() << "Queue sizes: "
+ << " Cache=" << impl.mCache.size()
+ << " AskName=" << impl.mAskNameQueue.size()
+ << " AskGroup=" << impl.mAskGroupQueue.size()
+ << " Pending=" << impl.mPendingQueue.size()
+ << " Reply=" << impl.mReplyQueue.size()
+// << " Observers=" << impl.mSignal.size()
+ << LL_ENDL;
+}
+
+void LLCacheName::clear()
+{
+ for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
+ impl.mCache.clear();
+}
+
+//static
+std::string LLCacheName::getDefaultName()
+{
+ return sCacheName["waiting"];
+}
+
+//static
+std::string LLCacheName::getDefaultLastName()
+{
+ return "Resident";
+}
+
+void LLCacheName::Impl::processPendingAsks()
+{
+ sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
+ sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue);
+ mAskNameQueue.clear();
+ mAskGroupQueue.clear();
+}
+
+void LLCacheName::Impl::processPendingReplies()
+{
+ // First call all the callbacks, because they might send messages.
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
+ {
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
+ if(!entry) continue;
+
+ if (!entry->mIsGroup)
+ {
+ std::string fullname =
+ LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ (reply->mSignal)(reply->mID, fullname, false);
+ }
+ else
+ {
+ (reply->mSignal)(reply->mID, entry->mGroupName, true);
+ }
+ }
+
+ // Forward on all replies, if needed.
+ ReplySender sender(mMsg);
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
+ {
+ PendingReply* reply = *it;
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID);
+ if(!entry) continue;
+
+ if (reply->mHost.isOk())
+ {
+ sender.send(reply->mID, *entry, reply->mHost);
+ }
+
+ reply->done();
+ }
+
+ for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); )
+ {
+ ReplyQueue::iterator curit = it++;
+ PendingReply* reply = *curit;
+ if (reply->isDone())
+ {
+ delete reply;
+ mReplyQueue.erase(curit);
+ }
+ }
+}
+
+
+void LLCacheName::Impl::sendRequest(
+ const char* msg_name,
+ const AskQueue& queue)
+{
+ if(queue.empty())
+ {
+ return;
+ }
+
+ bool start_new_message = true;
+ AskQueue::const_iterator it = queue.begin();
+ AskQueue::const_iterator end = queue.end();
+ for(; it != end; ++it)
+ {
+ if(start_new_message)
+ {
+ start_new_message = false;
+ mMsg->newMessageFast(msg_name);
+ }
+ mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);
+ mMsg->addUUIDFast(_PREHASH_ID, (*it));
+
+ if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))
+ {
+ start_new_message = true;
+ mMsg->sendReliable(mUpstreamHost);
+ }
+ }
+ if(!start_new_message)
+ {
+ mMsg->sendReliable(mUpstreamHost);
+ }
+}
+
+bool LLCacheName::Impl::isRequestPending(const LLUUID& id)
+{
+ U32 now = (U32)time(NULL);
+ U32 expire_time = now - PENDING_TIMEOUT_SECS;
+
+ PendingQueue::iterator iter = mPendingQueue.find(id);
+
+ if (iter == mPendingQueue.end()
+ || (iter->second < expire_time) )
+ {
+ mPendingQueue[id] = now;
+ return false;
+ }
+
+ return true;
+}
+
+void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)
+{
+ // You should only get this message if the cache is at the simulator
+ // level, hence having an upstream provider.
+ if (!mUpstreamHost.isOk())
+ {
+ LL_WARNS() << "LLCacheName - got UUID name/group request, but no upstream provider!" << LL_ENDL;
+ return;
+ }
+
+ LLHost fromHost = msg->getSender();
+ ReplySender sender(msg);
+
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_UUIDNameBlock);
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
+ if(entry)
+ {
+ if (isGroup != entry->mIsGroup)
+ {
+ LL_WARNS() << "LLCacheName - Asked for "
+ << (isGroup ? "group" : "user") << " name, "
+ << "but found "
+ << (entry->mIsGroup ? "group" : "user")
+ << ": " << id << LL_ENDL;
+ }
+ else
+ {
+ // ...it's in the cache, so send it as the reply
+ sender.send(id, *entry, fromHost);
+ }
+ }
+ else
+ {
+ if (!isRequestPending(id))
+ {
+ if (isGroup)
+ {
+ mAskGroupQueue.insert(id);
+ }
+ else
+ {
+ mAskNameQueue.insert(id);
+ }
+ }
+
+ addPending(id, fromHost);
+ }
+ }
+}
+
+
+
+void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
+{
+ S32 count = msg->getNumberOfBlocksFast(_PREHASH_UUIDNameBlock);
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);
+ LLCacheNameEntry* entry = get_ptr_in_map(mCache, id);
+ if (!entry)
+ {
+ entry = new LLCacheNameEntry;
+ mCache[id] = entry;
+ }
+
+ mPendingQueue.erase(id);
+
+ entry->mIsGroup = isGroup;
+ entry->mCreateTime = (U32)time(NULL);
+ if (!isGroup)
+ {
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i);
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, entry->mLastName, i);
+ }
+ else
+ { // is group
+ msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i);
+ LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR);
+ }
+
+ if (!isGroup)
+ {
+ // NOTE: Very occasionally the server sends down a full name
+ // in the first name field with an empty last name, for example,
+ // first = "Ladanie1 Resident", last = "".
+ // I cannot reproduce this, nor can I find a bug in the server code.
+ // Ensure "Resident" does not appear via cleanFullName, because
+ // buildFullName only checks last name. JC
+ std::string full_name;
+ if (entry->mLastName.empty())
+ {
+ full_name = cleanFullName(entry->mFirstName);
+
+ //fix what we are putting in the cache
+ entry->mFirstName = full_name;
+ entry->mLastName = "Resident";
+ }
+ else
+ {
+ full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
+ }
+ mSignal(id, full_name, false);
+ mReverseCache[full_name] = id;
+ }
+ else
+ {
+ mSignal(id, entry->mGroupName, true);
+ mReverseCache[entry->mGroupName] = id;
+ }
+ }
+}
+
+
+
+// static call back functions
+
+void LLCacheName::Impl::handleUUIDNameReply(LLMessageSystem* msg, void** userData)
+{
+ ((LLCacheName::Impl*)userData)->processUUIDReply(msg, false);
+}
+
+void LLCacheName::Impl::handleUUIDNameRequest(LLMessageSystem* msg, void** userData)
+{
+ ((LLCacheName::Impl*)userData)->processUUIDRequest(msg, false);
+}
+
+void LLCacheName::Impl::handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userData)
+{
+ ((LLCacheName::Impl*)userData)->processUUIDRequest(msg, true);
+}
+
+void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** userData)
+{
+ ((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
+}
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 8091248151..958f91d3c0 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -1,148 +1,148 @@
-/**
- * @file llcachename.h
- * @brief A cache of names from UUIDs.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCACHENAME_H
-#define LL_LLCACHENAME_H
-
-#include <boost/bind.hpp>
-#include <boost/signals2.hpp>
-
-class LLMessageSystem;
-class LLHost;
-class LLUUID;
-
-
-typedef boost::signals2::signal<void (const LLUUID& id,
- const std::string& name,
- bool is_group)> LLCacheNameSignal;
-typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
-
-// Old callback with user data for compatibility
-typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
-
-// Here's the theory:
-// If you request a name that isn't in the cache, it returns "waiting"
-// and requests the data. After the data arrives, you get that on
-// subsequent calls.
-// If the data hasn't been updated in an hour, it requests it again,
-// but keeps giving you the old value until new data arrives.
-// If you haven't requested the data in an hour, it releases it.
-class LLCacheName
-{
-public:
- LLCacheName(LLMessageSystem* msg);
- LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host);
- ~LLCacheName();
-
- // registers the upstream host
- // for viewers, this is the currently connected simulator
- // for simulators, this is the data server
- void setUpstream(const LLHost& upstream_host);
-
- boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
-
- // storing cache on disk; for viewer, in name.cache
- bool importFile(std::istream& istr);
- void exportFile(std::ostream& ostr);
-
- // If available, copies name ("bobsmith123" or "James Linden") into string
- // If not available, copies the string "waiting".
- // Returns true if available.
- bool getFullName(const LLUUID& id, std::string& full_name);
-
- // Reverse lookup of UUID from name
- bool getUUID(const std::string& first, const std::string& last, LLUUID& id);
- bool getUUID(const std::string& fullname, LLUUID& id);
-
- // IDEVO Temporary code
- // Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
- static std::string buildFullName(const std::string& first, const std::string& last);
-
- // Clean up legacy "bobsmith123 Resident" to "bobsmith123"
- // If name does not contain "Resident" returns it unchanged.
- static std::string cleanFullName(const std::string& full_name);
-
- // Converts a standard legacy name to a username
- // "bobsmith123 Resident" -> "bobsmith"
- // "Random Linden" -> "random.linden"
- static std::string buildUsername(const std::string& name);
-
- // Converts a complete display name to a legacy name
- // if possible, otherwise returns the input
- // "Alias (random.linden)" -> "Random Linden"
- // "Something random" -> "Something random"
- static std::string buildLegacyName(const std::string& name);
-
- // If available, this method copies the group name into the string
- // provided. The caller must allocate at least
- // DB_GROUP_NAME_BUF_SIZE characters. If not available, this
- // method copies the string "waiting". Returns true if available.
- bool getGroupName(const LLUUID& id, std::string& group);
-
- // Call the callback with the group or avatar name.
- // If the data is currently available, may call the callback immediatly
- // otherwise, will request the data, and will call the callback when
- // available. There is no garuntee the callback will ever be called.
- boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
-
- // Convenience method for looking up a group name, so you can
- // tell the difference between avatar lookup and group lookup
- // in global searches
- boost::signals2::connection getGroup(const LLUUID& group_id, const LLCacheNameCallback& callback);
-
- // LEGACY
- boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
- // This method needs to be called from time to time to send out
- // requests.
- void processPending();
-
- // Expire entries created more than "secs" seconds ago.
- void deleteEntriesOlderThan(S32 secs);
-
- // Debugging
- void dump(); // Dumps the contents of the cache
- void dumpStats(); // Dumps the sizes of the cache and associated queues.
- void clear(); // Deletes all entries from the cache
-
- static std::string getDefaultName();
-
- // Returns "Resident", the default last name for SLID-based accounts
- // that have no last name.
- static std::string getDefaultLastName();
-
- static void localizeCacheName(std::string key, std::string value);
- static std::map<std::string, std::string> sCacheName;
-private:
-
- class Impl;
- Impl& impl;
-};
-
-
-
-extern LLCacheName* gCacheName;
-
-#endif
+/**
+ * @file llcachename.h
+ * @brief A cache of names from UUIDs.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCACHENAME_H
+#define LL_LLCACHENAME_H
+
+#include <boost/bind.hpp>
+#include <boost/signals2.hpp>
+
+class LLMessageSystem;
+class LLHost;
+class LLUUID;
+
+
+typedef boost::signals2::signal<void (const LLUUID& id,
+ const std::string& name,
+ bool is_group)> LLCacheNameSignal;
+typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
+
+// Old callback with user data for compatibility
+typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
+
+// Here's the theory:
+// If you request a name that isn't in the cache, it returns "waiting"
+// and requests the data. After the data arrives, you get that on
+// subsequent calls.
+// If the data hasn't been updated in an hour, it requests it again,
+// but keeps giving you the old value until new data arrives.
+// If you haven't requested the data in an hour, it releases it.
+class LLCacheName
+{
+public:
+ LLCacheName(LLMessageSystem* msg);
+ LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host);
+ ~LLCacheName();
+
+ // registers the upstream host
+ // for viewers, this is the currently connected simulator
+ // for simulators, this is the data server
+ void setUpstream(const LLHost& upstream_host);
+
+ boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
+
+ // storing cache on disk; for viewer, in name.cache
+ bool importFile(std::istream& istr);
+ void exportFile(std::ostream& ostr);
+
+ // If available, copies name ("bobsmith123" or "James Linden") into string
+ // If not available, copies the string "waiting".
+ // Returns true if available.
+ bool getFullName(const LLUUID& id, std::string& full_name);
+
+ // Reverse lookup of UUID from name
+ bool getUUID(const std::string& first, const std::string& last, LLUUID& id);
+ bool getUUID(const std::string& fullname, LLUUID& id);
+
+ // IDEVO Temporary code
+ // Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
+ static std::string buildFullName(const std::string& first, const std::string& last);
+
+ // Clean up legacy "bobsmith123 Resident" to "bobsmith123"
+ // If name does not contain "Resident" returns it unchanged.
+ static std::string cleanFullName(const std::string& full_name);
+
+ // Converts a standard legacy name to a username
+ // "bobsmith123 Resident" -> "bobsmith"
+ // "Random Linden" -> "random.linden"
+ static std::string buildUsername(const std::string& name);
+
+ // Converts a complete display name to a legacy name
+ // if possible, otherwise returns the input
+ // "Alias (random.linden)" -> "Random Linden"
+ // "Something random" -> "Something random"
+ static std::string buildLegacyName(const std::string& name);
+
+ // If available, this method copies the group name into the string
+ // provided. The caller must allocate at least
+ // DB_GROUP_NAME_BUF_SIZE characters. If not available, this
+ // method copies the string "waiting". Returns true if available.
+ bool getGroupName(const LLUUID& id, std::string& group);
+
+ // Call the callback with the group or avatar name.
+ // If the data is currently available, may call the callback immediatly
+ // otherwise, will request the data, and will call the callback when
+ // available. There is no garuntee the callback will ever be called.
+ boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
+
+ // Convenience method for looking up a group name, so you can
+ // tell the difference between avatar lookup and group lookup
+ // in global searches
+ boost::signals2::connection getGroup(const LLUUID& group_id, const LLCacheNameCallback& callback);
+
+ // LEGACY
+ boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
+ // This method needs to be called from time to time to send out
+ // requests.
+ void processPending();
+
+ // Expire entries created more than "secs" seconds ago.
+ void deleteEntriesOlderThan(S32 secs);
+
+ // Debugging
+ void dump(); // Dumps the contents of the cache
+ void dumpStats(); // Dumps the sizes of the cache and associated queues.
+ void clear(); // Deletes all entries from the cache
+
+ static std::string getDefaultName();
+
+ // Returns "Resident", the default last name for SLID-based accounts
+ // that have no last name.
+ static std::string getDefaultLastName();
+
+ static void localizeCacheName(std::string key, std::string value);
+ static std::map<std::string, std::string> sCacheName;
+private:
+
+ class Impl;
+ Impl& impl;
+};
+
+
+
+extern LLCacheName* gCacheName;
+
+#endif
diff --git a/indra/llmessage/llchainio.cpp b/indra/llmessage/llchainio.cpp
index bcda6746a1..78dff246cb 100644
--- a/indra/llmessage/llchainio.cpp
+++ b/indra/llmessage/llchainio.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llchainio.cpp
* @author Phoenix
* @date 2005-08-04
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,20 +38,20 @@
*/
// static
bool LLDeferredChain::addToPump(
- LLPumpIO* pump,
- F32 in_seconds,
- const LLPumpIO::chain_t& deferred_chain,
- F32 chain_timeout)
+ LLPumpIO* pump,
+ F32 in_seconds,
+ const LLPumpIO::chain_t& deferred_chain,
+ F32 chain_timeout)
{
- if(!pump) return false;
- LLPumpIO::chain_t sleep_chain;
- sleep_chain.push_back(LLIOPipe::ptr_t(new LLIOSleep(in_seconds)));
- sleep_chain.push_back(
- LLIOPipe::ptr_t(new LLIOAddChain(deferred_chain, chain_timeout)));
+ if(!pump) return false;
+ LLPumpIO::chain_t sleep_chain;
+ sleep_chain.push_back(LLIOPipe::ptr_t(new LLIOSleep(in_seconds)));
+ sleep_chain.push_back(
+ LLIOPipe::ptr_t(new LLIOAddChain(deferred_chain, chain_timeout)));
- // give it a litle bit of padding.
- pump->addChain(sleep_chain, in_seconds + 10.0f);
- return true;
+ // give it a litle bit of padding.
+ pump->addChain(sleep_chain, in_seconds + 10.0f);
+ return true;
}
/**
@@ -69,20 +69,20 @@ LLChainIOFactory::~LLChainIOFactory()
#if 0
bool LLChainIOFactory::build(LLIOPipe* in, LLIOPipe* out) const
{
- if(!in || !out)
- {
- return false;
- }
- LLIOPipe* first = NULL;
- LLIOPipe* last = NULL;
- if(build_impl(first, last) && first && last)
- {
- in->connect(first);
- last->connect(out);
- return true;
- }
- LLIOPipe::ptr_t foo(first);
- LLIOPipe::ptr_t bar(last);
- return false;
+ if(!in || !out)
+ {
+ return false;
+ }
+ LLIOPipe* first = NULL;
+ LLIOPipe* last = NULL;
+ if(build_impl(first, last) && first && last)
+ {
+ in->connect(first);
+ last->connect(out);
+ return true;
+ }
+ LLIOPipe::ptr_t foo(first);
+ LLIOPipe::ptr_t bar(last);
+ return false;
}
#endif
diff --git a/indra/llmessage/llchainio.h b/indra/llmessage/llchainio.h
index 6e4d6c2013..3f12189214 100644
--- a/indra/llmessage/llchainio.h
+++ b/indra/llmessage/llchainio.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llchainio.h
* @author Phoenix
* @date 2005-08-04
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -31,7 +31,7 @@
#include "llpumpio.h"
-/**
+/**
* @class LLDeferredChain
* @brief This class allows easy addition of a chain which will sleep
* and then process another chain.
@@ -39,23 +39,23 @@
class LLDeferredChain
{
public:
- /**
- * @brief Add a chain to a pump in a finite # of seconds
- *
- * @prarm pump The pump to work on.
- * @prarm in_seconds The number of seconds from now when chain should start.
- * @prarm chain The chain to add in in_seconds seconds.
- * @prarm chain_timeout timeout for chain on the pump.
- * @return Returns true if the operation was queued.
- */
- static bool addToPump(
- LLPumpIO* pump,
- F32 in_seconds,
- const LLPumpIO::chain_t& chain,
- F32 chain_timeout);
+ /**
+ * @brief Add a chain to a pump in a finite # of seconds
+ *
+ * @prarm pump The pump to work on.
+ * @prarm in_seconds The number of seconds from now when chain should start.
+ * @prarm chain The chain to add in in_seconds seconds.
+ * @prarm chain_timeout timeout for chain on the pump.
+ * @return Returns true if the operation was queued.
+ */
+ static bool addToPump(
+ LLPumpIO* pump,
+ F32 in_seconds,
+ const LLPumpIO::chain_t& chain,
+ F32 chain_timeout);
};
-/**
+/**
* @class LLChainIOFactory
* @brief This class is an abstract base class for building io chains.
*
@@ -71,29 +71,29 @@ public:
class LLChainIOFactory
{
public:
- // Constructor
- LLChainIOFactory();
+ // Constructor
+ LLChainIOFactory();
- // Destructor
- virtual ~LLChainIOFactory();
+ // Destructor
+ virtual ~LLChainIOFactory();
- /**
- * @brief Build the chian with in as the first and end as the last
- *
- * The caller of the LLChainIOFactory is responsible for managing
- * the memory of the in pipe. All of the chains generated by the
- * factory will be ref counted as usual, so the caller will also
- * need to break the links in the chain.
- * @param chain The chain which will have new pipes appended
- * @param context A context for use by this factory if you choose
- * @retrun Returns true if the call was successful.
- */
- virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const = 0;
+ /**
+ * @brief Build the chian with in as the first and end as the last
+ *
+ * The caller of the LLChainIOFactory is responsible for managing
+ * the memory of the in pipe. All of the chains generated by the
+ * factory will be ref counted as usual, so the caller will also
+ * need to break the links in the chain.
+ * @param chain The chain which will have new pipes appended
+ * @param context A context for use by this factory if you choose
+ * @retrun Returns true if the call was successful.
+ */
+ virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const = 0;
protected:
};
-/**
+/**
* @class LLSimpleIOFactory
* @brief Basic implementation for making a factory that returns a
* 'chain' of one object
@@ -102,14 +102,14 @@ template<class Pipe>
class LLSimpleIOFactory : public LLChainIOFactory
{
public:
- virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
- {
- chain.push_back(LLIOPipe::ptr_t(new Pipe));
- return true;
- }
+ virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
+ {
+ chain.push_back(LLIOPipe::ptr_t(new Pipe));
+ return true;
+ }
};
-/**
+/**
* @class LLCloneIOFactory
* @brief Implementation for a facory which copies a particular pipe.
*/
@@ -117,19 +117,19 @@ template<class Pipe>
class LLCloneIOFactory : public LLChainIOFactory
{
public:
- LLCloneIOFactory(Pipe* original) :
- mHandle(original),
- mOriginal(original) {}
+ LLCloneIOFactory(Pipe* original) :
+ mHandle(original),
+ mOriginal(original) {}
- virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
- {
- chain.push_back(LLIOPipe::ptr_t(new Pipe(*mOriginal)));
- return true;
- }
+ virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
+ {
+ chain.push_back(LLIOPipe::ptr_t(new Pipe(*mOriginal)));
+ return true;
+ }
protected:
- LLIOPipe::ptr_t mHandle;
- Pipe* mOriginal;
+ LLIOPipe::ptr_t mHandle;
+ Pipe* mOriginal;
};
#endif // LL_LLCHAINIO_H
diff --git a/indra/llmessage/llcipher.h b/indra/llmessage/llcipher.h
index b3f142c001..cbd5d5bde1 100644
--- a/indra/llmessage/llcipher.h
+++ b/indra/llmessage/llcipher.h
@@ -1,56 +1,56 @@
-/**
- * @file llcipher.h
- * @brief Abstract base class for encryption ciphers.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LLCIPHER_H
-#define LLCIPHER_H
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLCipher
-//
-// Abstract base class for a cipher object.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLCipher
-{
-public:
- virtual ~LLCipher() {}
-
- // encrypt src and place result into dst. returns true if
- // Returns number of bytes written into dst, or 0 on error.
- virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
-
- // decrypt src and place result into dst.
- // Returns number of bytes written into dst, or 0 on error.
- virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
-
- // returns the minimum amount of space required to encrypt for a
- // unencrypted source buffer of length len.
- // *NOTE: This is estimated space and you should check the return value
- // of the encrypt function.
- virtual U32 requiredEncryptionSpace(U32 src_len) const = 0 ;
-};
-
-#endif
+/**
+ * @file llcipher.h
+ * @brief Abstract base class for encryption ciphers.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLCIPHER_H
+#define LLCIPHER_H
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLCipher
+//
+// Abstract base class for a cipher object.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLCipher
+{
+public:
+ virtual ~LLCipher() {}
+
+ // encrypt src and place result into dst. returns true if
+ // Returns number of bytes written into dst, or 0 on error.
+ virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
+
+ // decrypt src and place result into dst.
+ // Returns number of bytes written into dst, or 0 on error.
+ virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) = 0;
+
+ // returns the minimum amount of space required to encrypt for a
+ // unencrypted source buffer of length len.
+ // *NOTE: This is estimated space and you should check the return value
+ // of the encrypt function.
+ virtual U32 requiredEncryptionSpace(U32 src_len) const = 0 ;
+};
+
+#endif
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index a0bf999dee..bd9b3553fe 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -1,1419 +1,1419 @@
-/**
- * @file llcircuit.cpp
- * @brief Class to track UDP endpoints for the message system.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#if LL_WINDOWS
-
-#include <process.h>
-
-#else
-
-#if LL_LINUX
-#include <dlfcn.h> // RTLD_LAZY
-#endif
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#endif
-
-
-#if !defined(USE_CIRCUIT_LIST)
-#include <algorithm>
-#endif
-#include <sstream>
-#include <iterator>
-#include <stack>
-
-#include "llcircuit.h"
-
-#include "message.h"
-#include "llrand.h"
-#include "llstl.h"
-#include "lltransfermanager.h"
-#include "llmodularmath.h"
-
-const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked.
-const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked.
-
-const F32Seconds TARGET_PERIOD_LENGTH(5.f);
-const F32Seconds LL_DUPLICATE_SUPPRESSION_TIMEOUT(60.f); //this can be long, as time-based cleanup is
- // only done when wrapping packetids, now...
-
-LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
- const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
-: mHost (host),
- mWrapID(0),
- mPacketsOutID(0),
- mPacketsInID(in_id),
- mHighestPacketID(in_id),
- mTimeoutCallback(NULL),
- mTimeoutUserData(NULL),
- mTrusted(false),
- mbAllowTimeout(true),
- mbAlive(true),
- mBlocked(false),
- mPingTime(0.0),
- mLastPingSendTime(0.0),
- mLastPingReceivedTime(0.0),
- mNextPingSendTime(0.0),
- mPingsInTransit(0),
- mLastPingID(0),
- mPingDelay(INITIAL_PING_VALUE_MSEC),
- mPingDelayAveraged(INITIAL_PING_VALUE_MSEC),
- mUnackedPacketCount(0),
- mUnackedPacketBytes(0),
- mLastPacketInTime(0.0),
- mLocalEndPointID(),
- mPacketsOut(0),
- mPacketsIn(0),
- mPacketsLost(0),
- mBytesIn(0),
- mBytesOut(0),
- mLastPeriodLength(-1.f),
- mBytesInLastPeriod(0),
- mBytesOutLastPeriod(0),
- mBytesInThisPeriod(0),
- mBytesOutThisPeriod(0),
- mPeakBPSIn(0.f),
- mPeakBPSOut(0.f),
- mPeriodTime(0.0),
- mExistenceTimer(),
- mAckCreationTime(0.f),
- mCurrentResendCount(0),
- mLastPacketGap(0),
- mHeartbeatInterval(circuit_heartbeat_interval),
- mHeartbeatTimeout(circuit_timeout)
-{
- // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
- // running a message system loop.
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(true);
- F32 distribution_offset = ll_frand();
-
- mPingTime = mt_sec;
- mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset;
- mLastPingReceivedTime = mt_sec;
- mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
- mPeriodTime = mt_sec;
-
- mLocalEndPointID.generate();
-}
-
-
-LLCircuitData::~LLCircuitData()
-{
- LLReliablePacket *packetp = NULL;
-
- // Clean up all pending transfers.
- gTransferManager.cleanupConnection(mHost);
-
- // remove all pending reliable messages on this circuit
- std::vector<TPACKETID> doomed;
- reliable_iter iter;
- reliable_iter end = mUnackedPackets.end();
- for(iter = mUnackedPackets.begin(); iter != end; ++iter)
- {
- packetp = iter->second;
- gMessageSystem->mFailedResendPackets++;
- if(gMessageSystem->mVerboseLog)
- {
- doomed.push_back(packetp->mPacketID);
- }
- if (packetp->mCallback)
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
- }
-
- // Update stats
- mUnackedPacketCount--;
- mUnackedPacketBytes -= packetp->mBufferLength;
-
- delete packetp;
- }
-
- // remove all pending final retry reliable messages on this circuit
- end = mFinalRetryPackets.end();
- for(iter = mFinalRetryPackets.begin(); iter != end; ++iter)
- {
- packetp = iter->second;
- gMessageSystem->mFailedResendPackets++;
- if(gMessageSystem->mVerboseLog)
- {
- doomed.push_back(packetp->mPacketID);
- }
- if (packetp->mCallback)
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
- }
-
- // Update stats
- mUnackedPacketCount--;
- mUnackedPacketBytes -= packetp->mBufferLength;
-
- delete packetp;
- }
-
- // log aborted reliable packets for this circuit.
- if(gMessageSystem->mVerboseLog && !doomed.empty())
- {
- std::ostringstream str;
- std::ostream_iterator<TPACKETID> append(str, " ");
- str << "MSG: -> " << mHost << "\tABORTING RELIABLE:\t";
- std::copy(doomed.begin(), doomed.end(), append);
- LL_INFOS() << str.str() << LL_ENDL;
- }
-}
-
-
-void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
-{
- reliable_iter iter;
- LLReliablePacket *packetp;
-
- iter = mUnackedPackets.find(packet_num);
- if (iter != mUnackedPackets.end())
- {
- packetp = iter->second;
-
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
- << packetp->mPacketID;
- LL_INFOS() << str.str() << LL_ENDL;
- }
- if (packetp->mCallback)
- {
- if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
- }
- else
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
- }
- }
-
- // Update stats
- mUnackedPacketCount--;
- mUnackedPacketBytes -= packetp->mBufferLength;
-
- // Cleanup
- delete packetp;
- mUnackedPackets.erase(iter);
- return;
- }
-
- iter = mFinalRetryPackets.find(packet_num);
- if (iter != mFinalRetryPackets.end())
- {
- packetp = iter->second;
- // LL_INFOS() << "Packet " << packet_num << " removed from the pending list" << LL_ENDL;
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
- << packetp->mPacketID;
- LL_INFOS() << str.str() << LL_ENDL;
- }
- if (packetp->mCallback)
- {
- if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
- }
- else
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
- }
- }
-
- // Update stats
- mUnackedPacketCount--;
- mUnackedPacketBytes -= packetp->mBufferLength;
-
- // Cleanup
- delete packetp;
- mFinalRetryPackets.erase(iter);
- }
- else
- {
- // Couldn't find this packet on either of the unacked lists.
- // maybe it's a duplicate ack?
- }
-}
-
-
-
-S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
-{
- LLReliablePacket *packetp;
-
-
- //
- // Theoretically we should search through the list for the packet with the oldest
- // packet ID, as otherwise when we WRAP we will resend reliable packets out of order.
- // Since resends are ALREADY out of order, and wrapping is highly rare (16+million packets),
- // I'm not going to worry about this for now - djs
- //
-
- reliable_iter iter;
- bool have_resend_overflow = false;
- for (iter = mUnackedPackets.begin(); iter != mUnackedPackets.end();)
- {
- packetp = iter->second;
-
- // Only check overflow if we haven't had one yet.
- if (!have_resend_overflow)
- {
- have_resend_overflow = mThrottles.checkOverflow(TC_RESEND, 0);
- }
-
- if (have_resend_overflow)
- {
- // We've exceeded our bandwidth for resends.
- // Time to stop trying to send them.
-
- // If we have too many unacked packets, we need to start dropping expired ones.
- if (mUnackedPacketBytes > 512000)
- {
- if (now > packetp->mExpirationTime)
- {
- // This circuit has overflowed. Do not retry. Do not pass go.
- packetp->mRetries = 0;
- // Remove it from this list and add it to the final list.
- mUnackedPackets.erase(iter++);
- mFinalRetryPackets[packetp->mPacketID] = packetp;
- }
- else
- {
- ++iter;
- }
- // Move on to the next unacked packet.
- continue;
- }
-
- if (mUnackedPacketBytes > 256000 && !(getPacketsOut() % 1024))
- {
- // Warn if we've got a lot of resends waiting.
- LL_WARNS() << mHost << " has " << mUnackedPacketBytes
- << " bytes of reliable messages waiting" << LL_ENDL;
- }
- // Stop resending. There are less than 512000 unacked packets.
- break;
- }
-
- if (now > packetp->mExpirationTime)
- {
- packetp->mRetries--;
-
- // retry
- mCurrentResendCount++;
-
- gMessageSystem->mResentPackets++;
-
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: -> " << packetp->mHost
- << "\tRESENDING RELIABLE:\t" << packetp->mPacketID;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- packetp->mBuffer[0] |= LL_RESENT_FLAG; // tag packet id as being a resend
-
- gMessageSystem->mPacketRing.sendPacket(packetp->mSocket,
- (char *)packetp->mBuffer, packetp->mBufferLength,
- packetp->mHost);
-
- mThrottles.throttleOverflow(TC_RESEND, packetp->mBufferLength * 8.f);
-
- // The new method, retry time based on ping
- if (packetp->mPingBasedRetry)
- {
- packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged()));
- }
- else
- {
- // custom, constant retry time
- packetp->mExpirationTime = now + packetp->mTimeout;
- }
-
- if (!packetp->mRetries)
- {
- // Last resend, remove it from this list and add it to the final list.
- mUnackedPackets.erase(iter++);
- mFinalRetryPackets[packetp->mPacketID] = packetp;
- }
- else
- {
- // Don't remove it yet, it still gets to try to resend at least once.
- ++iter;
- }
- }
- else
- {
- // Don't need to do anything with this packet, keep iterating.
- ++iter;
- }
- }
-
-
- for (iter = mFinalRetryPackets.begin(); iter != mFinalRetryPackets.end();)
- {
- packetp = iter->second;
- if (now > packetp->mExpirationTime)
- {
- // fail (too many retries)
- //LL_INFOS() << "Packet " << packetp->mPacketID << " removed from the pending list: exceeded retry limit" << LL_ENDL;
- //if (packetp->mMessageName)
- //{
- // LL_INFOS() << "Packet name " << packetp->mMessageName << LL_ENDL;
- //}
- gMessageSystem->mFailedResendPackets++;
-
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: -> " << packetp->mHost << "\tABORTING RELIABLE:\t"
- << packetp->mPacketID;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- if (packetp->mCallback)
- {
- packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
- }
-
- // Update stats
- mUnackedPacketCount--;
- mUnackedPacketBytes -= packetp->mBufferLength;
-
- mFinalRetryPackets.erase(iter++);
- delete packetp;
- }
- else
- {
- ++iter;
- }
- }
-
- return mUnackedPacketCount;
-}
-
-
-LLCircuit::LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
-: mLastCircuit(NULL),
- mHeartbeatInterval(circuit_heartbeat_interval),
- mHeartbeatTimeout(circuit_timeout)
-{}
-
-LLCircuit::~LLCircuit()
-{
- // delete pointers in the map.
- std::for_each(mCircuitData.begin(),
- mCircuitData.end(),
- llcompose1(
- DeletePointerFunctor<LLCircuitData>(),
- llselect2nd<circuit_data_map::value_type>()));
-}
-
-LLCircuitData *LLCircuit::addCircuitData(const LLHost &host, TPACKETID in_id)
-{
- // This should really validate if one already exists
- LL_INFOS() << "LLCircuit::addCircuitData for " << host << LL_ENDL;
- LLCircuitData *tempp = new LLCircuitData(host, in_id, mHeartbeatInterval, mHeartbeatTimeout);
- mCircuitData.insert(circuit_data_map::value_type(host, tempp));
- mPingSet.insert(tempp);
-
- mLastCircuit = tempp;
- return tempp;
-}
-
-void LLCircuit::removeCircuitData(const LLHost &host)
-{
- LL_INFOS() << "LLCircuit::removeCircuitData for " << host << LL_ENDL;
- mLastCircuit = NULL;
- circuit_data_map::iterator it = mCircuitData.find(host);
- if(it != mCircuitData.end())
- {
- LLCircuitData *cdp = it->second;
- mCircuitData.erase(it);
-
- LLCircuit::ping_set_t::iterator psit = mPingSet.find(cdp);
- if (psit != mPingSet.end())
- {
- mPingSet.erase(psit);
- }
- else
- {
- LL_WARNS() << "Couldn't find entry for next ping in ping set!" << LL_ENDL;
- }
-
- // Clean up from optimization maps
- mUnackedCircuitMap.erase(host);
- mSendAckMap.erase(host);
- delete cdp;
- }
-
- // This also has to happen AFTER we nuke the circuit, because various
- // callbacks for the circuit may result in messages being sent to
- // this circuit, and the setting of mLastCircuit. We don't check
- // if the host matches, but we don't really care because mLastCircuit
- // is an optimization, and this happens VERY rarely.
- mLastCircuit = NULL;
-}
-
-void LLCircuitData::setAlive(bool b_alive)
-{
- if (mbAlive != b_alive)
- {
- mPacketsOutID = 0;
- mPacketsInID = 0;
- mbAlive = b_alive;
- }
- if (b_alive)
- {
- mLastPingReceivedTime = LLMessageSystem::getMessageTimeSeconds();
- mPingsInTransit = 0;
- mBlocked = false;
- }
-}
-
-
-void LLCircuitData::setAllowTimeout(bool allow)
-{
- mbAllowTimeout = allow;
-
- if (allow)
- {
- // resuming circuit
- // make sure it's alive
- setAlive(true);
- }
-}
-
-
-// Reset per-period counters if necessary.
-void LLCircuitData::checkPeriodTime()
-{
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
- F64Seconds period_length = mt_sec - mPeriodTime;
- if ( period_length > TARGET_PERIOD_LENGTH)
- {
- F32 bps_in = F32Bits(mBytesInThisPeriod).value() / period_length.value();
- if (bps_in > mPeakBPSIn)
- {
- mPeakBPSIn = bps_in;
- }
-
- F32 bps_out = F32Bits(mBytesOutThisPeriod).value() / period_length.value();
- if (bps_out > mPeakBPSOut)
- {
- mPeakBPSOut = bps_out;
- }
-
- mBytesInLastPeriod = mBytesInThisPeriod;
- mBytesOutLastPeriod = mBytesOutThisPeriod;
- mBytesInThisPeriod = S32Bytes(0);
- mBytesOutThisPeriod = S32Bytes(0);
- mLastPeriodLength = F32Seconds::convert(period_length);
-
- mPeriodTime = mt_sec;
- }
-}
-
-
-void LLCircuitData::addBytesIn(S32Bytes bytes)
-{
- mBytesIn += bytes;
- mBytesInThisPeriod += bytes;
-}
-
-
-void LLCircuitData::addBytesOut(S32Bytes bytes)
-{
- mBytesOut += bytes;
- mBytesOutThisPeriod += bytes;
-}
-
-
-void LLCircuitData::addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params)
-{
- LLReliablePacket *packet_info;
-
- packet_info = new LLReliablePacket(mSocket, buf_ptr, buf_len, params);
-
- mUnackedPacketCount++;
- mUnackedPacketBytes += packet_info->mBufferLength;
-
- if (params && params->mRetries)
- {
- mUnackedPackets[packet_info->mPacketID] = packet_info;
- }
- else
- {
- mFinalRetryPackets[packet_info->mPacketID] = packet_info;
- }
-}
-
-
-void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size)
-{
- F64Seconds now = LLMessageSystem::getMessageTimeSeconds();
- unacked_list_length = 0;
- unacked_list_size = 0;
-
- LLCircuitData* circ;
- circuit_data_map::iterator end = mUnackedCircuitMap.end();
- for(circuit_data_map::iterator it = mUnackedCircuitMap.begin(); it != end; ++it)
- {
- circ = (*it).second;
- unacked_list_length += circ->resendUnackedPackets(now);
- unacked_list_size += circ->getUnackedPacketBytes();
- }
-}
-
-
-bool LLCircuitData::isDuplicateResend(TPACKETID packetnum)
-{
- return (mRecentlyReceivedReliablePackets.find(packetnum) != mRecentlyReceivedReliablePackets.end());
-}
-
-
-void LLCircuit::dumpResends()
-{
- circuit_data_map::iterator end = mCircuitData.end();
- for(circuit_data_map::iterator it = mCircuitData.begin(); it != end; ++it)
- {
- (*it).second->dumpResendCountAndReset();
- }
-}
-
-LLCircuitData* LLCircuit::findCircuit(const LLHost& host) const
-{
- // An optimization on finding the previously found circuit.
- if (mLastCircuit && (mLastCircuit->mHost == host))
- {
- return mLastCircuit;
- }
-
- circuit_data_map::const_iterator it = mCircuitData.find(host);
- if(it == mCircuitData.end())
- {
- return NULL;
- }
- mLastCircuit = it->second;
- return mLastCircuit;
-}
-
-
-bool LLCircuit::isCircuitAlive(const LLHost& host) const
-{
- LLCircuitData *cdp = findCircuit(host);
- if(cdp)
- {
- return cdp->mbAlive;
- }
-
- return false;
-}
-
-void LLCircuitData::setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data)
-{
- mTimeoutCallback = callback_func;
- mTimeoutUserData = user_data;
-}
-
-void LLCircuitData::checkPacketInID(TPACKETID id, bool receive_resent)
-{
- // Done as floats so we don't have to worry about running out of room
- // with U32 getting poked into an S32.
- F32 delta = (F32)mHighestPacketID - (F32)id;
- if (delta > (0.5f*LL_MAX_OUT_PACKET_ID))
- {
- // We've almost definitely wrapped, reset the mLastPacketID to be low again.
- mHighestPacketID = id;
- }
- else if (delta < (-0.5f*LL_MAX_OUT_PACKET_ID))
- {
- // This is almost definitely an old packet coming in after a wrap, ignore it.
- }
- else
- {
- mHighestPacketID = llmax(mHighestPacketID, id);
- }
-
- // Save packet arrival time
- mLastPacketInTime = LLMessageSystem::getMessageTimeSeconds();
-
- // Have we received anything on this circuit yet?
- if (0 == mPacketsIn)
- {
- // Must be first packet from unclosed circuit.
- mPacketsIn++;
- setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
-
- mLastPacketGap = 0;
- return;
- }
-
- mPacketsIn++;
-
-
- // now, check to see if we've got a gap
- U32 gap = 0;
- if (mPacketsInID == id)
- {
- // nope! bump and wrap the counter, then return
- mPacketsInID++;
- mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
- }
- else if (id < mWrapID)
- {
- // id < mWrapID will happen if the first few packets are out of order. . .
- // at that point we haven't marked anything "potentially lost" and
- // the out-of-order packet will cause a full wrap marking all the IDs "potentially lost"
-
- // do nothing
- }
- else
- {
- // we have a gap! if that id is in the map, remove it from the map, leave mCurrentCircuit->mPacketsInID
- // alone
- // otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map
- // and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID
-
- // babbage: all operands in expression are unsigned, so modular
- // arithmetic will always find correct gap, regardless of wrap arounds.
- const U8 width = 24;
- gap = LLModularMath::subtract<width>(mPacketsInID, id);
-
- if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end())
- {
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << mHost << "\tRECOVERING LOST:\t" << id;
- LL_INFOS() << str.str() << LL_ENDL;
- }
- // LL_INFOS() << "removing potential lost: " << id << LL_ENDL;
- mPotentialLostPackets.erase(id);
- }
- else if (!receive_resent) // don't freak out over out-of-order reliable resends
- {
- U64Microseconds time = LLMessageSystem::getMessageTimeUsecs();
- TPACKETID index = mPacketsInID;
- S32 gap_count = 0;
- if ((index < id) && ((id - index) < 16))
- {
- while (index != id)
- {
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
- << index;
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
-// LL_INFOS() << "adding potential lost: " << index << LL_ENDL;
- mPotentialLostPackets[index] = time;
- index++;
- index = index % LL_MAX_OUT_PACKET_ID;
- gap_count++;
- }
- }
- else
- {
- LL_INFOS() << "packet_out_of_order - got packet " << id << " expecting " << index << " from " << mHost << LL_ENDL;
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
- << id << " expected " << index;
- LL_INFOS() << str.str() << LL_ENDL;
- }
- }
-
- mPacketsInID = id + 1;
- mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
-
- if (gap_count > 128)
- {
- LL_WARNS() << "Packet loss gap filler running amok!" << LL_ENDL;
- }
- else if (gap_count > 16)
- {
- LL_WARNS() << "Sustaining large amounts of packet loss!" << LL_ENDL;
- }
-
- }
- }
- mLastPacketGap = gap;
-}
-
-
-void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
-{
- F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
- S32 count = mPingSet.size();
- S32 cur = 0;
-
- // Only process each circuit once at most, stop processing if no circuits
- while((cur < count) && !mPingSet.empty())
- {
- cur++;
-
- LLCircuit::ping_set_t::iterator psit = mPingSet.begin();
- LLCircuitData *cdp = *psit;
-
- if (!cdp->mbAlive)
- {
- // We suspect that this case should never happen, given how
- // the alive status is set.
- // Skip over dead circuits, just add the ping interval and push it to the back
- // Always remember to remove it from the set before changing the sorting
- // key (mNextPingSendTime)
- mPingSet.erase(psit);
- cdp->mNextPingSendTime = cur_time + mHeartbeatInterval;
- mPingSet.insert(cdp);
- continue;
- }
- else
- {
- // Check to see if this needs a ping
- if (cur_time < cdp->mNextPingSendTime)
- {
- // This circuit doesn't need a ping, break out because
- // we have a sorted list, thus no more circuits need pings
- break;
- }
-
- // Update watchdog timers
- if (cdp->updateWatchDogTimers(msgsys))
- {
- // Randomize our pings a bit by doing some up to 5% early or late
- F64Seconds dt = 0.95f*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
-
- // Remove it, and reinsert it with the new next ping time.
- // Always remove before changing the sorting key.
- mPingSet.erase(psit);
- cdp->mNextPingSendTime = cur_time + dt;
- mPingSet.insert(cdp);
-
- // Update our throttles
- cdp->mThrottles.dynamicAdjust();
-
- // Update some stats, this is not terribly important
- cdp->checkPeriodTime();
- }
- else
- {
- // This mPingSet.erase isn't necessary, because removing the circuit will
- // remove the ping set.
- //mPingSet.erase(psit);
- removeCircuitData(cdp->mHost);
- }
- }
- }
-}
-
-
-bool LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
-{
- F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
- mLastPingSendTime = cur_time;
-
- if (!checkCircuitTimeout())
- {
- // Pass this back to the calling LLCircuit, this circuit needs to be cleaned up.
- return false;
- }
-
- // WARNING!
- // Duplicate suppression can FAIL if packets are delivered out of
- // order, although it's EXTREMELY unlikely. It would require
- // that the ping get delivered out of order enough that the ACK
- // for the packet that it was out of order with was received BEFORE
- // the ping was sent.
-
- // Find the current oldest reliable packetID
- // This is to handle the case if we actually manage to wrap our
- // packet IDs - the oldest will actually have a higher packet ID
- // than the current.
- bool wrapped = false;
- reliable_iter iter;
- iter = mUnackedPackets.upper_bound(getPacketOutID());
- if (iter == mUnackedPackets.end())
- {
- // Nothing AFTER this one, so we want the lowest packet ID
- // then.
- iter = mUnackedPackets.begin();
- wrapped = true;
- }
-
- TPACKETID packet_id = 0;
-
- // Check against the "final" packets
- bool wrapped_final = false;
- reliable_iter iter_final;
- iter_final = mFinalRetryPackets.upper_bound(getPacketOutID());
- if (iter_final == mFinalRetryPackets.end())
- {
- iter_final = mFinalRetryPackets.begin();
- wrapped_final = true;
- }
-
- //LL_INFOS() << mHost << " - unacked count " << mUnackedPackets.size() << LL_ENDL;
- //LL_INFOS() << mHost << " - final count " << mFinalRetryPackets.size() << LL_ENDL;
- if (wrapped != wrapped_final)
- {
- // One of the "unacked" or "final" lists hasn't wrapped. Whichever one
- // hasn't has the oldest packet.
- if (!wrapped)
- {
- // Hasn't wrapped, so the one on the
- // unacked packet list is older
- packet_id = iter->first;
- //LL_INFOS() << mHost << ": nowrapped unacked" << LL_ENDL;
- }
- else
- {
- packet_id = iter_final->first;
- //LL_INFOS() << mHost << ": nowrapped final" << LL_ENDL;
- }
- }
- else
- {
- // They both wrapped, we can just use the minimum of the two.
- if ((iter == mUnackedPackets.end()) && (iter_final == mFinalRetryPackets.end()))
- {
- // Wow! No unacked packets at all!
- // Send the ID of the last packet we sent out.
- // This will flush all of the destination's
- // unacked packets, theoretically.
- //LL_INFOS() << mHost << ": No unacked!" << LL_ENDL;
- packet_id = getPacketOutID();
- }
- else
- {
- bool had_unacked = false;
- if (iter != mUnackedPackets.end())
- {
- // Unacked list has the lowest so far
- packet_id = iter->first;
- had_unacked = true;
- //LL_INFOS() << mHost << ": Unacked" << LL_ENDL;
- }
-
- if (iter_final != mFinalRetryPackets.end())
- {
- // Use the lowest of the unacked list and the final list
- if (had_unacked)
- {
- // Both had a packet, use the lowest.
- packet_id = llmin(packet_id, iter_final->first);
- //LL_INFOS() << mHost << ": Min of unacked/final" << LL_ENDL;
- }
- else
- {
- // Only the final had a packet, use it.
- packet_id = iter_final->first;
- //LL_INFOS() << mHost << ": Final!" << LL_ENDL;
- }
- }
- }
- }
-
- // Send off the another ping.
- pingTimerStart();
- msgsys->newMessageFast(_PREHASH_StartPingCheck);
- msgsys->nextBlock(_PREHASH_PingID);
- msgsys->addU8Fast(_PREHASH_PingID, nextPingID());
- msgsys->addU32Fast(_PREHASH_OldestUnacked, packet_id);
- msgsys->sendMessage(mHost);
-
- // Also do lost packet accounting.
- // Check to see if anything on our lost list is old enough to
- // be considered lost
-
- LLCircuitData::packet_time_map::iterator it;
- U64Microseconds timeout = llmin(LL_MAX_LOST_TIMEOUT, F32Seconds(getPingDelayAveraged()) * LL_LOST_TIMEOUT_FACTOR);
-
- U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
- for (it = mPotentialLostPackets.begin(); it != mPotentialLostPackets.end(); )
- {
- U64Microseconds delta_t_usec = mt_usec - (*it).second;
- if (delta_t_usec > timeout)
- {
- // let's call this one a loss!
- mPacketsLost++;
- gMessageSystem->mDroppedPackets++;
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << mHost << "\tLOST PACKET:\t"
- << (*it).first;
- LL_INFOS() << str.str() << LL_ENDL;
- }
- mPotentialLostPackets.erase(it++);
- }
- else
- {
- ++it;
- }
- }
-
- return true;
-}
-
-
-void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
-{
- // purge old data from the duplicate suppression queue
-
- // we want to KEEP all x where oldest_id <= x <= last incoming packet, and delete everything else.
-
- //LL_INFOS() << mHost << ": clearing before oldest " << oldest_id << LL_ENDL;
- //LL_INFOS() << "Recent list before: " << mRecentlyReceivedReliablePackets.size() << LL_ENDL;
- if (oldest_id < mHighestPacketID)
- {
- // Clean up everything with a packet ID less than oldest_id.
- packet_time_map::iterator pit_start;
- packet_time_map::iterator pit_end;
- pit_start = mRecentlyReceivedReliablePackets.begin();
- pit_end = mRecentlyReceivedReliablePackets.lower_bound(oldest_id);
- mRecentlyReceivedReliablePackets.erase(pit_start, pit_end);
- }
-
- // Do timeout checks on everything with an ID > mHighestPacketID.
- // This should be empty except for wrapping IDs. Thus, this should be
- // highly rare.
- U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
-
- packet_time_map::iterator pit;
- for(pit = mRecentlyReceivedReliablePackets.upper_bound(mHighestPacketID);
- pit != mRecentlyReceivedReliablePackets.end(); )
- {
- // Validate that the packet ID seems far enough away
- if ((pit->first - mHighestPacketID) < 100)
- {
- LL_WARNS() << "Probably incorrectly timing out non-wrapped packets!" << LL_ENDL;
- }
- U64Microseconds delta_t_usec = mt_usec - (*pit).second;
- F64Seconds delta_t_sec = delta_t_usec;
- if (delta_t_sec > LL_DUPLICATE_SUPPRESSION_TIMEOUT)
- {
- // enough time has elapsed we're not likely to get a duplicate on this one
- LL_INFOS() << "Clearing " << pit->first << " from recent list" << LL_ENDL;
- mRecentlyReceivedReliablePackets.erase(pit++);
- }
- else
- {
- ++pit;
- }
- }
- //LL_INFOS() << "Recent list after: " << mRecentlyReceivedReliablePackets.size() << LL_ENDL;
-}
-
-bool LLCircuitData::checkCircuitTimeout()
-{
- F64Seconds time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
-
- // Nota Bene: This needs to be turned off if you are debugging multiple simulators
- if (time_since_last_ping > mHeartbeatTimeout)
- {
- LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " last ping " << time_since_last_ping << " seconds ago." <<LL_ENDL;
- setAlive(false);
- if (mTimeoutCallback)
- {
- LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " calling callback." << LL_ENDL;
- mTimeoutCallback(mHost, mTimeoutUserData);
- }
- if (!isAlive())
- {
- // The callback didn't try and resurrect the circuit. We should kill it.
- LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " still dead, dropping." << LL_ENDL;
- return false;
- }
- }
-
- return true;
-}
-
-// Call this method when a reliable message comes in - this will
-// correctly place the packet in the correct list to be acked later.
-bool LLCircuitData::collectRAck(TPACKETID packet_num)
-{
- if (mAcks.empty())
- {
- // First extra ack, we need to add ourselves to the list of circuits that need to send acks
- gMessageSystem->mCircuitInfo.mSendAckMap[mHost] = this;
- }
-
- mAcks.push_back(packet_num);
- if (mAckCreationTime == 0)
- {
- mAckCreationTime = getAgeInSeconds();
- }
- return true;
-}
-
-// this method is called during the message system processAcks() to
-// send out any acks that did not get sent already.
-void LLCircuit::sendAcks(F32 collect_time)
-{
- collect_time = llclamp(collect_time, 0.f, LL_COLLECT_ACK_TIME_MAX);
- LLCircuitData* cd;
- circuit_data_map::iterator it = mSendAckMap.begin();
- while (it != mSendAckMap.end())
- {
- circuit_data_map::iterator cur_it = it++;
- cd = (*cur_it).second;
- S32 count = (S32)cd->mAcks.size();
- F32 age = cd->getAgeInSeconds() - cd->mAckCreationTime;
- if (age > collect_time || count == 0)
- {
- if (count>0)
- {
- // send the packet acks
- S32 acks_this_packet = 0;
- for(S32 i = 0; i < count; ++i)
- {
- if(acks_this_packet == 0)
- {
- gMessageSystem->newMessageFast(_PREHASH_PacketAck);
- }
- gMessageSystem->nextBlockFast(_PREHASH_Packets);
- gMessageSystem->addU32Fast(_PREHASH_ID, cd->mAcks[i]);
- ++acks_this_packet;
- if(acks_this_packet > 250)
- {
- gMessageSystem->sendMessage(cd->mHost);
- acks_this_packet = 0;
- }
- }
- if(acks_this_packet > 0)
- {
- gMessageSystem->sendMessage(cd->mHost);
- }
-
- if(gMessageSystem->mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: -> " << cd->mHost << "\tPACKET ACKS:\t";
- std::ostream_iterator<TPACKETID> append(str, " ");
- std::copy(cd->mAcks.begin(), cd->mAcks.end(), append);
- LL_INFOS() << str.str() << LL_ENDL;
- }
-
- // empty out the acks list
- cd->mAcks.clear();
- cd->mAckCreationTime = 0.f;
- }
- // remove data map
- mSendAckMap.erase(cur_it);
- }
- }
-}
-
-
-std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit)
-{
- F32 age = circuit.mExistenceTimer.getElapsedTimeF32();
-
- using namespace std;
- s << "Circuit " << circuit.mHost << " "
- << circuit.mRemoteID << " "
- << (circuit.mbAlive ? "Alive" : "Not Alive") << " "
- << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed")
- << endl;
-
- s << " Packets Lost: " << circuit.mPacketsLost
- << " Measured Ping: " << circuit.mPingDelay
- << " Averaged Ping: " << circuit.mPingDelayAveraged
- << endl;
-
- s << "Global In/Out " << S32(age) << " sec"
- << " KBytes: " << circuit.mBytesIn.valueInUnits<LLUnits::Kilobytes>() << "/" << circuit.mBytesOut.valueInUnits<LLUnits::Kilobytes>()
- << " Kbps: "
- << S32(circuit.mBytesIn.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
- << "/"
- << S32(circuit.mBytesOut.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
- << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut
- << endl;
-
- s << "Recent In/Out " << circuit.mLastPeriodLength
- << " KBytes: "
- << circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobytes>()
- << "/"
- << circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobytes>()
- << " Kbps: "
- << (S32)(circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
- << "/"
- << (S32)(circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
- << " Peak kbps: "
- << S32(circuit.mPeakBPSIn / 1024.f)
- << "/"
- << S32(circuit.mPeakBPSOut / 1024.f)
- << endl;
-
- return s;
-}
-
-void LLCircuitData::getInfo(LLSD& info) const
-{
- info["Host"] = mHost.getIPandPort();
- info["Alive"] = mbAlive;
- info["Age"] = mExistenceTimer.getElapsedTimeF32();
-}
-
-void LLCircuitData::dumpResendCountAndReset()
-{
- if (mCurrentResendCount)
- {
- LL_INFOS() << "Circuit: " << mHost << " resent " << mCurrentResendCount << " packets" << LL_ENDL;
- mCurrentResendCount = 0;
- }
-}
-
-std::ostream& operator<<(std::ostream& s, LLCircuit &circuit)
-{
- s << "Circuit Info:" << std::endl;
- LLCircuit::circuit_data_map::iterator end = circuit.mCircuitData.end();
- LLCircuit::circuit_data_map::iterator it;
- for(it = circuit.mCircuitData.begin(); it != end; ++it)
- {
- s << *((*it).second) << std::endl;
- }
- return s;
-}
-
-void LLCircuit::getInfo(LLSD& info) const
-{
- LLCircuit::circuit_data_map::const_iterator end = mCircuitData.end();
- LLCircuit::circuit_data_map::const_iterator it;
- LLSD circuit_info;
- for(it = mCircuitData.begin(); it != end; ++it)
- {
- (*it).second->getInfo(circuit_info);
- info["Circuits"].append(circuit_info);
- }
-}
-
-void LLCircuit::getCircuitRange(
- const LLHost& key,
- LLCircuit::circuit_data_map::iterator& first,
- LLCircuit::circuit_data_map::iterator& end)
-{
- end = mCircuitData.end();
- first = mCircuitData.upper_bound(key);
-}
-
-TPACKETID LLCircuitData::nextPacketOutID()
-{
- mPacketsOut++;
-
- TPACKETID id;
-
- id = (mPacketsOutID + 1) % LL_MAX_OUT_PACKET_ID;
-
- if (id < mPacketsOutID)
- {
- // we just wrapped on a circuit, reset the wrap ID to zero
- mWrapID = 0;
- }
- mPacketsOutID = id;
- return id;
-}
-
-
-void LLCircuitData::setPacketInID(TPACKETID id)
-{
- id = id % LL_MAX_OUT_PACKET_ID;
- mPacketsInID = id;
- mRecentlyReceivedReliablePackets.clear();
-
- mWrapID = id;
-}
-
-
-void LLCircuitData::pingTimerStop(const U8 ping_id)
-{
- F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
-
- // Nota Bene: no averaging of ping times until we get a feel for how this works
- F64Seconds time = mt_secs - mPingTime;
- if (time == F32Seconds(0.0))
- {
- // Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise
- // all of our ping calculations will be skewed.
- mt_secs = LLMessageSystem::getMessageTimeSeconds(true);
- }
- mLastPingReceivedTime = mt_secs;
-
- // If ping is longer than 1 second, we'll get sequence deltas in the ping.
- // Approximate by assuming each ping counts for 1 second (slightly low, probably)
- S32 delta_ping = (S32)mLastPingID - (S32) ping_id;
- if (delta_ping < 0)
- {
- delta_ping += 256;
- }
-
- U32Milliseconds msec = delta_ping*mHeartbeatInterval + time;
- setPingDelay(msec);
-
- mPingsInTransit = delta_ping;
- if (mBlocked && (mPingsInTransit <= PING_RELEASE_BLOCK))
- {
- mBlocked = false;
- }
-}
-
-
-void LLCircuitData::pingTimerStart()
-{
- mPingTime = LLMessageSystem::getMessageTimeSeconds();
- mPingsInTransit++;
-
- if (!mBlocked && (mPingsInTransit > PING_START_BLOCK))
- {
- mBlocked = true;
- }
-}
-
-
-U32 LLCircuitData::getPacketsIn() const
-{
- return mPacketsIn;
-}
-
-
-S32Bytes LLCircuitData::getBytesIn() const
-{
- return mBytesIn;
-}
-
-
-S32Bytes LLCircuitData::getBytesOut() const
-{
- return mBytesOut;
-}
-
-
-U32 LLCircuitData::getPacketsOut() const
-{
- return mPacketsOut;
-}
-
-
-TPACKETID LLCircuitData::getPacketOutID() const
-{
- return mPacketsOutID;
-}
-
-
-U32 LLCircuitData::getPacketsLost() const
-{
- return mPacketsLost;
-}
-
-
-bool LLCircuitData::isAlive() const
-{
- return mbAlive;
-}
-
-
-bool LLCircuitData::isBlocked() const
-{
- return mBlocked;
-}
-
-
-bool LLCircuitData::getAllowTimeout() const
-{
- return mbAllowTimeout;
-}
-
-
-U32Milliseconds LLCircuitData::getPingDelay() const
-{
- return mPingDelay;
-}
-
-
-F32Milliseconds LLCircuitData::getPingInTransitTime()
-{
- // This may be inaccurate in the case of a circuit that was "dead" and then revived,
- // but only until the first round trip ping is sent - djs
- F32Milliseconds time_since_ping_was_sent(0);
-
- if (mPingsInTransit)
- {
- time_since_ping_was_sent = F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
- + (LLMessageSystem::getMessageTimeSeconds() - mPingTime)));
- }
-
- return time_since_ping_was_sent;
-}
-
-
-void LLCircuitData::setPingDelay(U32Milliseconds ping)
-{
- mPingDelay = ping;
- mPingDelayAveraged = llmax((F32Milliseconds)ping, getPingDelayAveraged());
- mPingDelayAveraged = ((1.f - LL_AVERAGED_PING_ALPHA) * mPingDelayAveraged)
- + (LL_AVERAGED_PING_ALPHA * (F32Milliseconds) ping);
- mPingDelayAveraged = llclamp(mPingDelayAveraged,
- LL_AVERAGED_PING_MIN,
- LL_AVERAGED_PING_MAX);
-}
-
-
-F32Milliseconds LLCircuitData::getPingDelayAveraged()
-{
- return llmin(llmax(getPingInTransitTime(), mPingDelayAveraged), LL_AVERAGED_PING_MAX);
-}
-
-
-bool LLCircuitData::getTrusted() const
-{
- return mTrusted;
-}
-
-
-void LLCircuitData::setTrusted(bool t)
-{
- mTrusted = t;
-}
-
-F32 LLCircuitData::getAgeInSeconds() const
-{
- return mExistenceTimer.getElapsedTimeF32();
-}
+/**
+ * @file llcircuit.cpp
+ * @brief Class to track UDP endpoints for the message system.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#if LL_WINDOWS
+
+#include <process.h>
+
+#else
+
+#if LL_LINUX
+#include <dlfcn.h> // RTLD_LAZY
+#endif
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#endif
+
+
+#if !defined(USE_CIRCUIT_LIST)
+#include <algorithm>
+#endif
+#include <sstream>
+#include <iterator>
+#include <stack>
+
+#include "llcircuit.h"
+
+#include "message.h"
+#include "llrand.h"
+#include "llstl.h"
+#include "lltransfermanager.h"
+#include "llmodularmath.h"
+
+const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked.
+const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked.
+
+const F32Seconds TARGET_PERIOD_LENGTH(5.f);
+const F32Seconds LL_DUPLICATE_SUPPRESSION_TIMEOUT(60.f); //this can be long, as time-based cleanup is
+ // only done when wrapping packetids, now...
+
+LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
+ const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
+: mHost (host),
+ mWrapID(0),
+ mPacketsOutID(0),
+ mPacketsInID(in_id),
+ mHighestPacketID(in_id),
+ mTimeoutCallback(NULL),
+ mTimeoutUserData(NULL),
+ mTrusted(false),
+ mbAllowTimeout(true),
+ mbAlive(true),
+ mBlocked(false),
+ mPingTime(0.0),
+ mLastPingSendTime(0.0),
+ mLastPingReceivedTime(0.0),
+ mNextPingSendTime(0.0),
+ mPingsInTransit(0),
+ mLastPingID(0),
+ mPingDelay(INITIAL_PING_VALUE_MSEC),
+ mPingDelayAveraged(INITIAL_PING_VALUE_MSEC),
+ mUnackedPacketCount(0),
+ mUnackedPacketBytes(0),
+ mLastPacketInTime(0.0),
+ mLocalEndPointID(),
+ mPacketsOut(0),
+ mPacketsIn(0),
+ mPacketsLost(0),
+ mBytesIn(0),
+ mBytesOut(0),
+ mLastPeriodLength(-1.f),
+ mBytesInLastPeriod(0),
+ mBytesOutLastPeriod(0),
+ mBytesInThisPeriod(0),
+ mBytesOutThisPeriod(0),
+ mPeakBPSIn(0.f),
+ mPeakBPSOut(0.f),
+ mPeriodTime(0.0),
+ mExistenceTimer(),
+ mAckCreationTime(0.f),
+ mCurrentResendCount(0),
+ mLastPacketGap(0),
+ mHeartbeatInterval(circuit_heartbeat_interval),
+ mHeartbeatTimeout(circuit_timeout)
+{
+ // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
+ // running a message system loop.
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(true);
+ F32 distribution_offset = ll_frand();
+
+ mPingTime = mt_sec;
+ mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset;
+ mLastPingReceivedTime = mt_sec;
+ mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
+ mPeriodTime = mt_sec;
+
+ mLocalEndPointID.generate();
+}
+
+
+LLCircuitData::~LLCircuitData()
+{
+ LLReliablePacket *packetp = NULL;
+
+ // Clean up all pending transfers.
+ gTransferManager.cleanupConnection(mHost);
+
+ // remove all pending reliable messages on this circuit
+ std::vector<TPACKETID> doomed;
+ reliable_iter iter;
+ reliable_iter end = mUnackedPackets.end();
+ for(iter = mUnackedPackets.begin(); iter != end; ++iter)
+ {
+ packetp = iter->second;
+ gMessageSystem->mFailedResendPackets++;
+ if(gMessageSystem->mVerboseLog)
+ {
+ doomed.push_back(packetp->mPacketID);
+ }
+ if (packetp->mCallback)
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
+ }
+
+ // Update stats
+ mUnackedPacketCount--;
+ mUnackedPacketBytes -= packetp->mBufferLength;
+
+ delete packetp;
+ }
+
+ // remove all pending final retry reliable messages on this circuit
+ end = mFinalRetryPackets.end();
+ for(iter = mFinalRetryPackets.begin(); iter != end; ++iter)
+ {
+ packetp = iter->second;
+ gMessageSystem->mFailedResendPackets++;
+ if(gMessageSystem->mVerboseLog)
+ {
+ doomed.push_back(packetp->mPacketID);
+ }
+ if (packetp->mCallback)
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_CIRCUIT_GONE);
+ }
+
+ // Update stats
+ mUnackedPacketCount--;
+ mUnackedPacketBytes -= packetp->mBufferLength;
+
+ delete packetp;
+ }
+
+ // log aborted reliable packets for this circuit.
+ if(gMessageSystem->mVerboseLog && !doomed.empty())
+ {
+ std::ostringstream str;
+ std::ostream_iterator<TPACKETID> append(str, " ");
+ str << "MSG: -> " << mHost << "\tABORTING RELIABLE:\t";
+ std::copy(doomed.begin(), doomed.end(), append);
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+}
+
+
+void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
+{
+ reliable_iter iter;
+ LLReliablePacket *packetp;
+
+ iter = mUnackedPackets.find(packet_num);
+ if (iter != mUnackedPackets.end())
+ {
+ packetp = iter->second;
+
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
+ << packetp->mPacketID;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+ if (packetp->mCallback)
+ {
+ if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
+ }
+ else
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
+ }
+ }
+
+ // Update stats
+ mUnackedPacketCount--;
+ mUnackedPacketBytes -= packetp->mBufferLength;
+
+ // Cleanup
+ delete packetp;
+ mUnackedPackets.erase(iter);
+ return;
+ }
+
+ iter = mFinalRetryPackets.find(packet_num);
+ if (iter != mFinalRetryPackets.end())
+ {
+ packetp = iter->second;
+ // LL_INFOS() << "Packet " << packet_num << " removed from the pending list" << LL_ENDL;
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << packetp->mHost << "\tRELIABLE ACKED:\t"
+ << packetp->mPacketID;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+ if (packetp->mCallback)
+ {
+ if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
+ }
+ else
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_NOERR);
+ }
+ }
+
+ // Update stats
+ mUnackedPacketCount--;
+ mUnackedPacketBytes -= packetp->mBufferLength;
+
+ // Cleanup
+ delete packetp;
+ mFinalRetryPackets.erase(iter);
+ }
+ else
+ {
+ // Couldn't find this packet on either of the unacked lists.
+ // maybe it's a duplicate ack?
+ }
+}
+
+
+
+S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
+{
+ LLReliablePacket *packetp;
+
+
+ //
+ // Theoretically we should search through the list for the packet with the oldest
+ // packet ID, as otherwise when we WRAP we will resend reliable packets out of order.
+ // Since resends are ALREADY out of order, and wrapping is highly rare (16+million packets),
+ // I'm not going to worry about this for now - djs
+ //
+
+ reliable_iter iter;
+ bool have_resend_overflow = false;
+ for (iter = mUnackedPackets.begin(); iter != mUnackedPackets.end();)
+ {
+ packetp = iter->second;
+
+ // Only check overflow if we haven't had one yet.
+ if (!have_resend_overflow)
+ {
+ have_resend_overflow = mThrottles.checkOverflow(TC_RESEND, 0);
+ }
+
+ if (have_resend_overflow)
+ {
+ // We've exceeded our bandwidth for resends.
+ // Time to stop trying to send them.
+
+ // If we have too many unacked packets, we need to start dropping expired ones.
+ if (mUnackedPacketBytes > 512000)
+ {
+ if (now > packetp->mExpirationTime)
+ {
+ // This circuit has overflowed. Do not retry. Do not pass go.
+ packetp->mRetries = 0;
+ // Remove it from this list and add it to the final list.
+ mUnackedPackets.erase(iter++);
+ mFinalRetryPackets[packetp->mPacketID] = packetp;
+ }
+ else
+ {
+ ++iter;
+ }
+ // Move on to the next unacked packet.
+ continue;
+ }
+
+ if (mUnackedPacketBytes > 256000 && !(getPacketsOut() % 1024))
+ {
+ // Warn if we've got a lot of resends waiting.
+ LL_WARNS() << mHost << " has " << mUnackedPacketBytes
+ << " bytes of reliable messages waiting" << LL_ENDL;
+ }
+ // Stop resending. There are less than 512000 unacked packets.
+ break;
+ }
+
+ if (now > packetp->mExpirationTime)
+ {
+ packetp->mRetries--;
+
+ // retry
+ mCurrentResendCount++;
+
+ gMessageSystem->mResentPackets++;
+
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: -> " << packetp->mHost
+ << "\tRESENDING RELIABLE:\t" << packetp->mPacketID;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+
+ packetp->mBuffer[0] |= LL_RESENT_FLAG; // tag packet id as being a resend
+
+ gMessageSystem->mPacketRing.sendPacket(packetp->mSocket,
+ (char *)packetp->mBuffer, packetp->mBufferLength,
+ packetp->mHost);
+
+ mThrottles.throttleOverflow(TC_RESEND, packetp->mBufferLength * 8.f);
+
+ // The new method, retry time based on ping
+ if (packetp->mPingBasedRetry)
+ {
+ packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged()));
+ }
+ else
+ {
+ // custom, constant retry time
+ packetp->mExpirationTime = now + packetp->mTimeout;
+ }
+
+ if (!packetp->mRetries)
+ {
+ // Last resend, remove it from this list and add it to the final list.
+ mUnackedPackets.erase(iter++);
+ mFinalRetryPackets[packetp->mPacketID] = packetp;
+ }
+ else
+ {
+ // Don't remove it yet, it still gets to try to resend at least once.
+ ++iter;
+ }
+ }
+ else
+ {
+ // Don't need to do anything with this packet, keep iterating.
+ ++iter;
+ }
+ }
+
+
+ for (iter = mFinalRetryPackets.begin(); iter != mFinalRetryPackets.end();)
+ {
+ packetp = iter->second;
+ if (now > packetp->mExpirationTime)
+ {
+ // fail (too many retries)
+ //LL_INFOS() << "Packet " << packetp->mPacketID << " removed from the pending list: exceeded retry limit" << LL_ENDL;
+ //if (packetp->mMessageName)
+ //{
+ // LL_INFOS() << "Packet name " << packetp->mMessageName << LL_ENDL;
+ //}
+ gMessageSystem->mFailedResendPackets++;
+
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: -> " << packetp->mHost << "\tABORTING RELIABLE:\t"
+ << packetp->mPacketID;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+
+ if (packetp->mCallback)
+ {
+ packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
+ }
+
+ // Update stats
+ mUnackedPacketCount--;
+ mUnackedPacketBytes -= packetp->mBufferLength;
+
+ mFinalRetryPackets.erase(iter++);
+ delete packetp;
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+
+ return mUnackedPacketCount;
+}
+
+
+LLCircuit::LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
+: mLastCircuit(NULL),
+ mHeartbeatInterval(circuit_heartbeat_interval),
+ mHeartbeatTimeout(circuit_timeout)
+{}
+
+LLCircuit::~LLCircuit()
+{
+ // delete pointers in the map.
+ std::for_each(mCircuitData.begin(),
+ mCircuitData.end(),
+ llcompose1(
+ DeletePointerFunctor<LLCircuitData>(),
+ llselect2nd<circuit_data_map::value_type>()));
+}
+
+LLCircuitData *LLCircuit::addCircuitData(const LLHost &host, TPACKETID in_id)
+{
+ // This should really validate if one already exists
+ LL_INFOS() << "LLCircuit::addCircuitData for " << host << LL_ENDL;
+ LLCircuitData *tempp = new LLCircuitData(host, in_id, mHeartbeatInterval, mHeartbeatTimeout);
+ mCircuitData.insert(circuit_data_map::value_type(host, tempp));
+ mPingSet.insert(tempp);
+
+ mLastCircuit = tempp;
+ return tempp;
+}
+
+void LLCircuit::removeCircuitData(const LLHost &host)
+{
+ LL_INFOS() << "LLCircuit::removeCircuitData for " << host << LL_ENDL;
+ mLastCircuit = NULL;
+ circuit_data_map::iterator it = mCircuitData.find(host);
+ if(it != mCircuitData.end())
+ {
+ LLCircuitData *cdp = it->second;
+ mCircuitData.erase(it);
+
+ LLCircuit::ping_set_t::iterator psit = mPingSet.find(cdp);
+ if (psit != mPingSet.end())
+ {
+ mPingSet.erase(psit);
+ }
+ else
+ {
+ LL_WARNS() << "Couldn't find entry for next ping in ping set!" << LL_ENDL;
+ }
+
+ // Clean up from optimization maps
+ mUnackedCircuitMap.erase(host);
+ mSendAckMap.erase(host);
+ delete cdp;
+ }
+
+ // This also has to happen AFTER we nuke the circuit, because various
+ // callbacks for the circuit may result in messages being sent to
+ // this circuit, and the setting of mLastCircuit. We don't check
+ // if the host matches, but we don't really care because mLastCircuit
+ // is an optimization, and this happens VERY rarely.
+ mLastCircuit = NULL;
+}
+
+void LLCircuitData::setAlive(bool b_alive)
+{
+ if (mbAlive != b_alive)
+ {
+ mPacketsOutID = 0;
+ mPacketsInID = 0;
+ mbAlive = b_alive;
+ }
+ if (b_alive)
+ {
+ mLastPingReceivedTime = LLMessageSystem::getMessageTimeSeconds();
+ mPingsInTransit = 0;
+ mBlocked = false;
+ }
+}
+
+
+void LLCircuitData::setAllowTimeout(bool allow)
+{
+ mbAllowTimeout = allow;
+
+ if (allow)
+ {
+ // resuming circuit
+ // make sure it's alive
+ setAlive(true);
+ }
+}
+
+
+// Reset per-period counters if necessary.
+void LLCircuitData::checkPeriodTime()
+{
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
+ F64Seconds period_length = mt_sec - mPeriodTime;
+ if ( period_length > TARGET_PERIOD_LENGTH)
+ {
+ F32 bps_in = F32Bits(mBytesInThisPeriod).value() / period_length.value();
+ if (bps_in > mPeakBPSIn)
+ {
+ mPeakBPSIn = bps_in;
+ }
+
+ F32 bps_out = F32Bits(mBytesOutThisPeriod).value() / period_length.value();
+ if (bps_out > mPeakBPSOut)
+ {
+ mPeakBPSOut = bps_out;
+ }
+
+ mBytesInLastPeriod = mBytesInThisPeriod;
+ mBytesOutLastPeriod = mBytesOutThisPeriod;
+ mBytesInThisPeriod = S32Bytes(0);
+ mBytesOutThisPeriod = S32Bytes(0);
+ mLastPeriodLength = F32Seconds::convert(period_length);
+
+ mPeriodTime = mt_sec;
+ }
+}
+
+
+void LLCircuitData::addBytesIn(S32Bytes bytes)
+{
+ mBytesIn += bytes;
+ mBytesInThisPeriod += bytes;
+}
+
+
+void LLCircuitData::addBytesOut(S32Bytes bytes)
+{
+ mBytesOut += bytes;
+ mBytesOutThisPeriod += bytes;
+}
+
+
+void LLCircuitData::addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params)
+{
+ LLReliablePacket *packet_info;
+
+ packet_info = new LLReliablePacket(mSocket, buf_ptr, buf_len, params);
+
+ mUnackedPacketCount++;
+ mUnackedPacketBytes += packet_info->mBufferLength;
+
+ if (params && params->mRetries)
+ {
+ mUnackedPackets[packet_info->mPacketID] = packet_info;
+ }
+ else
+ {
+ mFinalRetryPackets[packet_info->mPacketID] = packet_info;
+ }
+}
+
+
+void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size)
+{
+ F64Seconds now = LLMessageSystem::getMessageTimeSeconds();
+ unacked_list_length = 0;
+ unacked_list_size = 0;
+
+ LLCircuitData* circ;
+ circuit_data_map::iterator end = mUnackedCircuitMap.end();
+ for(circuit_data_map::iterator it = mUnackedCircuitMap.begin(); it != end; ++it)
+ {
+ circ = (*it).second;
+ unacked_list_length += circ->resendUnackedPackets(now);
+ unacked_list_size += circ->getUnackedPacketBytes();
+ }
+}
+
+
+bool LLCircuitData::isDuplicateResend(TPACKETID packetnum)
+{
+ return (mRecentlyReceivedReliablePackets.find(packetnum) != mRecentlyReceivedReliablePackets.end());
+}
+
+
+void LLCircuit::dumpResends()
+{
+ circuit_data_map::iterator end = mCircuitData.end();
+ for(circuit_data_map::iterator it = mCircuitData.begin(); it != end; ++it)
+ {
+ (*it).second->dumpResendCountAndReset();
+ }
+}
+
+LLCircuitData* LLCircuit::findCircuit(const LLHost& host) const
+{
+ // An optimization on finding the previously found circuit.
+ if (mLastCircuit && (mLastCircuit->mHost == host))
+ {
+ return mLastCircuit;
+ }
+
+ circuit_data_map::const_iterator it = mCircuitData.find(host);
+ if(it == mCircuitData.end())
+ {
+ return NULL;
+ }
+ mLastCircuit = it->second;
+ return mLastCircuit;
+}
+
+
+bool LLCircuit::isCircuitAlive(const LLHost& host) const
+{
+ LLCircuitData *cdp = findCircuit(host);
+ if(cdp)
+ {
+ return cdp->mbAlive;
+ }
+
+ return false;
+}
+
+void LLCircuitData::setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data)
+{
+ mTimeoutCallback = callback_func;
+ mTimeoutUserData = user_data;
+}
+
+void LLCircuitData::checkPacketInID(TPACKETID id, bool receive_resent)
+{
+ // Done as floats so we don't have to worry about running out of room
+ // with U32 getting poked into an S32.
+ F32 delta = (F32)mHighestPacketID - (F32)id;
+ if (delta > (0.5f*LL_MAX_OUT_PACKET_ID))
+ {
+ // We've almost definitely wrapped, reset the mLastPacketID to be low again.
+ mHighestPacketID = id;
+ }
+ else if (delta < (-0.5f*LL_MAX_OUT_PACKET_ID))
+ {
+ // This is almost definitely an old packet coming in after a wrap, ignore it.
+ }
+ else
+ {
+ mHighestPacketID = llmax(mHighestPacketID, id);
+ }
+
+ // Save packet arrival time
+ mLastPacketInTime = LLMessageSystem::getMessageTimeSeconds();
+
+ // Have we received anything on this circuit yet?
+ if (0 == mPacketsIn)
+ {
+ // Must be first packet from unclosed circuit.
+ mPacketsIn++;
+ setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
+
+ mLastPacketGap = 0;
+ return;
+ }
+
+ mPacketsIn++;
+
+
+ // now, check to see if we've got a gap
+ U32 gap = 0;
+ if (mPacketsInID == id)
+ {
+ // nope! bump and wrap the counter, then return
+ mPacketsInID++;
+ mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
+ }
+ else if (id < mWrapID)
+ {
+ // id < mWrapID will happen if the first few packets are out of order. . .
+ // at that point we haven't marked anything "potentially lost" and
+ // the out-of-order packet will cause a full wrap marking all the IDs "potentially lost"
+
+ // do nothing
+ }
+ else
+ {
+ // we have a gap! if that id is in the map, remove it from the map, leave mCurrentCircuit->mPacketsInID
+ // alone
+ // otherwise, walk from mCurrentCircuit->mPacketsInID to id with wrapping, adding the values to the map
+ // and setting mPacketsInID to id + 1 % LL_MAX_OUT_PACKET_ID
+
+ // babbage: all operands in expression are unsigned, so modular
+ // arithmetic will always find correct gap, regardless of wrap arounds.
+ const U8 width = 24;
+ gap = LLModularMath::subtract<width>(mPacketsInID, id);
+
+ if (mPotentialLostPackets.find(id) != mPotentialLostPackets.end())
+ {
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << mHost << "\tRECOVERING LOST:\t" << id;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+ // LL_INFOS() << "removing potential lost: " << id << LL_ENDL;
+ mPotentialLostPackets.erase(id);
+ }
+ else if (!receive_resent) // don't freak out over out-of-order reliable resends
+ {
+ U64Microseconds time = LLMessageSystem::getMessageTimeUsecs();
+ TPACKETID index = mPacketsInID;
+ S32 gap_count = 0;
+ if ((index < id) && ((id - index) < 16))
+ {
+ while (index != id)
+ {
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
+ << index;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+
+// LL_INFOS() << "adding potential lost: " << index << LL_ENDL;
+ mPotentialLostPackets[index] = time;
+ index++;
+ index = index % LL_MAX_OUT_PACKET_ID;
+ gap_count++;
+ }
+ }
+ else
+ {
+ LL_INFOS() << "packet_out_of_order - got packet " << id << " expecting " << index << " from " << mHost << LL_ENDL;
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << mHost << "\tPACKET GAP:\t"
+ << id << " expected " << index;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+ }
+
+ mPacketsInID = id + 1;
+ mPacketsInID = (mPacketsInID) % LL_MAX_OUT_PACKET_ID;
+
+ if (gap_count > 128)
+ {
+ LL_WARNS() << "Packet loss gap filler running amok!" << LL_ENDL;
+ }
+ else if (gap_count > 16)
+ {
+ LL_WARNS() << "Sustaining large amounts of packet loss!" << LL_ENDL;
+ }
+
+ }
+ }
+ mLastPacketGap = gap;
+}
+
+
+void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
+{
+ F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
+ S32 count = mPingSet.size();
+ S32 cur = 0;
+
+ // Only process each circuit once at most, stop processing if no circuits
+ while((cur < count) && !mPingSet.empty())
+ {
+ cur++;
+
+ LLCircuit::ping_set_t::iterator psit = mPingSet.begin();
+ LLCircuitData *cdp = *psit;
+
+ if (!cdp->mbAlive)
+ {
+ // We suspect that this case should never happen, given how
+ // the alive status is set.
+ // Skip over dead circuits, just add the ping interval and push it to the back
+ // Always remember to remove it from the set before changing the sorting
+ // key (mNextPingSendTime)
+ mPingSet.erase(psit);
+ cdp->mNextPingSendTime = cur_time + mHeartbeatInterval;
+ mPingSet.insert(cdp);
+ continue;
+ }
+ else
+ {
+ // Check to see if this needs a ping
+ if (cur_time < cdp->mNextPingSendTime)
+ {
+ // This circuit doesn't need a ping, break out because
+ // we have a sorted list, thus no more circuits need pings
+ break;
+ }
+
+ // Update watchdog timers
+ if (cdp->updateWatchDogTimers(msgsys))
+ {
+ // Randomize our pings a bit by doing some up to 5% early or late
+ F64Seconds dt = 0.95f*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
+
+ // Remove it, and reinsert it with the new next ping time.
+ // Always remove before changing the sorting key.
+ mPingSet.erase(psit);
+ cdp->mNextPingSendTime = cur_time + dt;
+ mPingSet.insert(cdp);
+
+ // Update our throttles
+ cdp->mThrottles.dynamicAdjust();
+
+ // Update some stats, this is not terribly important
+ cdp->checkPeriodTime();
+ }
+ else
+ {
+ // This mPingSet.erase isn't necessary, because removing the circuit will
+ // remove the ping set.
+ //mPingSet.erase(psit);
+ removeCircuitData(cdp->mHost);
+ }
+ }
+ }
+}
+
+
+bool LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
+{
+ F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
+ mLastPingSendTime = cur_time;
+
+ if (!checkCircuitTimeout())
+ {
+ // Pass this back to the calling LLCircuit, this circuit needs to be cleaned up.
+ return false;
+ }
+
+ // WARNING!
+ // Duplicate suppression can FAIL if packets are delivered out of
+ // order, although it's EXTREMELY unlikely. It would require
+ // that the ping get delivered out of order enough that the ACK
+ // for the packet that it was out of order with was received BEFORE
+ // the ping was sent.
+
+ // Find the current oldest reliable packetID
+ // This is to handle the case if we actually manage to wrap our
+ // packet IDs - the oldest will actually have a higher packet ID
+ // than the current.
+ bool wrapped = false;
+ reliable_iter iter;
+ iter = mUnackedPackets.upper_bound(getPacketOutID());
+ if (iter == mUnackedPackets.end())
+ {
+ // Nothing AFTER this one, so we want the lowest packet ID
+ // then.
+ iter = mUnackedPackets.begin();
+ wrapped = true;
+ }
+
+ TPACKETID packet_id = 0;
+
+ // Check against the "final" packets
+ bool wrapped_final = false;
+ reliable_iter iter_final;
+ iter_final = mFinalRetryPackets.upper_bound(getPacketOutID());
+ if (iter_final == mFinalRetryPackets.end())
+ {
+ iter_final = mFinalRetryPackets.begin();
+ wrapped_final = true;
+ }
+
+ //LL_INFOS() << mHost << " - unacked count " << mUnackedPackets.size() << LL_ENDL;
+ //LL_INFOS() << mHost << " - final count " << mFinalRetryPackets.size() << LL_ENDL;
+ if (wrapped != wrapped_final)
+ {
+ // One of the "unacked" or "final" lists hasn't wrapped. Whichever one
+ // hasn't has the oldest packet.
+ if (!wrapped)
+ {
+ // Hasn't wrapped, so the one on the
+ // unacked packet list is older
+ packet_id = iter->first;
+ //LL_INFOS() << mHost << ": nowrapped unacked" << LL_ENDL;
+ }
+ else
+ {
+ packet_id = iter_final->first;
+ //LL_INFOS() << mHost << ": nowrapped final" << LL_ENDL;
+ }
+ }
+ else
+ {
+ // They both wrapped, we can just use the minimum of the two.
+ if ((iter == mUnackedPackets.end()) && (iter_final == mFinalRetryPackets.end()))
+ {
+ // Wow! No unacked packets at all!
+ // Send the ID of the last packet we sent out.
+ // This will flush all of the destination's
+ // unacked packets, theoretically.
+ //LL_INFOS() << mHost << ": No unacked!" << LL_ENDL;
+ packet_id = getPacketOutID();
+ }
+ else
+ {
+ bool had_unacked = false;
+ if (iter != mUnackedPackets.end())
+ {
+ // Unacked list has the lowest so far
+ packet_id = iter->first;
+ had_unacked = true;
+ //LL_INFOS() << mHost << ": Unacked" << LL_ENDL;
+ }
+
+ if (iter_final != mFinalRetryPackets.end())
+ {
+ // Use the lowest of the unacked list and the final list
+ if (had_unacked)
+ {
+ // Both had a packet, use the lowest.
+ packet_id = llmin(packet_id, iter_final->first);
+ //LL_INFOS() << mHost << ": Min of unacked/final" << LL_ENDL;
+ }
+ else
+ {
+ // Only the final had a packet, use it.
+ packet_id = iter_final->first;
+ //LL_INFOS() << mHost << ": Final!" << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ // Send off the another ping.
+ pingTimerStart();
+ msgsys->newMessageFast(_PREHASH_StartPingCheck);
+ msgsys->nextBlock(_PREHASH_PingID);
+ msgsys->addU8Fast(_PREHASH_PingID, nextPingID());
+ msgsys->addU32Fast(_PREHASH_OldestUnacked, packet_id);
+ msgsys->sendMessage(mHost);
+
+ // Also do lost packet accounting.
+ // Check to see if anything on our lost list is old enough to
+ // be considered lost
+
+ LLCircuitData::packet_time_map::iterator it;
+ U64Microseconds timeout = llmin(LL_MAX_LOST_TIMEOUT, F32Seconds(getPingDelayAveraged()) * LL_LOST_TIMEOUT_FACTOR);
+
+ U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
+ for (it = mPotentialLostPackets.begin(); it != mPotentialLostPackets.end(); )
+ {
+ U64Microseconds delta_t_usec = mt_usec - (*it).second;
+ if (delta_t_usec > timeout)
+ {
+ // let's call this one a loss!
+ mPacketsLost++;
+ gMessageSystem->mDroppedPackets++;
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << mHost << "\tLOST PACKET:\t"
+ << (*it).first;
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+ mPotentialLostPackets.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ return true;
+}
+
+
+void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
+{
+ // purge old data from the duplicate suppression queue
+
+ // we want to KEEP all x where oldest_id <= x <= last incoming packet, and delete everything else.
+
+ //LL_INFOS() << mHost << ": clearing before oldest " << oldest_id << LL_ENDL;
+ //LL_INFOS() << "Recent list before: " << mRecentlyReceivedReliablePackets.size() << LL_ENDL;
+ if (oldest_id < mHighestPacketID)
+ {
+ // Clean up everything with a packet ID less than oldest_id.
+ packet_time_map::iterator pit_start;
+ packet_time_map::iterator pit_end;
+ pit_start = mRecentlyReceivedReliablePackets.begin();
+ pit_end = mRecentlyReceivedReliablePackets.lower_bound(oldest_id);
+ mRecentlyReceivedReliablePackets.erase(pit_start, pit_end);
+ }
+
+ // Do timeout checks on everything with an ID > mHighestPacketID.
+ // This should be empty except for wrapping IDs. Thus, this should be
+ // highly rare.
+ U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
+
+ packet_time_map::iterator pit;
+ for(pit = mRecentlyReceivedReliablePackets.upper_bound(mHighestPacketID);
+ pit != mRecentlyReceivedReliablePackets.end(); )
+ {
+ // Validate that the packet ID seems far enough away
+ if ((pit->first - mHighestPacketID) < 100)
+ {
+ LL_WARNS() << "Probably incorrectly timing out non-wrapped packets!" << LL_ENDL;
+ }
+ U64Microseconds delta_t_usec = mt_usec - (*pit).second;
+ F64Seconds delta_t_sec = delta_t_usec;
+ if (delta_t_sec > LL_DUPLICATE_SUPPRESSION_TIMEOUT)
+ {
+ // enough time has elapsed we're not likely to get a duplicate on this one
+ LL_INFOS() << "Clearing " << pit->first << " from recent list" << LL_ENDL;
+ mRecentlyReceivedReliablePackets.erase(pit++);
+ }
+ else
+ {
+ ++pit;
+ }
+ }
+ //LL_INFOS() << "Recent list after: " << mRecentlyReceivedReliablePackets.size() << LL_ENDL;
+}
+
+bool LLCircuitData::checkCircuitTimeout()
+{
+ F64Seconds time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
+
+ // Nota Bene: This needs to be turned off if you are debugging multiple simulators
+ if (time_since_last_ping > mHeartbeatTimeout)
+ {
+ LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " last ping " << time_since_last_ping << " seconds ago." <<LL_ENDL;
+ setAlive(false);
+ if (mTimeoutCallback)
+ {
+ LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " calling callback." << LL_ENDL;
+ mTimeoutCallback(mHost, mTimeoutUserData);
+ }
+ if (!isAlive())
+ {
+ // The callback didn't try and resurrect the circuit. We should kill it.
+ LL_WARNS() << "LLCircuitData::checkCircuitTimeout for " << mHost << " still dead, dropping." << LL_ENDL;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Call this method when a reliable message comes in - this will
+// correctly place the packet in the correct list to be acked later.
+bool LLCircuitData::collectRAck(TPACKETID packet_num)
+{
+ if (mAcks.empty())
+ {
+ // First extra ack, we need to add ourselves to the list of circuits that need to send acks
+ gMessageSystem->mCircuitInfo.mSendAckMap[mHost] = this;
+ }
+
+ mAcks.push_back(packet_num);
+ if (mAckCreationTime == 0)
+ {
+ mAckCreationTime = getAgeInSeconds();
+ }
+ return true;
+}
+
+// this method is called during the message system processAcks() to
+// send out any acks that did not get sent already.
+void LLCircuit::sendAcks(F32 collect_time)
+{
+ collect_time = llclamp(collect_time, 0.f, LL_COLLECT_ACK_TIME_MAX);
+ LLCircuitData* cd;
+ circuit_data_map::iterator it = mSendAckMap.begin();
+ while (it != mSendAckMap.end())
+ {
+ circuit_data_map::iterator cur_it = it++;
+ cd = (*cur_it).second;
+ S32 count = (S32)cd->mAcks.size();
+ F32 age = cd->getAgeInSeconds() - cd->mAckCreationTime;
+ if (age > collect_time || count == 0)
+ {
+ if (count>0)
+ {
+ // send the packet acks
+ S32 acks_this_packet = 0;
+ for(S32 i = 0; i < count; ++i)
+ {
+ if(acks_this_packet == 0)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_PacketAck);
+ }
+ gMessageSystem->nextBlockFast(_PREHASH_Packets);
+ gMessageSystem->addU32Fast(_PREHASH_ID, cd->mAcks[i]);
+ ++acks_this_packet;
+ if(acks_this_packet > 250)
+ {
+ gMessageSystem->sendMessage(cd->mHost);
+ acks_this_packet = 0;
+ }
+ }
+ if(acks_this_packet > 0)
+ {
+ gMessageSystem->sendMessage(cd->mHost);
+ }
+
+ if(gMessageSystem->mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: -> " << cd->mHost << "\tPACKET ACKS:\t";
+ std::ostream_iterator<TPACKETID> append(str, " ");
+ std::copy(cd->mAcks.begin(), cd->mAcks.end(), append);
+ LL_INFOS() << str.str() << LL_ENDL;
+ }
+
+ // empty out the acks list
+ cd->mAcks.clear();
+ cd->mAckCreationTime = 0.f;
+ }
+ // remove data map
+ mSendAckMap.erase(cur_it);
+ }
+ }
+}
+
+
+std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit)
+{
+ F32 age = circuit.mExistenceTimer.getElapsedTimeF32();
+
+ using namespace std;
+ s << "Circuit " << circuit.mHost << " "
+ << circuit.mRemoteID << " "
+ << (circuit.mbAlive ? "Alive" : "Not Alive") << " "
+ << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed")
+ << endl;
+
+ s << " Packets Lost: " << circuit.mPacketsLost
+ << " Measured Ping: " << circuit.mPingDelay
+ << " Averaged Ping: " << circuit.mPingDelayAveraged
+ << endl;
+
+ s << "Global In/Out " << S32(age) << " sec"
+ << " KBytes: " << circuit.mBytesIn.valueInUnits<LLUnits::Kilobytes>() << "/" << circuit.mBytesOut.valueInUnits<LLUnits::Kilobytes>()
+ << " Kbps: "
+ << S32(circuit.mBytesIn.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
+ << "/"
+ << S32(circuit.mBytesOut.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
+ << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut
+ << endl;
+
+ s << "Recent In/Out " << circuit.mLastPeriodLength
+ << " KBytes: "
+ << circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobytes>()
+ << "/"
+ << circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobytes>()
+ << " Kbps: "
+ << (S32)(circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
+ << "/"
+ << (S32)(circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
+ << " Peak kbps: "
+ << S32(circuit.mPeakBPSIn / 1024.f)
+ << "/"
+ << S32(circuit.mPeakBPSOut / 1024.f)
+ << endl;
+
+ return s;
+}
+
+void LLCircuitData::getInfo(LLSD& info) const
+{
+ info["Host"] = mHost.getIPandPort();
+ info["Alive"] = mbAlive;
+ info["Age"] = mExistenceTimer.getElapsedTimeF32();
+}
+
+void LLCircuitData::dumpResendCountAndReset()
+{
+ if (mCurrentResendCount)
+ {
+ LL_INFOS() << "Circuit: " << mHost << " resent " << mCurrentResendCount << " packets" << LL_ENDL;
+ mCurrentResendCount = 0;
+ }
+}
+
+std::ostream& operator<<(std::ostream& s, LLCircuit &circuit)
+{
+ s << "Circuit Info:" << std::endl;
+ LLCircuit::circuit_data_map::iterator end = circuit.mCircuitData.end();
+ LLCircuit::circuit_data_map::iterator it;
+ for(it = circuit.mCircuitData.begin(); it != end; ++it)
+ {
+ s << *((*it).second) << std::endl;
+ }
+ return s;
+}
+
+void LLCircuit::getInfo(LLSD& info) const
+{
+ LLCircuit::circuit_data_map::const_iterator end = mCircuitData.end();
+ LLCircuit::circuit_data_map::const_iterator it;
+ LLSD circuit_info;
+ for(it = mCircuitData.begin(); it != end; ++it)
+ {
+ (*it).second->getInfo(circuit_info);
+ info["Circuits"].append(circuit_info);
+ }
+}
+
+void LLCircuit::getCircuitRange(
+ const LLHost& key,
+ LLCircuit::circuit_data_map::iterator& first,
+ LLCircuit::circuit_data_map::iterator& end)
+{
+ end = mCircuitData.end();
+ first = mCircuitData.upper_bound(key);
+}
+
+TPACKETID LLCircuitData::nextPacketOutID()
+{
+ mPacketsOut++;
+
+ TPACKETID id;
+
+ id = (mPacketsOutID + 1) % LL_MAX_OUT_PACKET_ID;
+
+ if (id < mPacketsOutID)
+ {
+ // we just wrapped on a circuit, reset the wrap ID to zero
+ mWrapID = 0;
+ }
+ mPacketsOutID = id;
+ return id;
+}
+
+
+void LLCircuitData::setPacketInID(TPACKETID id)
+{
+ id = id % LL_MAX_OUT_PACKET_ID;
+ mPacketsInID = id;
+ mRecentlyReceivedReliablePackets.clear();
+
+ mWrapID = id;
+}
+
+
+void LLCircuitData::pingTimerStop(const U8 ping_id)
+{
+ F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
+
+ // Nota Bene: no averaging of ping times until we get a feel for how this works
+ F64Seconds time = mt_secs - mPingTime;
+ if (time == F32Seconds(0.0))
+ {
+ // Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise
+ // all of our ping calculations will be skewed.
+ mt_secs = LLMessageSystem::getMessageTimeSeconds(true);
+ }
+ mLastPingReceivedTime = mt_secs;
+
+ // If ping is longer than 1 second, we'll get sequence deltas in the ping.
+ // Approximate by assuming each ping counts for 1 second (slightly low, probably)
+ S32 delta_ping = (S32)mLastPingID - (S32) ping_id;
+ if (delta_ping < 0)
+ {
+ delta_ping += 256;
+ }
+
+ U32Milliseconds msec = delta_ping*mHeartbeatInterval + time;
+ setPingDelay(msec);
+
+ mPingsInTransit = delta_ping;
+ if (mBlocked && (mPingsInTransit <= PING_RELEASE_BLOCK))
+ {
+ mBlocked = false;
+ }
+}
+
+
+void LLCircuitData::pingTimerStart()
+{
+ mPingTime = LLMessageSystem::getMessageTimeSeconds();
+ mPingsInTransit++;
+
+ if (!mBlocked && (mPingsInTransit > PING_START_BLOCK))
+ {
+ mBlocked = true;
+ }
+}
+
+
+U32 LLCircuitData::getPacketsIn() const
+{
+ return mPacketsIn;
+}
+
+
+S32Bytes LLCircuitData::getBytesIn() const
+{
+ return mBytesIn;
+}
+
+
+S32Bytes LLCircuitData::getBytesOut() const
+{
+ return mBytesOut;
+}
+
+
+U32 LLCircuitData::getPacketsOut() const
+{
+ return mPacketsOut;
+}
+
+
+TPACKETID LLCircuitData::getPacketOutID() const
+{
+ return mPacketsOutID;
+}
+
+
+U32 LLCircuitData::getPacketsLost() const
+{
+ return mPacketsLost;
+}
+
+
+bool LLCircuitData::isAlive() const
+{
+ return mbAlive;
+}
+
+
+bool LLCircuitData::isBlocked() const
+{
+ return mBlocked;
+}
+
+
+bool LLCircuitData::getAllowTimeout() const
+{
+ return mbAllowTimeout;
+}
+
+
+U32Milliseconds LLCircuitData::getPingDelay() const
+{
+ return mPingDelay;
+}
+
+
+F32Milliseconds LLCircuitData::getPingInTransitTime()
+{
+ // This may be inaccurate in the case of a circuit that was "dead" and then revived,
+ // but only until the first round trip ping is sent - djs
+ F32Milliseconds time_since_ping_was_sent(0);
+
+ if (mPingsInTransit)
+ {
+ time_since_ping_was_sent = F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
+ + (LLMessageSystem::getMessageTimeSeconds() - mPingTime)));
+ }
+
+ return time_since_ping_was_sent;
+}
+
+
+void LLCircuitData::setPingDelay(U32Milliseconds ping)
+{
+ mPingDelay = ping;
+ mPingDelayAveraged = llmax((F32Milliseconds)ping, getPingDelayAveraged());
+ mPingDelayAveraged = ((1.f - LL_AVERAGED_PING_ALPHA) * mPingDelayAveraged)
+ + (LL_AVERAGED_PING_ALPHA * (F32Milliseconds) ping);
+ mPingDelayAveraged = llclamp(mPingDelayAveraged,
+ LL_AVERAGED_PING_MIN,
+ LL_AVERAGED_PING_MAX);
+}
+
+
+F32Milliseconds LLCircuitData::getPingDelayAveraged()
+{
+ return llmin(llmax(getPingInTransitTime(), mPingDelayAveraged), LL_AVERAGED_PING_MAX);
+}
+
+
+bool LLCircuitData::getTrusted() const
+{
+ return mTrusted;
+}
+
+
+void LLCircuitData::setTrusted(bool t)
+{
+ mTrusted = t;
+}
+
+F32 LLCircuitData::getAgeInSeconds() const
+{
+ return mExistenceTimer.getElapsedTimeF32();
+}
diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h
index 95e470b543..ba38849f70 100644
--- a/indra/llmessage/llcircuit.h
+++ b/indra/llmessage/llcircuit.h
@@ -1,350 +1,350 @@
-/**
- * @file llcircuit.h
- * @brief Provides a method for tracking network circuit information
- * for the UDP message system
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCIRCUIT_H
-#define LL_LLCIRCUIT_H
-
-#include <map>
-#include <vector>
-
-#include "llerror.h"
-
-#include "lltimer.h"
-#include "net.h"
-#include "llhost.h"
-#include "llpacketack.h"
-#include "lluuid.h"
-#include "llthrottle.h"
-
-//
-// Constants
-//
-const F32 LL_AVERAGED_PING_ALPHA = 0.2f; // relaxation constant on ping running average
-const F32Milliseconds LL_AVERAGED_PING_MAX(2000);
-const F32Milliseconds LL_AVERAGED_PING_MIN(100); // increased to avoid retransmits when a process is slow
-
-const U32Milliseconds INITIAL_PING_VALUE_MSEC(1000); // initial value for the ping delay, or for ping delay for an unknown circuit
-
-const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000;
-const int LL_ERR_CIRCUIT_GONE = -23017;
-const int LL_ERR_TCP_TIMEOUT = -23016;
-
-// 0 - flags
-// [1,4] - packetid
-// 5 - data offset (after message name)
-const U8 LL_PACKET_ID_SIZE = 6;
-
-const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100;
-const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200;
-const F32 LL_COLLECT_ACK_TIME_MAX = 2.f;
-
-//
-// Prototypes and Predefines
-//
-class LLMessageSystem;
-class LLEncodedDatagramService;
-class LLSD;
-
-//
-// Classes
-//
-
-
-class LLCircuitData
-{
-public:
- LLCircuitData(const LLHost &host, TPACKETID in_id,
- const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
- ~LLCircuitData();
-
- S32 resendUnackedPackets(const F64Seconds now);
- void clearDuplicateList(TPACKETID oldest_id);
-
-
- void dumpResendCountAndReset(); // Used for tracking how many resends are being done on a circuit.
-
-
-
- // Public because stupid message system callbacks uses it.
- void pingTimerStart();
- void pingTimerStop(const U8 ping_id);
- void ackReliablePacket(TPACKETID packet_num);
-
- // remote computer information
- const LLUUID& getRemoteID() const { return mRemoteID; }
- const LLUUID& getRemoteSessionID() const { return mRemoteSessionID; }
- void setRemoteID(const LLUUID& id) { mRemoteID = id; }
- void setRemoteSessionID(const LLUUID& id) { mRemoteSessionID = id; }
-
- void setTrusted(bool t);
-
- // The local end point ID is used when establishing a trusted circuit.
- // no matching set function for getLocalEndPointID()
- // mLocalEndPointID should only ever be setup in the LLCircuitData constructor
- const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; }
-
- U32Milliseconds getPingDelay() const;
- S32 getPingsInTransit() const { return mPingsInTransit; }
-
- // ACCESSORS
- bool isAlive() const;
- bool isBlocked() const;
- bool getAllowTimeout() const;
- F32Milliseconds getPingDelayAveraged();
- F32Milliseconds getPingInTransitTime();
- U32 getPacketsIn() const;
- S32Bytes getBytesIn() const;
- S32Bytes getBytesOut() const;
- U32 getPacketsOut() const;
- U32 getPacketsLost() const;
- TPACKETID getPacketOutID() const;
- bool getTrusted() const;
- F32 getAgeInSeconds() const;
- S32 getUnackedPacketCount() const { return mUnackedPacketCount; }
- S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; }
- F64Seconds getNextPingSendTime() const { return mNextPingSendTime; }
- U32 getLastPacketGap() const { return mLastPacketGap; }
- LLHost getHost() const { return mHost; }
- F64Seconds getLastPacketInTime() const { return mLastPacketInTime; }
-
- LLThrottleGroup &getThrottleGroup() { return mThrottles; }
-
- class less
- {
- public:
- bool operator()(const LLCircuitData* lhs, const LLCircuitData* rhs) const
- {
- if (lhs->getNextPingSendTime() < rhs->getNextPingSendTime())
- {
- return true;
- }
- else if (lhs->getNextPingSendTime() > rhs->getNextPingSendTime())
- {
- return false;
- }
- else return lhs > rhs;
- }
- };
-
- //
- // Debugging stuff (not necessary for operation)
- //
- void checkPeriodTime(); // Reset per-period counters if necessary.
- friend std::ostream& operator<<(std::ostream& s, LLCircuitData &circuit);
- void getInfo(LLSD& info) const;
-
- friend class LLCircuit;
- friend class LLMessageSystem;
- friend class LLEncodedDatagramService;
- friend void crash_on_spaceserver_timeout (const LLHost &host, void *); // HACK, so it has access to setAlive() so it can send a final shutdown message.
-protected:
- TPACKETID nextPacketOutID();
- void setPacketInID(TPACKETID id);
- void checkPacketInID(TPACKETID id, bool receive_resent);
- void setPingDelay(U32Milliseconds ping);
- bool checkCircuitTimeout(); // Return false if the circuit is dead and should be cleaned up
-
- void addBytesIn(S32Bytes bytes);
- void addBytesOut(S32Bytes bytes);
-
- U8 nextPingID() { mLastPingID++; return mLastPingID; }
-
- bool updateWatchDogTimers(LLMessageSystem *msgsys); // Return false if the circuit is dead and should be cleaned up
-
- void addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params);
- bool isDuplicateResend(TPACKETID packetnum);
- // Call this method when a reliable message comes in - this will
- // correctly place the packet in the correct list to be acked
- // later. RAack = requested ack
- bool collectRAck(TPACKETID packet_num);
-
-
- void setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
-
-
-
- void setAlive(bool b_alive);
- void setAllowTimeout(bool allow);
-
-protected:
- // Identification for this circuit.
- LLHost mHost;
- LLUUID mRemoteID;
- LLUUID mRemoteSessionID;
-
- LLThrottleGroup mThrottles;
-
- TPACKETID mWrapID;
-
- // Current packet IDs of incoming/outgoing packets
- // Used for packet sequencing/packet loss detection.
- TPACKETID mPacketsOutID;
- TPACKETID mPacketsInID;
- TPACKETID mHighestPacketID;
-
-
- // Callback and data to run in the case of a circuit timeout.
- // Used primarily to try and reconnect to servers if they crash/die.
- void (*mTimeoutCallback)(const LLHost &host, void *user_data);
- void *mTimeoutUserData;
-
- bool mTrusted; // Is this circuit trusted?
- bool mbAllowTimeout; // Machines can "pause" circuits, forcing them not to be dropped
-
- bool mbAlive; // Indicates whether a circuit is "alive", i.e. responded to pings
-
- bool mBlocked; // Blocked is true if the circuit is hosed, i.e. far behind on pings
-
- // Not sure what the difference between this and mLastPingSendTime is
- F64Seconds mPingTime; // Time at which a ping was sent.
-
- F64Seconds mLastPingSendTime; // Time we last sent a ping
- F64Seconds mLastPingReceivedTime; // Time we last received a ping
- F64Seconds mNextPingSendTime; // Time to try and send the next ping
- S32 mPingsInTransit; // Number of pings in transit
- U8 mLastPingID; // ID of the last ping that we sent out
-
-
- // Used for determining the resend time for reliable resends.
- U32Milliseconds mPingDelay; // raw ping delay
- F32Milliseconds mPingDelayAveraged; // averaged ping delay (fast attack/slow decay)
-
- typedef std::map<TPACKETID, U64Microseconds> packet_time_map;
-
- packet_time_map mPotentialLostPackets;
- packet_time_map mRecentlyReceivedReliablePackets;
- std::vector<TPACKETID> mAcks;
- F32 mAckCreationTime; // first ack creation time
-
- typedef std::map<TPACKETID, LLReliablePacket *> reliable_map;
- typedef reliable_map::iterator reliable_iter;
-
- reliable_map mUnackedPackets;
- reliable_map mFinalRetryPackets;
-
- S32 mUnackedPacketCount;
- S32 mUnackedPacketBytes;
-
- F64Seconds mLastPacketInTime; // Time of last packet arrival
-
- LLUUID mLocalEndPointID;
-
- //
- // These variables are being used for statistical and debugging purpose ONLY,
- // as far as I can tell.
- //
-
- U32 mPacketsOut;
- U32 mPacketsIn;
- S32 mPacketsLost;
- S32Bytes mBytesIn,
- mBytesOut;
-
- F32Seconds mLastPeriodLength;
- S32Bytes mBytesInLastPeriod;
- S32Bytes mBytesOutLastPeriod;
- S32Bytes mBytesInThisPeriod;
- S32Bytes mBytesOutThisPeriod;
- F32 mPeakBPSIn; // bits per second, max of all period bps
- F32 mPeakBPSOut; // bits per second, max of all period bps
- F64Seconds mPeriodTime;
- LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers
-
- S32 mCurrentResendCount; // Number of resent packets since last spam
- U32 mLastPacketGap; // Gap in sequence number of last packet.
-
- const F32Seconds mHeartbeatInterval;
- const F32Seconds mHeartbeatTimeout;
-};
-
-
-// Actually a singleton class -- the global messagesystem
-// has a single LLCircuit member.
-class LLCircuit
-{
-public:
- // CREATORS
- LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
- ~LLCircuit();
-
- // ACCESSORS
- LLCircuitData* findCircuit(const LLHost& host) const;
- bool isCircuitAlive(const LLHost& host) const;
-
- // MANIPULATORS
- LLCircuitData *addCircuitData(const LLHost &host, TPACKETID in_id);
- void removeCircuitData(const LLHost &host);
-
- void updateWatchDogTimers(LLMessageSystem *msgsys);
- void resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size);
-
- // this method is called during the message system processAcks()
- // to send out any acks that did not get sent already.
- void sendAcks(F32 collect_time);
-
- friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit);
- void getInfo(LLSD& info) const;
-
- void dumpResends();
-
- typedef std::map<LLHost, LLCircuitData*> circuit_data_map;
-
- /**
- * @brief This method gets an iterator range starting after key in
- * the circuit data map.
- *
- * @param key The the host before first.
- * @param first[out] The first matching value after key. This
- * value will equal end if there are no entries.
- * @param end[out] The end of the iteration sequence.
- */
- void getCircuitRange(
- const LLHost& key,
- circuit_data_map::iterator& first,
- circuit_data_map::iterator& end);
-
- // Lists that optimize how many circuits we need to traverse a frame
- // HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up.
- circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data
- circuit_data_map mSendAckMap; // Map of circuits which need to send acks
-protected:
- circuit_data_map mCircuitData;
-
- typedef std::set<LLCircuitData *, LLCircuitData::less> ping_set_t; // Circuits sorted by next ping time
-
- ping_set_t mPingSet;
-
- // This variable points to the last circuit data we found to
- // optimize the many, many times we call findCircuit. This may be
- // set in otherwise const methods, so it is declared mutable.
- mutable LLCircuitData* mLastCircuit;
-
-private:
- const F32Seconds mHeartbeatInterval;
- const F32Seconds mHeartbeatTimeout;
-};
-#endif
+/**
+ * @file llcircuit.h
+ * @brief Provides a method for tracking network circuit information
+ * for the UDP message system
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCIRCUIT_H
+#define LL_LLCIRCUIT_H
+
+#include <map>
+#include <vector>
+
+#include "llerror.h"
+
+#include "lltimer.h"
+#include "net.h"
+#include "llhost.h"
+#include "llpacketack.h"
+#include "lluuid.h"
+#include "llthrottle.h"
+
+//
+// Constants
+//
+const F32 LL_AVERAGED_PING_ALPHA = 0.2f; // relaxation constant on ping running average
+const F32Milliseconds LL_AVERAGED_PING_MAX(2000);
+const F32Milliseconds LL_AVERAGED_PING_MIN(100); // increased to avoid retransmits when a process is slow
+
+const U32Milliseconds INITIAL_PING_VALUE_MSEC(1000); // initial value for the ping delay, or for ping delay for an unknown circuit
+
+const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000;
+const int LL_ERR_CIRCUIT_GONE = -23017;
+const int LL_ERR_TCP_TIMEOUT = -23016;
+
+// 0 - flags
+// [1,4] - packetid
+// 5 - data offset (after message name)
+const U8 LL_PACKET_ID_SIZE = 6;
+
+const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100;
+const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200;
+const F32 LL_COLLECT_ACK_TIME_MAX = 2.f;
+
+//
+// Prototypes and Predefines
+//
+class LLMessageSystem;
+class LLEncodedDatagramService;
+class LLSD;
+
+//
+// Classes
+//
+
+
+class LLCircuitData
+{
+public:
+ LLCircuitData(const LLHost &host, TPACKETID in_id,
+ const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
+ ~LLCircuitData();
+
+ S32 resendUnackedPackets(const F64Seconds now);
+ void clearDuplicateList(TPACKETID oldest_id);
+
+
+ void dumpResendCountAndReset(); // Used for tracking how many resends are being done on a circuit.
+
+
+
+ // Public because stupid message system callbacks uses it.
+ void pingTimerStart();
+ void pingTimerStop(const U8 ping_id);
+ void ackReliablePacket(TPACKETID packet_num);
+
+ // remote computer information
+ const LLUUID& getRemoteID() const { return mRemoteID; }
+ const LLUUID& getRemoteSessionID() const { return mRemoteSessionID; }
+ void setRemoteID(const LLUUID& id) { mRemoteID = id; }
+ void setRemoteSessionID(const LLUUID& id) { mRemoteSessionID = id; }
+
+ void setTrusted(bool t);
+
+ // The local end point ID is used when establishing a trusted circuit.
+ // no matching set function for getLocalEndPointID()
+ // mLocalEndPointID should only ever be setup in the LLCircuitData constructor
+ const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; }
+
+ U32Milliseconds getPingDelay() const;
+ S32 getPingsInTransit() const { return mPingsInTransit; }
+
+ // ACCESSORS
+ bool isAlive() const;
+ bool isBlocked() const;
+ bool getAllowTimeout() const;
+ F32Milliseconds getPingDelayAveraged();
+ F32Milliseconds getPingInTransitTime();
+ U32 getPacketsIn() const;
+ S32Bytes getBytesIn() const;
+ S32Bytes getBytesOut() const;
+ U32 getPacketsOut() const;
+ U32 getPacketsLost() const;
+ TPACKETID getPacketOutID() const;
+ bool getTrusted() const;
+ F32 getAgeInSeconds() const;
+ S32 getUnackedPacketCount() const { return mUnackedPacketCount; }
+ S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; }
+ F64Seconds getNextPingSendTime() const { return mNextPingSendTime; }
+ U32 getLastPacketGap() const { return mLastPacketGap; }
+ LLHost getHost() const { return mHost; }
+ F64Seconds getLastPacketInTime() const { return mLastPacketInTime; }
+
+ LLThrottleGroup &getThrottleGroup() { return mThrottles; }
+
+ class less
+ {
+ public:
+ bool operator()(const LLCircuitData* lhs, const LLCircuitData* rhs) const
+ {
+ if (lhs->getNextPingSendTime() < rhs->getNextPingSendTime())
+ {
+ return true;
+ }
+ else if (lhs->getNextPingSendTime() > rhs->getNextPingSendTime())
+ {
+ return false;
+ }
+ else return lhs > rhs;
+ }
+ };
+
+ //
+ // Debugging stuff (not necessary for operation)
+ //
+ void checkPeriodTime(); // Reset per-period counters if necessary.
+ friend std::ostream& operator<<(std::ostream& s, LLCircuitData &circuit);
+ void getInfo(LLSD& info) const;
+
+ friend class LLCircuit;
+ friend class LLMessageSystem;
+ friend class LLEncodedDatagramService;
+ friend void crash_on_spaceserver_timeout (const LLHost &host, void *); // HACK, so it has access to setAlive() so it can send a final shutdown message.
+protected:
+ TPACKETID nextPacketOutID();
+ void setPacketInID(TPACKETID id);
+ void checkPacketInID(TPACKETID id, bool receive_resent);
+ void setPingDelay(U32Milliseconds ping);
+ bool checkCircuitTimeout(); // Return false if the circuit is dead and should be cleaned up
+
+ void addBytesIn(S32Bytes bytes);
+ void addBytesOut(S32Bytes bytes);
+
+ U8 nextPingID() { mLastPingID++; return mLastPingID; }
+
+ bool updateWatchDogTimers(LLMessageSystem *msgsys); // Return false if the circuit is dead and should be cleaned up
+
+ void addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLReliablePacketParams *params);
+ bool isDuplicateResend(TPACKETID packetnum);
+ // Call this method when a reliable message comes in - this will
+ // correctly place the packet in the correct list to be acked
+ // later. RAack = requested ack
+ bool collectRAck(TPACKETID packet_num);
+
+
+ void setTimeoutCallback(void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
+
+
+
+ void setAlive(bool b_alive);
+ void setAllowTimeout(bool allow);
+
+protected:
+ // Identification for this circuit.
+ LLHost mHost;
+ LLUUID mRemoteID;
+ LLUUID mRemoteSessionID;
+
+ LLThrottleGroup mThrottles;
+
+ TPACKETID mWrapID;
+
+ // Current packet IDs of incoming/outgoing packets
+ // Used for packet sequencing/packet loss detection.
+ TPACKETID mPacketsOutID;
+ TPACKETID mPacketsInID;
+ TPACKETID mHighestPacketID;
+
+
+ // Callback and data to run in the case of a circuit timeout.
+ // Used primarily to try and reconnect to servers if they crash/die.
+ void (*mTimeoutCallback)(const LLHost &host, void *user_data);
+ void *mTimeoutUserData;
+
+ bool mTrusted; // Is this circuit trusted?
+ bool mbAllowTimeout; // Machines can "pause" circuits, forcing them not to be dropped
+
+ bool mbAlive; // Indicates whether a circuit is "alive", i.e. responded to pings
+
+ bool mBlocked; // Blocked is true if the circuit is hosed, i.e. far behind on pings
+
+ // Not sure what the difference between this and mLastPingSendTime is
+ F64Seconds mPingTime; // Time at which a ping was sent.
+
+ F64Seconds mLastPingSendTime; // Time we last sent a ping
+ F64Seconds mLastPingReceivedTime; // Time we last received a ping
+ F64Seconds mNextPingSendTime; // Time to try and send the next ping
+ S32 mPingsInTransit; // Number of pings in transit
+ U8 mLastPingID; // ID of the last ping that we sent out
+
+
+ // Used for determining the resend time for reliable resends.
+ U32Milliseconds mPingDelay; // raw ping delay
+ F32Milliseconds mPingDelayAveraged; // averaged ping delay (fast attack/slow decay)
+
+ typedef std::map<TPACKETID, U64Microseconds> packet_time_map;
+
+ packet_time_map mPotentialLostPackets;
+ packet_time_map mRecentlyReceivedReliablePackets;
+ std::vector<TPACKETID> mAcks;
+ F32 mAckCreationTime; // first ack creation time
+
+ typedef std::map<TPACKETID, LLReliablePacket *> reliable_map;
+ typedef reliable_map::iterator reliable_iter;
+
+ reliable_map mUnackedPackets;
+ reliable_map mFinalRetryPackets;
+
+ S32 mUnackedPacketCount;
+ S32 mUnackedPacketBytes;
+
+ F64Seconds mLastPacketInTime; // Time of last packet arrival
+
+ LLUUID mLocalEndPointID;
+
+ //
+ // These variables are being used for statistical and debugging purpose ONLY,
+ // as far as I can tell.
+ //
+
+ U32 mPacketsOut;
+ U32 mPacketsIn;
+ S32 mPacketsLost;
+ S32Bytes mBytesIn,
+ mBytesOut;
+
+ F32Seconds mLastPeriodLength;
+ S32Bytes mBytesInLastPeriod;
+ S32Bytes mBytesOutLastPeriod;
+ S32Bytes mBytesInThisPeriod;
+ S32Bytes mBytesOutThisPeriod;
+ F32 mPeakBPSIn; // bits per second, max of all period bps
+ F32 mPeakBPSOut; // bits per second, max of all period bps
+ F64Seconds mPeriodTime;
+ LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers
+
+ S32 mCurrentResendCount; // Number of resent packets since last spam
+ U32 mLastPacketGap; // Gap in sequence number of last packet.
+
+ const F32Seconds mHeartbeatInterval;
+ const F32Seconds mHeartbeatTimeout;
+};
+
+
+// Actually a singleton class -- the global messagesystem
+// has a single LLCircuit member.
+class LLCircuit
+{
+public:
+ // CREATORS
+ LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
+ ~LLCircuit();
+
+ // ACCESSORS
+ LLCircuitData* findCircuit(const LLHost& host) const;
+ bool isCircuitAlive(const LLHost& host) const;
+
+ // MANIPULATORS
+ LLCircuitData *addCircuitData(const LLHost &host, TPACKETID in_id);
+ void removeCircuitData(const LLHost &host);
+
+ void updateWatchDogTimers(LLMessageSystem *msgsys);
+ void resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size);
+
+ // this method is called during the message system processAcks()
+ // to send out any acks that did not get sent already.
+ void sendAcks(F32 collect_time);
+
+ friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit);
+ void getInfo(LLSD& info) const;
+
+ void dumpResends();
+
+ typedef std::map<LLHost, LLCircuitData*> circuit_data_map;
+
+ /**
+ * @brief This method gets an iterator range starting after key in
+ * the circuit data map.
+ *
+ * @param key The the host before first.
+ * @param first[out] The first matching value after key. This
+ * value will equal end if there are no entries.
+ * @param end[out] The end of the iteration sequence.
+ */
+ void getCircuitRange(
+ const LLHost& key,
+ circuit_data_map::iterator& first,
+ circuit_data_map::iterator& end);
+
+ // Lists that optimize how many circuits we need to traverse a frame
+ // HACK - this should become protected eventually, but stupid !@$@# message system/circuit classes are jumbling things up.
+ circuit_data_map mUnackedCircuitMap; // Map of circuits with unacked data
+ circuit_data_map mSendAckMap; // Map of circuits which need to send acks
+protected:
+ circuit_data_map mCircuitData;
+
+ typedef std::set<LLCircuitData *, LLCircuitData::less> ping_set_t; // Circuits sorted by next ping time
+
+ ping_set_t mPingSet;
+
+ // This variable points to the last circuit data we found to
+ // optimize the many, many times we call findCircuit. This may be
+ // set in otherwise const methods, so it is declared mutable.
+ mutable LLCircuitData* mLastCircuit;
+
+private:
+ const F32Seconds mHeartbeatInterval;
+ const F32Seconds mHeartbeatTimeout;
+};
+#endif
diff --git a/indra/llmessage/llclassifiedflags.cpp b/indra/llmessage/llclassifiedflags.cpp
index bf8c9171a7..345942955c 100644
--- a/indra/llmessage/llclassifiedflags.cpp
+++ b/indra/llmessage/llclassifiedflags.cpp
@@ -1,84 +1,84 @@
-/**
- * @file llclassifiedflags.cpp
- * @brief
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-//*****************************************************************************
-// llclassifiedflags.cpp
-//
-// Some exported symbols and functions for dealing with classified flags.
-//
-// Copyright 2005, Linden Research, Inc
-//*****************************************************************************
-
-#include "linden_common.h"
-
-#include "llclassifiedflags.h"
-
-ClassifiedFlags pack_classified_flags_request(bool auto_renew, bool inc_pg, bool inc_mature, bool inc_adult)
-{
- U8 rv = 0;
- if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
- if(inc_mature) rv |= CLASSIFIED_QUERY_INC_MATURE;
- if (inc_pg && !inc_mature) rv |= CLASSIFIED_FLAG_MATURE;
- if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
- if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
- return rv;
-}
-
-ClassifiedFlags pack_classified_flags(bool auto_renew, bool inc_pg, bool inc_mature, bool inc_adult)
-{
- U8 rv = 0;
- if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
- if(inc_mature)
- {
- rv |= CLASSIFIED_QUERY_INC_MATURE;
- rv |= CLASSIFIED_FLAG_MATURE;
- }
- if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
- if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
- return rv;
-}
-
-bool is_cf_mature(ClassifiedFlags flags)
-{
- return ((flags & CLASSIFIED_FLAG_MATURE) != 0) || ((flags & CLASSIFIED_QUERY_INC_MATURE) != 0);
-}
-
-// Deprecated, but leaving commented out because someday we might
-// want to let users enable/disable classifieds. JC
-//bool is_cf_enabled(ClassifiedFlags flags)
-//{
-// return ((flags & CLASSIFIED_FLAG_ENABLED) == CLASSIFIED_FLAG_ENABLED);
-//}
-
-bool is_cf_update_time(ClassifiedFlags flags)
-{
- return ((flags & CLASSIFIED_FLAG_UPDATE_TIME) != 0);
-}
-
-bool is_cf_auto_renew(ClassifiedFlags flags)
-{
- return ((flags & CLASSIFIED_FLAG_AUTO_RENEW) != 0);
-}
+/**
+ * @file llclassifiedflags.cpp
+ * @brief
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+//*****************************************************************************
+// llclassifiedflags.cpp
+//
+// Some exported symbols and functions for dealing with classified flags.
+//
+// Copyright 2005, Linden Research, Inc
+//*****************************************************************************
+
+#include "linden_common.h"
+
+#include "llclassifiedflags.h"
+
+ClassifiedFlags pack_classified_flags_request(bool auto_renew, bool inc_pg, bool inc_mature, bool inc_adult)
+{
+ U8 rv = 0;
+ if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
+ if(inc_mature) rv |= CLASSIFIED_QUERY_INC_MATURE;
+ if (inc_pg && !inc_mature) rv |= CLASSIFIED_FLAG_MATURE;
+ if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
+ if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
+ return rv;
+}
+
+ClassifiedFlags pack_classified_flags(bool auto_renew, bool inc_pg, bool inc_mature, bool inc_adult)
+{
+ U8 rv = 0;
+ if(inc_pg) rv |= CLASSIFIED_QUERY_INC_PG;
+ if(inc_mature)
+ {
+ rv |= CLASSIFIED_QUERY_INC_MATURE;
+ rv |= CLASSIFIED_FLAG_MATURE;
+ }
+ if(inc_adult) rv |= CLASSIFIED_QUERY_INC_ADULT;
+ if(auto_renew) rv |= CLASSIFIED_FLAG_AUTO_RENEW;
+ return rv;
+}
+
+bool is_cf_mature(ClassifiedFlags flags)
+{
+ return ((flags & CLASSIFIED_FLAG_MATURE) != 0) || ((flags & CLASSIFIED_QUERY_INC_MATURE) != 0);
+}
+
+// Deprecated, but leaving commented out because someday we might
+// want to let users enable/disable classifieds. JC
+//bool is_cf_enabled(ClassifiedFlags flags)
+//{
+// return ((flags & CLASSIFIED_FLAG_ENABLED) == CLASSIFIED_FLAG_ENABLED);
+//}
+
+bool is_cf_update_time(ClassifiedFlags flags)
+{
+ return ((flags & CLASSIFIED_FLAG_UPDATE_TIME) != 0);
+}
+
+bool is_cf_auto_renew(ClassifiedFlags flags)
+{
+ return ((flags & CLASSIFIED_FLAG_AUTO_RENEW) != 0);
+}
diff --git a/indra/llmessage/llclassifiedflags.h b/indra/llmessage/llclassifiedflags.h
index 9298b90357..126b23340f 100644
--- a/indra/llmessage/llclassifiedflags.h
+++ b/indra/llmessage/llclassifiedflags.h
@@ -1,62 +1,62 @@
-/**
- * @file llclassifiedflags.h
- * @brief Flags used in the classifieds.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCLASSIFIEDFLAGS_H
-#define LL_LLCLASSIFIEDFLAGS_H
-
-typedef U8 ClassifiedFlags;
-
-const U8 CLASSIFIED_FLAG_NONE = 1 << 0;
-const U8 CLASSIFIED_FLAG_MATURE = 1 << 1;
-//const U8 CLASSIFIED_FLAG_ENABLED = 1 << 2; // see llclassifiedflags.cpp
-//const U8 CLASSIFIED_FLAG_HAS_PRICE= 1 << 3; // deprecated
-const U8 CLASSIFIED_FLAG_UPDATE_TIME= 1 << 4;
-const U8 CLASSIFIED_FLAG_AUTO_RENEW = 1 << 5;
-
-const U8 CLASSIFIED_QUERY_FILTER_MATURE = 1 << 1;
-//const U8 CLASSIFIED_QUERY_FILTER_ENABLED = 1 << 2;
-//const U8 CLASSIFIED_QUERY_FILTER_PRICE = 1 << 3;
-
-// These are new with Adult-enabled viewers (1.23 and later)
-const U8 CLASSIFIED_QUERY_INC_PG = 1 << 2;
-const U8 CLASSIFIED_QUERY_INC_MATURE = 1 << 3;
-const U8 CLASSIFIED_QUERY_INC_ADULT = 1 << 6;
-const U8 CLASSIFIED_QUERY_INC_NEW_VIEWER = (CLASSIFIED_QUERY_INC_PG | CLASSIFIED_QUERY_INC_MATURE | CLASSIFIED_QUERY_INC_ADULT);
-
-const S32 MAX_CLASSIFIEDS = 100;
-
-// This function is used in AO viewers to pack old query flags into the request
-// so that they can talk to old dataservers properly. When the AO servers are deployed on agni
-// we can revert back to ClassifiedFlags pack_classified_flags and get rider of this one.
-ClassifiedFlags pack_classified_flags_request(bool auto_renew, bool is_pg, bool is_mature, bool is_adult);
-
-ClassifiedFlags pack_classified_flags(bool auto_renew, bool is_pg, bool is_mature, bool is_adult);
-bool is_cf_mature(ClassifiedFlags flags);
-//bool is_cf_enabled(ClassifiedFlags flags);
-bool is_cf_update_time(ClassifiedFlags flags);
-bool is_cf_auto_renew(ClassifiedFlags flags);
-
-#endif
+/**
+ * @file llclassifiedflags.h
+ * @brief Flags used in the classifieds.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCLASSIFIEDFLAGS_H
+#define LL_LLCLASSIFIEDFLAGS_H
+
+typedef U8 ClassifiedFlags;
+
+const U8 CLASSIFIED_FLAG_NONE = 1 << 0;
+const U8 CLASSIFIED_FLAG_MATURE = 1 << 1;
+//const U8 CLASSIFIED_FLAG_ENABLED = 1 << 2; // see llclassifiedflags.cpp
+//const U8 CLASSIFIED_FLAG_HAS_PRICE= 1 << 3; // deprecated
+const U8 CLASSIFIED_FLAG_UPDATE_TIME= 1 << 4;
+const U8 CLASSIFIED_FLAG_AUTO_RENEW = 1 << 5;
+
+const U8 CLASSIFIED_QUERY_FILTER_MATURE = 1 << 1;
+//const U8 CLASSIFIED_QUERY_FILTER_ENABLED = 1 << 2;
+//const U8 CLASSIFIED_QUERY_FILTER_PRICE = 1 << 3;
+
+// These are new with Adult-enabled viewers (1.23 and later)
+const U8 CLASSIFIED_QUERY_INC_PG = 1 << 2;
+const U8 CLASSIFIED_QUERY_INC_MATURE = 1 << 3;
+const U8 CLASSIFIED_QUERY_INC_ADULT = 1 << 6;
+const U8 CLASSIFIED_QUERY_INC_NEW_VIEWER = (CLASSIFIED_QUERY_INC_PG | CLASSIFIED_QUERY_INC_MATURE | CLASSIFIED_QUERY_INC_ADULT);
+
+const S32 MAX_CLASSIFIEDS = 100;
+
+// This function is used in AO viewers to pack old query flags into the request
+// so that they can talk to old dataservers properly. When the AO servers are deployed on agni
+// we can revert back to ClassifiedFlags pack_classified_flags and get rider of this one.
+ClassifiedFlags pack_classified_flags_request(bool auto_renew, bool is_pg, bool is_mature, bool is_adult);
+
+ClassifiedFlags pack_classified_flags(bool auto_renew, bool is_pg, bool is_mature, bool is_adult);
+bool is_cf_mature(ClassifiedFlags flags);
+//bool is_cf_enabled(ClassifiedFlags flags);
+bool is_cf_update_time(ClassifiedFlags flags);
+bool is_cf_auto_renew(ClassifiedFlags flags);
+
+#endif
diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp
index c0a5e361b1..959cfb2762 100644
--- a/indra/llmessage/llcoproceduremanager.cpp
+++ b/indra/llmessage/llcoproceduremanager.cpp
@@ -41,7 +41,7 @@
//=========================================================================
// Map of pool sizes for known pools
static const std::map<std::string, U32> DefaultPoolSizes{
- {std::string("Upload"), 1},
+ {std::string("Upload"), 1},
{std::string("AIS"), 1},
// *TODO: Rider for the moment keep AIS calls serialized otherwise the COF will tend to get out of sync.
};
@@ -61,11 +61,11 @@ public:
LLCoprocedurePool(const std::string &name, size_t size);
~LLCoprocedurePool();
- /// Places the coprocedure on the queue for processing.
- ///
+ /// Places the coprocedure on the queue for processing.
+ ///
/// @param name Is used for debugging and should identify this coroutine.
- /// @param proc Is a bound function to be executed
- ///
+ /// @param proc Is a bound function to be executed
+ ///
/// @return This method returns a UUID that can be used later to cancel execution.
LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc);
@@ -91,7 +91,7 @@ public:
}
void close();
-
+
private:
struct QueuedCoproc
{
@@ -108,7 +108,7 @@ private:
CoProcedure_t mProc;
};
- // we use a buffered_channel here rather than unbuffered_channel since we want to be able to
+ // we use a buffered_channel here rather than unbuffered_channel since we want to be able to
// push values without blocking,even if there's currently no one calling a pop operation (due to
// fiber running right now)
typedef boost::fibers::buffered_channel<QueuedCoproc::ptr_t> CoprocQueue_t;
@@ -167,7 +167,7 @@ void LLCoprocedureManager::initializePool(const std::string &poolName)
if (size == 0)
{
- // if not found grab the know default... if there is no known
+ // if not found grab the know default... if there is no known
// default use a reasonable number like 5.
auto it = DefaultPoolSizes.find(poolName);
size = (it != DefaultPoolSizes.end()) ? it->second : DEFAULT_POOL_SIZE;
@@ -190,7 +190,7 @@ void LLCoprocedureManager::initializePool(const std::string &poolName)
//-------------------------------------------------------------------------
LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc)
{
- // Attempt to find the pool and enqueue the procedure. If the pool does
+ // Attempt to find the pool and enqueue the procedure. If the pool does
// not exist, create it.
poolMap_t::iterator it = mPoolMap.find(pool);
@@ -355,7 +355,7 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size):
LL_INFOS("CoProcMgr") << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items, queue max " << LLCoprocedureManager::DEFAULT_QUEUE_SIZE << LL_ENDL;
}
-LLCoprocedurePool::~LLCoprocedurePool()
+LLCoprocedurePool::~LLCoprocedurePool()
{
}
diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h
index c5bc37dd0e..6c6e506654 100644
--- a/indra/llmessage/llcoproceduremanager.h
+++ b/indra/llmessage/llcoproceduremanager.h
@@ -46,15 +46,15 @@ public:
typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t;
- /// Places the coprocedure on the queue for processing.
- ///
+ /// Places the coprocedure on the queue for processing.
+ ///
/// @param name Is used for debugging and should identify this coroutine.
- /// @param proc Is a bound function to be executed
- ///
+ /// @param proc Is a bound function to be executed
+ ///
/// @return This method returns a UUID that can be used later to cancel execution.
LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc);
- /// Cancel a coprocedure. If the coprocedure is already being actively executed
+ /// Cancel a coprocedure. If the coprocedure is already being actively executed
/// this method calls cancelYieldingOperation() on the associated HttpAdapter
/// If it has not yet been dequeued it is simply removed from the queue.
//void cancelCoprocedure(const LLUUID &id);
@@ -80,7 +80,7 @@ public:
void close(const std::string &pool);
void initializePool(const std::string &poolName);
-
+
private:
typedef std::shared_ptr<LLCoprocedurePool> poolPtr_t;
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index fc561c6b0f..45b673b9d5 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llcorehttputil.h
* @date 2014-08-25
* @brief Adapter and utility classes expanding the llcorehttp interfaces.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2014&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2014, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -75,20 +75,20 @@ extern const F32 HTTP_REQUEST_EXPIRY_SECS;
/// the output LLSD object, out_llsd, is written with the
/// result and true is returned.
///
-/// @arg response Response object as returned in
-/// in an HttpHandler onCompleted() callback.
-/// @arg log If true, LLSD parser will emit errors
-/// as LL_INFOS-level messages as it parses.
-/// Otherwise, it *should* be a quiet parse.
-/// @arg out_llsd Output LLSD object written only upon
-/// successful parse of the response object.
+/// @arg response Response object as returned in
+/// in an HttpHandler onCompleted() callback.
+/// @arg log If true, LLSD parser will emit errors
+/// as LL_INFOS-level messages as it parses.
+/// Otherwise, it *should* be a quiet parse.
+/// @arg out_llsd Output LLSD object written only upon
+/// successful parse of the response object.
///
-/// @return Returns true (and writes to out_llsd) if
-/// parse was successful. False otherwise.
+/// @return Returns true (and writes to out_llsd) if
+/// parse was successful. False otherwise.
///
bool responseToLLSD(LLCore::HttpResponse * response,
- bool log,
- LLSD & out_llsd);
+ bool log,
+ LLSD & out_llsd);
/// Create a std::string representation of a response object
/// suitable for logging. Mainly intended for logging of
@@ -104,15 +104,15 @@ std::string responseToString(LLCore::HttpResponse * response);
/// One will not be provided by this call. You might look after
/// the 'Accept:' header as well.
///
-/// @return If request is successfully issued, the
-/// HttpHandle representing the request.
-/// On error, LLCORE_HTTP_HANDLE_INVALID
-/// is returned and caller can fetch detailed
-/// status with the getStatus() method on the
-/// request object. In case of error, no
-/// request is queued and caller may need to
-/// perform additional cleanup such as freeing
-/// a now-useless HttpHandler object.
+/// @return If request is successfully issued, the
+/// HttpHandle representing the request.
+/// On error, LLCORE_HTTP_HANDLE_INVALID
+/// is returned and caller can fetch detailed
+/// status with the getStatus() method on the
+/// request object. In case of error, no
+/// request is queued and caller may need to
+/// perform additional cleanup such as freeing
+/// a now-useless HttpHandler object.
///
LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
@@ -123,11 +123,11 @@ LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest * request,
const LLCore::HttpHandler::ptr_t &handler);
inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & request,
- LLCore::HttpRequest::policy_t policy_id,
- const std::string & url,
- const LLSD & body,
- const LLCore::HttpOptions::ptr_t & options,
- const LLCore::HttpHeaders::ptr_t & headers,
+ LLCore::HttpRequest::policy_t policy_id,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t & options,
+ const LLCore::HttpHeaders::ptr_t & headers,
const LLCore::HttpHandler::ptr_t & handler)
{
return requestPostWithLLSD(request.get(), policy_id,
@@ -154,30 +154,30 @@ inline LLCore::HttpHandle requestPostWithLLSD(LLCore::HttpRequest::ptr_t & reque
/// an HttpHeaders object with a correct 'Content-Type:' header.
/// One will not be provided by this call.
///
-/// @return If request is successfully issued, the
-/// HttpHandle representing the request.
-/// On error, LLCORE_HTTP_HANDLE_INVALID
-/// is returned and caller can fetch detailed
-/// status with the getStatus() method on the
-/// request object. In case of error, no
-/// request is queued and caller may need to
-/// perform additional cleanup such as freeing
-/// a now-useless HttpHandler object.
+/// @return If request is successfully issued, the
+/// HttpHandle representing the request.
+/// On error, LLCORE_HTTP_HANDLE_INVALID
+/// is returned and caller can fetch detailed
+/// status with the getStatus() method on the
+/// request object. In case of error, no
+/// request is queued and caller may need to
+/// perform additional cleanup such as freeing
+/// a now-useless HttpHandler object.
///
LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest * request,
- LLCore::HttpRequest::policy_t policy_id,
- const std::string & url,
- const LLSD & body,
- const LLCore::HttpOptions::ptr_t &options,
- const LLCore::HttpHeaders::ptr_t &headers,
+ LLCore::HttpRequest::policy_t policy_id,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t &options,
+ const LLCore::HttpHeaders::ptr_t &headers,
const LLCore::HttpHandler::ptr_t &handler);
inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
- LLCore::HttpRequest::policy_t policy_id,
- const std::string & url,
- const LLSD & body,
- const LLCore::HttpOptions::ptr_t & options,
- const LLCore::HttpHeaders::ptr_t & headers,
+ LLCore::HttpRequest::policy_t policy_id,
+ const std::string & url,
+ const LLSD & body,
+ const LLCore::HttpOptions::ptr_t & options,
+ const LLCore::HttpHeaders::ptr_t & headers,
LLCore::HttpHandler::ptr_t handler)
{
return requestPutWithLLSD(request.get(), policy_id,
@@ -203,15 +203,15 @@ inline LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & reques
/// an HttpHeaders object with a correct 'Content-Type:' header.
/// One will not be provided by this call.
///
-/// @return If request is successfully issued, the
-/// HttpHandle representing the request.
-/// On error, LLCORE_HTTP_HANDLE_INVALID
-/// is returned and caller can fetch detailed
-/// status with the getStatus() method on the
-/// request object. In case of error, no
-/// request is queued and caller may need to
-/// perform additional cleanup such as freeing
-/// a now-useless HttpHandler object.
+/// @return If request is successfully issued, the
+/// HttpHandle representing the request.
+/// On error, LLCORE_HTTP_HANDLE_INVALID
+/// is returned and caller can fetch detailed
+/// status with the getStatus() method on the
+/// request object. In case of error, no
+/// request is queued and caller may need to
+/// perform additional cleanup such as freeing
+/// a now-useless HttpHandler object.
///
LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest * request,
LLCore::HttpRequest::policy_t policy_id,
@@ -247,10 +247,10 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ
}
//=========================================================================
-/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for
-/// interacting with coroutines. When the request is completed the response
+/// The HttpCoroHandler is a specialization of the LLCore::HttpHandler for
+/// interacting with coroutines. When the request is completed the response
/// will be posted onto the supplied Event Pump.
-///
+///
/// The LLSD posted back to the coroutine will have the following additions:
/// llsd["http_result"] -+- ["message"] - An error message returned from the HTTP status
/// +- ["status"] - The status code associated with the HTTP call
@@ -258,7 +258,7 @@ inline LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & requ
/// +- ["type"] - The LLCore::HttpStatus type associted with the HTTP call
/// +- ["url"] - The URL used to make the call.
/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
-///
+///
class HttpCoroHandler : public LLCore::HttpHandler
{
public:
@@ -289,21 +289,21 @@ private:
};
//=========================================================================
-/// An adapter to handle some of the boilerplate code surrounding HTTP and coroutine
+/// An adapter to handle some of the boilerplate code surrounding HTTP and coroutine
/// interaction.
-///
-/// Construct an HttpCoroutineAdapter giving it a name and policy Id. After
-/// any application specific setup call the post, put or get method. The request
+///
+/// Construct an HttpCoroutineAdapter giving it a name and policy Id. After
+/// any application specific setup call the post, put or get method. The request
/// will be automatically pumped and the method will return with an LLSD describing
-/// the result of the operation. See HttpCoroHandler for a description of the
+/// the result of the operation. See HttpCoroHandler for a description of the
/// decoration done to the returned LLSD.
-///
-/// Posting through the adapter will automatically add the following headers to
-/// the request if they have not been previously specified in a supplied
+///
+/// Posting through the adapter will automatically add the following headers to
+/// the request if they have not been previously specified in a supplied
/// HttpHeaders object:
/// "Accept=application/llsd+xml"
/// "X-SecondLife-UDP-Listen-Port=###"
-///
+///
class HttpCoroutineAdapter
{
public:
@@ -323,9 +323,9 @@ public:
HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId);
~HttpCoroutineAdapter();
- /// Execute a Post transaction on the supplied URL and yield execution of
- /// the coroutine until a result is available.
- ///
+ /// Execute a Post transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD postAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -407,9 +407,9 @@ public:
- /// Execute a Put transaction on the supplied URL and yield execution of
+ /// Execute a Put transaction on the supplied URL and yield execution of
/// the coroutine until a result is available.
- ///
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD putAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -437,12 +437,12 @@ public:
LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
}
- /// Execute a Get transaction on the supplied URL and yield execution of
+ /// Execute a Get transaction on the supplied URL and yield execution of
/// the coroutine until a result is available.
- ///
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
- ///
+ ///
LLSD getAndSuspend(LLCore::HttpRequest::ptr_t request,
const std::string & url,
LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()),
@@ -467,9 +467,9 @@ public:
headers);
}
- /// These methods have the same behavior as @getAndSuspend() however they are
- /// expecting the server to return the results formatted in a JSON string.
- /// On a successful GET call the JSON results will be converted into LLSD
+ /// These methods have the same behavior as @getAndSuspend() however they are
+ /// expecting the server to return the results formatted in a JSON string.
+ /// On a successful GET call the JSON results will be converted into LLSD
/// before being returned to the caller.
LLSD getJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
const std::string & url,
@@ -484,9 +484,9 @@ public:
}
- /// Execute a DELETE transaction on the supplied URL and yield execution of
+ /// Execute a DELETE transaction on the supplied URL and yield execution of
/// the coroutine until a result is available.
- ///
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD deleteAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -501,9 +501,9 @@ public:
headers);
}
- /// These methods have the same behavior as @deleteAndSuspend() however they are
- /// expecting the server to return any results formatted in a JSON string.
- /// On a successful DELETE call the JSON results will be converted into LLSD
+ /// These methods have the same behavior as @deleteAndSuspend() however they are
+ /// expecting the server to return any results formatted in a JSON string.
+ /// On a successful DELETE call the JSON results will be converted into LLSD
/// before being returned to the caller.
LLSD deleteJsonAndSuspend(LLCore::HttpRequest::ptr_t request,
const std::string & url,
@@ -518,9 +518,9 @@ public:
}
- /// Execute a PATCH transaction on the supplied URL and yield execution of
- /// the coroutine until a result is available.
- ///
+ /// Execute a PATCH transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD patchAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -535,12 +535,12 @@ public:
LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
}
- /// Execute a COPY transaction on the supplied URL and yield execution of
- /// the coroutine until a result is available.
- ///
+ /// Execute a COPY transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
/// @Note: The destination is passed through the HTTP pipe as a header
/// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
- ///
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD copyAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -555,12 +555,12 @@ public:
LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()), headers);
}
- /// Execute a MOVE transaction on the supplied URL and yield execution of
- /// the coroutine until a result is available.
- ///
+ /// Execute a MOVE transaction on the supplied URL and yield execution of
+ /// the coroutine until a result is available.
+ ///
/// @Note: The destination is passed through the HTTP pipe in the headers.
/// The header used is defined as: HTTP_OUT_HEADER_DESTINATION("Destination");
- ///
+ ///
/// @Note: the request's smart pointer is passed by value so that it will
/// not be deallocated during the yield.
LLSD moveAndSuspend(LLCore::HttpRequest::ptr_t request,
@@ -580,7 +580,7 @@ public:
static LLCore::HttpStatus getStatusFromLLSD(const LLSD &httpResults);
- /// The convenience routines below can be provided with callback functors
+ /// The convenience routines below can be provided with callback functors
/// which will be invoked in the case of success or failure. These callbacks
/// should match this form.
/// @sa callbackHttpGet
@@ -603,9 +603,9 @@ public:
/// Generic Get and post routines for HTTP via coroutines.
/// These static methods do all required setup for the GET or POST operation.
- /// When the operation completes successfully they will put the success message in the log at INFO level,
+ /// When the operation completes successfully they will put the success message in the log at INFO level,
/// If the operation fails the failure message is written to the log at WARN level.
- ///
+ ///
static void messageHttpGet(const std::string &url, const std::string &success = std::string(), const std::string &failure = std::string());
static void messageHttpPost(const std::string &url, const LLSD &postData, const std::string &success, const std::string &failure);
@@ -638,7 +638,7 @@ private:
HttpCoroHandler::ptr_t &handler);
LLSD getAndSuspend_(LLCore::HttpRequest::ptr_t &request,
- const std::string & url, LLCore::HttpOptions::ptr_t &options,
+ const std::string & url, LLCore::HttpOptions::ptr_t &options,
LLCore::HttpHeaders::ptr_t &headers, HttpCoroHandler::ptr_t &handler);
LLSD deleteAndSuspend_(LLCore::HttpRequest::ptr_t &request,
@@ -651,7 +651,7 @@ private:
HttpCoroHandler::ptr_t &handler);
LLSD copyAndSuspend_(LLCore::HttpRequest::ptr_t &request,
- const std::string & url,
+ const std::string & url,
LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
HttpCoroHandler::ptr_t &handler);
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index 1545443798..e8cd11c0a0 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -1,2180 +1,2180 @@
-/**
- * @file lldatapacker.cpp
- * @brief Data packer implementation.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lldatapacker.h"
-#include "llerror.h"
-
-#include "message.h"
-
-#include "v4color.h"
-#include "v4coloru.h"
-#include "v2math.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "lluuid.h"
-
-// *NOTE: there are functions below which use sscanf and rely on this
-// particular value of DP_BUFSIZE. Search for '511' (DP_BUFSIZE - 1)
-// to find them if you change this number.
-const S32 DP_BUFSIZE = 512;
-
-static char DUMMY_BUFFER[128]; /*Flawfinder: ignore*/
-
-LLDataPacker::LLDataPacker() : mPassFlags(0), mWriteEnabled(false)
-{
-}
-
-//virtual
-void LLDataPacker::reset()
-{
- LL_ERRS() << "Using unimplemented datapacker reset!" << LL_ENDL;
-}
-
-//virtual
-void LLDataPacker::dumpBufferToLog()
-{
- LL_ERRS() << "dumpBufferToLog not implemented for this type!" << LL_ENDL;
-}
-
-bool LLDataPacker::packFixed(const F32 value, const char *name,
- const bool is_signed, const U32 int_bits, const U32 frac_bits)
-{
- bool success = true;
- S32 unsigned_bits = int_bits + frac_bits;
- S32 total_bits = unsigned_bits;
-
- if (is_signed)
- {
- total_bits++;
- }
-
- S32 min_val;
- U32 max_val;
- if (is_signed)
- {
- min_val = 1 << int_bits;
- min_val *= -1;
- }
- else
- {
- min_val = 0;
- }
- max_val = 1 << int_bits;
-
- // Clamp to be within range
- F32 fixed_val = llclamp(value, (F32)min_val, (F32)max_val);
- if (is_signed)
- {
- fixed_val += max_val;
- }
- fixed_val *= 1 << frac_bits;
-
- if (total_bits <= 8)
- {
- packU8((U8)fixed_val, name);
- }
- else if (total_bits <= 16)
- {
- packU16((U16)fixed_val, name);
- }
- else if (total_bits <= 31)
- {
- packU32((U32)fixed_val, name);
- }
- else
- {
- LL_ERRS() << "Using fixed-point packing of " << total_bits << " bits, why?!" << LL_ENDL;
- }
- return success;
-}
-
-bool LLDataPacker::unpackFixed(F32 &value, const char *name,
- const bool is_signed, const U32 int_bits, const U32 frac_bits)
-{
- bool success = true;
- //LL_INFOS() << "unpackFixed:" << name << " int:" << int_bits << " frac:" << frac_bits << LL_ENDL;
- S32 unsigned_bits = int_bits + frac_bits;
- S32 total_bits = unsigned_bits;
-
- if (is_signed)
- {
- total_bits++;
- }
-
- U32 max_val;
- max_val = 1 << int_bits;
-
- F32 fixed_val;
- if (total_bits <= 8)
- {
- U8 fixed_8;
- success = unpackU8(fixed_8, name);
- fixed_val = (F32)fixed_8;
- }
- else if (total_bits <= 16)
- {
- U16 fixed_16;
- success = unpackU16(fixed_16, name);
- fixed_val = (F32)fixed_16;
- }
- else if (total_bits <= 31)
- {
- U32 fixed_32;
- success = unpackU32(fixed_32, name);
- fixed_val = (F32)fixed_32;
- }
- else
- {
- fixed_val = 0;
- LL_ERRS() << "Bad bit count: " << total_bits << LL_ENDL;
- }
-
- //LL_INFOS() << "Fixed_val:" << fixed_val << LL_ENDL;
-
- fixed_val /= (F32)(1 << frac_bits);
- if (is_signed)
- {
- fixed_val -= max_val;
- }
- value = fixed_val;
- //LL_INFOS() << "Value: " << value << LL_ENDL;
- return success;
-}
-
-bool LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name)
-{
- for (S32 idx = 0; idx < count; ++idx)
- {
- if (!unpackU16(values[idx], name))
- {
- LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
- return false;
- }
- }
- return true;
-}
-
-bool LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name)
-{
- for (S32 idx = 0; idx < count; ++idx)
- {
- if (!unpackS16(values[idx], name))
- {
- LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
- return false;
- }
- }
- return true;
-}
-
-bool LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name)
-{
- for (S32 idx = 0; idx < count; ++idx)
- {
- if (!unpackF32(values[idx], name))
- {
- LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
- return false;
- }
- }
- return true;
-}
-
-bool LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name)
-{
- for (S32 idx = 0; idx < count; ++idx)
- {
- if (!unpackColor4U(values[idx], name))
- {
- LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
- return false;
- }
- }
- return true;
-}
-
-bool LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)
-{
- for (S32 idx = 0; idx < count; ++idx)
- {
- if (!unpackUUID(values[idx], name))
- {
- LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL;
- return false;
- }
- }
- return true;
-}
-
-//---------------------------------------------------------------------------
-// LLDataPackerBinaryBuffer implementation
-//---------------------------------------------------------------------------
-
-bool LLDataPackerBinaryBuffer::packString(const std::string& value, const char *name)
-{
- S32 length = value.length()+1;
-
- if (!verifyLength(length, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);
- }
- mCurBufferp += length;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackString(std::string& value, const char *name)
-{
- S32 length = (S32)strlen((char *)mCurBufferp) + 1; /*Flawfinder: ignore*/
-
- if (!verifyLength(length, name))
- {
- return false;
- }
-
- value = std::string((char*)mCurBufferp); // We already assume NULL termination calling strlen()
-
- mCurBufferp += length;
- return true;
-}
-
-bool LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
-{
- if (!verifyLength(size + 4, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &size, MVT_S32, 4);
- }
- mCurBufferp += 4;
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
- }
- mCurBufferp += size;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
-{
- if (!verifyLength(4, name))
- {
- LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
- return false;
- }
-
- htolememcpy(&size, mCurBufferp, MVT_S32, 4);
-
- if (size < 0)
- {
- LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData unpacked invalid size, aborting!" << LL_ENDL;
- return false;
- }
-
- mCurBufferp += 4;
-
- if (!verifyLength(size, name))
- {
- LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
- return false;
- }
-
- htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
- mCurBufferp += size;
-
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
-{
- if (!verifyLength(size, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
- }
- mCurBufferp += size;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
-{
- if (!verifyLength(size, name))
- {
- return false;
- }
- htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
- mCurBufferp += size;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packU8(const U8 value, const char *name)
-{
- if (!verifyLength(sizeof(U8), name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- *mCurBufferp = value;
- }
- mCurBufferp++;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackU8(U8 &value, const char *name)
-{
- if (!verifyLength(sizeof(U8), name))
- {
- return false;
- }
-
- value = *mCurBufferp;
- mCurBufferp++;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
-{
- if (!verifyLength(sizeof(U16), name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &value, MVT_U16, 2);
- }
- mCurBufferp += 2;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
-{
- if (!verifyLength(sizeof(U16), name))
- {
- return false;
- }
-
- htolememcpy(&value, mCurBufferp, MVT_U16, 2);
- mCurBufferp += 2;
- return true;
-}
-
-bool LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name)
-{
- bool success = verifyLength(sizeof(S16), name);
-
- if (mWriteEnabled && success)
- {
- htolememcpy(mCurBufferp, &value, MVT_S16, 2);
- }
- mCurBufferp += 2;
- return success;
-}
-
-bool LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)
-{
- bool success = verifyLength(sizeof(S16), name);
-
- if (success)
- {
- htolememcpy(&value, mCurBufferp, MVT_S16, 2);
- }
- mCurBufferp += 2;
- return success;
-}
-
-bool LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
-{
- if (!verifyLength(sizeof(U32), name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &value, MVT_U32, 4);
- }
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
-{
- if (!verifyLength(sizeof(U32), name))
- {
- return false;
- }
-
- htolememcpy(&value, mCurBufferp, MVT_U32, 4);
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
-{
- if (!verifyLength(sizeof(S32), name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &value, MVT_S32, 4);
- }
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
-{
- if(!verifyLength(sizeof(S32), name))
- {
- return false;
- }
-
- htolememcpy(&value, mCurBufferp, MVT_S32, 4);
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
-{
- if (!verifyLength(sizeof(F32), name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &value, MVT_F32, 4);
- }
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
-{
- if (!verifyLength(sizeof(F32), name))
- {
- return false;
- }
-
- htolememcpy(&value, mCurBufferp, MVT_F32, 4);
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
- }
- mCurBufferp += 16;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
- mCurBufferp += 16;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *name)
-{
- if (!verifyLength(4, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);
- }
- mCurBufferp += 4;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
-{
- if (!verifyLength(4, name))
- {
- return false;
- }
-
- htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
- mCurBufferp += 4;
- return true;
-}
-
-
-
-bool LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *name)
-{
- if (!verifyLength(8, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);
- htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);
- }
- mCurBufferp += 8;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
-{
- if (!verifyLength(8, name))
- {
- return false;
- }
-
- htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
- htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
- mCurBufferp += 8;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *name)
-{
- if (!verifyLength(12, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);
- }
- mCurBufferp += 12;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
-{
- if (!verifyLength(12, name))
- {
- return false;
- }
-
- htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
- mCurBufferp += 12;
- return true;
-}
-
-bool LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
- }
- mCurBufferp += 16;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
- mCurBufferp += 16;
- return true;
-}
-
-bool LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- if (mWriteEnabled)
- {
- htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);
- }
- mCurBufferp += 16;
- return true;
-}
-
-
-bool LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
-{
- if (!verifyLength(16, name))
- {
- return false;
- }
-
- htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
- mCurBufferp += 16;
- return true;
-}
-
-const LLDataPackerBinaryBuffer& LLDataPackerBinaryBuffer::operator=(const LLDataPackerBinaryBuffer &a)
-{
- if (a.getBufferSize() > getBufferSize())
- {
- // We've got problems, ack!
- LL_ERRS() << "Trying to do an assignment with not enough room in the target." << LL_ENDL;
- }
- memcpy(mBufferp, a.mBufferp, a.getBufferSize()); /*Flawfinder: ignore*/
- return *this;
-}
-
-void LLDataPackerBinaryBuffer::dumpBufferToLog()
-{
- LL_WARNS() << "Binary Buffer Dump, size: " << mBufferSize << LL_ENDL;
- char line_buffer[256]; /*Flawfinder: ignore*/
- S32 i;
- S32 cur_line_pos = 0;
-
- S32 cur_line = 0;
- for (i = 0; i < mBufferSize; i++)
- {
- snprintf(line_buffer + cur_line_pos*3, sizeof(line_buffer) - cur_line_pos*3, "%02x ", mBufferp[i]); /* Flawfinder: ignore */
- cur_line_pos++;
- if (cur_line_pos >= 16)
- {
- cur_line_pos = 0;
- LL_WARNS() << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << LL_ENDL;
- cur_line++;
- }
- }
- if (cur_line_pos)
- {
- LL_WARNS() << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << LL_ENDL;
- }
-}
-
-//---------------------------------------------------------------------------
-// LLDataPackerAsciiBuffer implementation
-//---------------------------------------------------------------------------
-bool LLDataPackerAsciiBuffer::packString(const std::string& value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", value.c_str()); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = value.length() + 1; /*Flawfinder: ignore*/
- }
-
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- // *NOTE: I believe we need to mark a failure bit at this point.
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packString: string truncated: " << value << LL_ENDL;
- }
- mCurBufferp += numCopied;
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name)
-{
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
- if (!getValueStr(name, valuestr, DP_BUFSIZE)) // NULL terminated
- {
- return false;
- }
- value = valuestr;
- return true;
-}
-
-
-bool LLDataPackerAsciiBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
-
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%010d ", size); /* Flawfinder: ignore */
-
- // snprintf returns number of bytes that would have been
- // written had the output not being truncated. In that case,
- // it will retuen >= passed in size value. so a check needs
- // to be added to detect truncation, and if there is any, only
- // account for the actual number of bytes written..and not
- // what could have been written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: number truncated: " << size << LL_ENDL;
- }
- mCurBufferp += numCopied;
-
-
- S32 i;
- bool bBufferFull = false;
- for (i = 0; i < size && !bBufferFull; i++)
- {
- numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]); /* Flawfinder: ignore */
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: data truncated: " << LL_ENDL;
- bBufferFull = true;
- }
- mCurBufferp += numCopied;
- }
-
- if (!bBufferFull)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n"); /* Flawfinder: ignore */
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: newline truncated: " << LL_ENDL;
- }
- mCurBufferp += numCopied;
- }
- }
- else
- {
- // why +10 ?? XXXCHECK
- numCopied = 10 + 1; // size plus newline
- numCopied += size;
- if (numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- }
- mCurBufferp += numCopied;
- }
-
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char *cur_pos = &valuestr[0];
- sscanf(valuestr,"%010d", &size);
- cur_pos += 11;
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- S32 val;
- sscanf(cur_pos,"%02x", &val);
- value[i] = val;
- cur_pos += 3;
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
-
- if (mWriteEnabled)
- {
- S32 i;
- int numCopied = 0;
- bool bBufferFull = false;
- for (i = 0; i < size && !bBufferFull; i++)
- {
- numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]); /* Flawfinder: ignore */
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryDataFixed: data truncated: " << LL_ENDL;
- bBufferFull = true;
- }
- mCurBufferp += numCopied;
-
- }
- if (!bBufferFull)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n"); /* Flawfinder: ignore */
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryDataFixed: newline truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- }
- }
- else
- {
- int numCopied = 2 * size + 1; //hex bytes plus newline
- if (numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- }
- mCurBufferp += numCopied;
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char *cur_pos = &valuestr[0];
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- S32 val;
- sscanf(cur_pos,"%02x", &val);
- value[i] = val;
- cur_pos += 3;
- }
- return success;
-}
-
-
-
-bool LLDataPackerAsciiBuffer::packU8(const U8 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
- }
- else
- {
- // just do the write to a temp buffer to get the length
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
- }
-
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packU8: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
-
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackU8(U8 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr,"%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::packU16(const U16 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
- }
-
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packU16: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
-
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr,"%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
- }
-
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize())
- {
- numCopied = getBufferSize() - getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
-
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr, "%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%u\n", value); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%u\n", value); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packU32: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackU32(U32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%u", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packS32(const S32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packS32: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackS32(S32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%d", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packF32(const F32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f\n", value); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%f\n", value); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packF32: val truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackF32(F32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packColor4(const LLColor4 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packColor4: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackColor4(LLColor4 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::packColor4U(const LLColor4U &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packColor4U: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackColor4U(LLColor4U &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 r, g, b, a;
-
- sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
- value.mV[0] = r;
- value.mV[1] = g;
- value.mV[2] = b;
- value.mV[3] = a;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packVector2(const LLVector2 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f\n", value.mV[0], value.mV[1]); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f\n", value.mV[0], value.mV[1]); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packVector2: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackVector2(LLVector2 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packVector3(const LLVector3 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packVector3: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackVector3(LLVector3 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
- return success;
-}
-
-bool LLDataPackerAsciiBuffer::packVector4(const LLVector4 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packVector4: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackVector4(LLVector4 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::packUUID(const LLUUID &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
-
- int numCopied = 0;
- if (mWriteEnabled)
- {
- std::string tmp_str;
- value.toString(tmp_str);
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", tmp_str.c_str()); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = 64 + 1; // UUID + newline
- }
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::packUUID: truncated: " << LL_ENDL;
- success = false;
- }
- mCurBufferp += numCopied;
- return success;
-}
-
-
-bool LLDataPackerAsciiBuffer::unpackUUID(LLUUID &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char tmp_str[64]; /* Flawfinder: ignore */
- sscanf(valuestr, "%63s", tmp_str); /* Flawfinder: ignore */
- value.set(tmp_str);
-
- return success;
-}
-
-void LLDataPackerAsciiBuffer::dump()
-{
- LL_INFOS() << "Buffer: " << mBufferp << LL_ENDL;
-}
-
-void LLDataPackerAsciiBuffer::writeIndentedName(const char *name)
-{
- if (mIncludeNames)
- {
- int numCopied = 0;
- if (mWriteEnabled)
- {
- numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\t", name); /* Flawfinder: ignore */
- }
- else
- {
- numCopied = (S32)strlen(name) + 1; /* Flawfinder: ignore */ //name + tab
- }
-
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
- {
- numCopied = getBufferSize()-getCurrentSize();
- LL_WARNS() << "LLDataPackerAsciiBuffer::writeIndentedName: truncated: " << LL_ENDL;
- }
-
- mCurBufferp += numCopied;
- }
-}
-
-bool LLDataPackerAsciiBuffer::getValueStr(const char *name, char *out_value, S32 value_len)
-{
- bool success = true;
- char buffer[DP_BUFSIZE]; /* Flawfinder: ignore */
- char keyword[DP_BUFSIZE]; /* Flawfinder: ignore */
- char value[DP_BUFSIZE]; /* Flawfinder: ignore */
-
- buffer[0] = '\0';
- keyword[0] = '\0';
- value[0] = '\0';
-
- if (mIncludeNames)
- {
- // Read both the name and the value, and validate the name.
- sscanf(mCurBufferp, "%511[^\n]", buffer);
- // Skip the \n
- mCurBufferp += (S32)strlen(buffer) + 1; /* Flawfinder: ignore */
-
- sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
-
- if (strcmp(keyword, name))
- {
- LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
- return false;
- }
- }
- else
- {
- // Just the value exists
- sscanf(mCurBufferp, "%511[^\n]", value);
- // Skip the \n
- mCurBufferp += (S32)strlen(value) + 1; /* Flawfinder: ignore */
- }
-
- S32 in_value_len = (S32)strlen(value)+1; /* Flawfinder: ignore */
- S32 min_len = llmin(in_value_len, value_len);
- memcpy(out_value, value, min_len); /* Flawfinder: ignore */
- out_value[min_len-1] = 0;
-
- return success;
-}
-
-// helper function used by LLDataPackerAsciiFile
-// to convert F32 into a string. This is to avoid
-// << operator writing F32 value into a stream
-// since it does not seem to preserve the float value
-std::string convertF32ToString(F32 val)
-{
- std::string str;
- char buf[20];
- snprintf(buf, 20, "%f", val);
- str = buf;
- return str;
-}
-
-//---------------------------------------------------------------------------
-// LLDataPackerAsciiFile implementation
-//---------------------------------------------------------------------------
-bool LLDataPackerAsciiFile::packString(const std::string& value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%s\n", value.c_str());
- }
- else if (mOutputStream)
- {
- *mOutputStream << value << "\n";
- }
- return success;
-}
-
-bool LLDataPackerAsciiFile::unpackString(std::string& value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
- value = valuestr;
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packBinaryData(const U8 *value, S32 size, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
-
- if (mFP)
- {
- fprintf(mFP, "%010d ", size);
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- fprintf(mFP, "%02x ", value[i]);
- }
- fprintf(mFP, "\n");
- }
- else if (mOutputStream)
- {
- char buffer[32]; /* Flawfinder: ignore */
- snprintf(buffer,sizeof(buffer), "%010d ", size); /* Flawfinder: ignore */
- *mOutputStream << buffer;
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- snprintf(buffer, sizeof(buffer), "%02x ", value[i]); /* Flawfinder: ignore */
- *mOutputStream << buffer;
- }
- *mOutputStream << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackBinaryData(U8 *value, S32 &size, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char *cur_pos = &valuestr[0];
- sscanf(valuestr,"%010d", &size);
- cur_pos += 11;
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- S32 val;
- sscanf(cur_pos,"%02x", &val);
- value[i] = val;
- cur_pos += 3;
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
-
- if (mFP)
- {
- S32 i;
- for (i = 0; i < size; i++)
- {
- fprintf(mFP, "%02x ", value[i]);
- }
- fprintf(mFP, "\n");
- }
- else if (mOutputStream)
- {
- char buffer[32]; /*Flawfinder: ignore*/
- S32 i;
- for (i = 0; i < size; i++)
- {
- snprintf(buffer, sizeof(buffer), "%02x ", value[i]); /* Flawfinder: ignore */
- *mOutputStream << buffer;
- }
- *mOutputStream << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char *cur_pos = &valuestr[0];
-
- S32 i;
- for (i = 0; i < size; i++)
- {
- S32 val;
- sscanf(cur_pos,"%02x", &val);
- value[i] = val;
- cur_pos += 3;
- }
- return success;
-}
-
-
-
-bool LLDataPackerAsciiFile::packU8(const U8 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%d\n", value);
- }
- else if (mOutputStream)
- {
- // We have to cast this to an integer because streams serialize
- // bytes as bytes - not as text.
- *mOutputStream << (S32)value << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackU8(U8 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr,"%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiFile::packU16(const U16 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%d\n", value);
- }
- else if (mOutputStream)
- {
- *mOutputStream <<"" << value << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr,"%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiFile::packS16(const S16 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP, "%d\n", value);
- }
- else if (mOutputStream)
- {
- *mOutputStream << "" << value << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 in_val;
- sscanf(valuestr, "%d", &in_val);
- value = in_val;
- return success;
-}
-
-bool LLDataPackerAsciiFile::packU32(const U32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%u\n", value);
- }
- else if (mOutputStream)
- {
- *mOutputStream <<"" << value << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackU32(U32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%u", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packS32(const S32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%d\n", value);
- }
- else if (mOutputStream)
- {
- *mOutputStream <<"" << value << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackS32(S32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%d", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packF32(const F32 value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%f\n", value);
- }
- else if (mOutputStream)
- {
- *mOutputStream <<"" << convertF32ToString(value) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackF32(F32 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f", &value);
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packColor4(const LLColor4 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
- }
- else if (mOutputStream)
- {
- *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackColor4(LLColor4 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
- return success;
-}
-
-bool LLDataPackerAsciiFile::packColor4U(const LLColor4U &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
- }
- else if (mOutputStream)
- {
- *mOutputStream << (S32)(value.mV[0]) << " " << (S32)(value.mV[1]) << " " << (S32)(value.mV[2]) << " " << (S32)(value.mV[3]) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackColor4U(LLColor4U &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- S32 r, g, b, a;
-
- sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
- value.mV[0] = r;
- value.mV[1] = g;
- value.mV[2] = b;
- value.mV[3] = a;
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packVector2(const LLVector2 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%f %f\n", value.mV[0], value.mV[1]);
- }
- else if (mOutputStream)
- {
- *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackVector2(LLVector2 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packVector3(const LLVector3 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]);
- }
- else if (mOutputStream)
- {
- *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackVector3(LLVector3 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
- return success;
-}
-
-bool LLDataPackerAsciiFile::packVector4(const LLVector4 &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- if (mFP)
- {
- fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
- }
- else if (mOutputStream)
- {
- *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackVector4(LLVector4 &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::packUUID(const LLUUID &value, const char *name)
-{
- bool success = true;
- writeIndentedName(name);
- std::string tmp_str;
- value.toString(tmp_str);
- if (mFP)
- {
- fprintf(mFP,"%s\n", tmp_str.c_str());
- }
- else if (mOutputStream)
- {
- *mOutputStream <<"" << tmp_str << "\n";
- }
- return success;
-}
-
-
-bool LLDataPackerAsciiFile::unpackUUID(LLUUID &value, const char *name)
-{
- bool success = true;
- char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
- if (!getValueStr(name, valuestr, DP_BUFSIZE))
- {
- return false;
- }
-
- char tmp_str[64]; /*Flawfinder: ignore */
- sscanf(valuestr,"%63s",tmp_str); /* Flawfinder: ignore */
- value.set(tmp_str);
-
- return success;
-}
-
-
-void LLDataPackerAsciiFile::writeIndentedName(const char *name)
-{
- std::string indent_buf;
- indent_buf.reserve(mIndent+1);
-
- S32 i;
- for(i = 0; i < mIndent; i++)
- {
- indent_buf[i] = '\t';
- }
- indent_buf[i] = 0;
- if (mFP)
- {
- fprintf(mFP,"%s%s\t",indent_buf.c_str(), name);
- }
- else if (mOutputStream)
- {
- *mOutputStream << indent_buf << name << "\t";
- }
-}
-
-bool LLDataPackerAsciiFile::getValueStr(const char *name, char *out_value, S32 value_len)
-{
- bool success = false;
- char buffer[DP_BUFSIZE]; /*Flawfinder: ignore*/
- char keyword[DP_BUFSIZE]; /*Flawfinder: ignore*/
- char value[DP_BUFSIZE]; /*Flawfinder: ignore*/
-
- buffer[0] = '\0';
- keyword[0] = '\0';
- value[0] = '\0';
-
- if (mFP)
- {
- fpos_t last_pos;
- if (0 != fgetpos(mFP, &last_pos)) // 0==success for fgetpos
- {
- LL_WARNS() << "Data packer failed to fgetpos" << LL_ENDL;
- return false;
- }
-
- if (fgets(buffer, DP_BUFSIZE, mFP) == NULL)
- {
- buffer[0] = '\0';
- }
-
- sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
-
- if (!keyword[0])
- {
- LL_WARNS() << "Data packer could not get the keyword!" << LL_ENDL;
- fsetpos(mFP, &last_pos);
- return false;
- }
- if (strcmp(keyword, name))
- {
- LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
- fsetpos(mFP, &last_pos);
- return false;
- }
-
- S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
- S32 min_len = llmin(in_value_len, value_len);
- memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
- out_value[min_len-1] = 0;
- success = true;
- }
- else if (mInputStream)
- {
- mInputStream->getline(buffer, DP_BUFSIZE);
-
- sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
- if (!keyword[0])
- {
- LL_WARNS() << "Data packer could not get the keyword!" << LL_ENDL;
- return false;
- }
- if (strcmp(keyword, name))
- {
- LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
- return false;
- }
-
- S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
- S32 min_len = llmin(in_value_len, value_len);
- memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
- out_value[min_len-1] = 0;
- success = true;
- }
-
- return success;
-}
+/**
+ * @file lldatapacker.cpp
+ * @brief Data packer implementation.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldatapacker.h"
+#include "llerror.h"
+
+#include "message.h"
+
+#include "v4color.h"
+#include "v4coloru.h"
+#include "v2math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "lluuid.h"
+
+// *NOTE: there are functions below which use sscanf and rely on this
+// particular value of DP_BUFSIZE. Search for '511' (DP_BUFSIZE - 1)
+// to find them if you change this number.
+const S32 DP_BUFSIZE = 512;
+
+static char DUMMY_BUFFER[128]; /*Flawfinder: ignore*/
+
+LLDataPacker::LLDataPacker() : mPassFlags(0), mWriteEnabled(false)
+{
+}
+
+//virtual
+void LLDataPacker::reset()
+{
+ LL_ERRS() << "Using unimplemented datapacker reset!" << LL_ENDL;
+}
+
+//virtual
+void LLDataPacker::dumpBufferToLog()
+{
+ LL_ERRS() << "dumpBufferToLog not implemented for this type!" << LL_ENDL;
+}
+
+bool LLDataPacker::packFixed(const F32 value, const char *name,
+ const bool is_signed, const U32 int_bits, const U32 frac_bits)
+{
+ bool success = true;
+ S32 unsigned_bits = int_bits + frac_bits;
+ S32 total_bits = unsigned_bits;
+
+ if (is_signed)
+ {
+ total_bits++;
+ }
+
+ S32 min_val;
+ U32 max_val;
+ if (is_signed)
+ {
+ min_val = 1 << int_bits;
+ min_val *= -1;
+ }
+ else
+ {
+ min_val = 0;
+ }
+ max_val = 1 << int_bits;
+
+ // Clamp to be within range
+ F32 fixed_val = llclamp(value, (F32)min_val, (F32)max_val);
+ if (is_signed)
+ {
+ fixed_val += max_val;
+ }
+ fixed_val *= 1 << frac_bits;
+
+ if (total_bits <= 8)
+ {
+ packU8((U8)fixed_val, name);
+ }
+ else if (total_bits <= 16)
+ {
+ packU16((U16)fixed_val, name);
+ }
+ else if (total_bits <= 31)
+ {
+ packU32((U32)fixed_val, name);
+ }
+ else
+ {
+ LL_ERRS() << "Using fixed-point packing of " << total_bits << " bits, why?!" << LL_ENDL;
+ }
+ return success;
+}
+
+bool LLDataPacker::unpackFixed(F32 &value, const char *name,
+ const bool is_signed, const U32 int_bits, const U32 frac_bits)
+{
+ bool success = true;
+ //LL_INFOS() << "unpackFixed:" << name << " int:" << int_bits << " frac:" << frac_bits << LL_ENDL;
+ S32 unsigned_bits = int_bits + frac_bits;
+ S32 total_bits = unsigned_bits;
+
+ if (is_signed)
+ {
+ total_bits++;
+ }
+
+ U32 max_val;
+ max_val = 1 << int_bits;
+
+ F32 fixed_val;
+ if (total_bits <= 8)
+ {
+ U8 fixed_8;
+ success = unpackU8(fixed_8, name);
+ fixed_val = (F32)fixed_8;
+ }
+ else if (total_bits <= 16)
+ {
+ U16 fixed_16;
+ success = unpackU16(fixed_16, name);
+ fixed_val = (F32)fixed_16;
+ }
+ else if (total_bits <= 31)
+ {
+ U32 fixed_32;
+ success = unpackU32(fixed_32, name);
+ fixed_val = (F32)fixed_32;
+ }
+ else
+ {
+ fixed_val = 0;
+ LL_ERRS() << "Bad bit count: " << total_bits << LL_ENDL;
+ }
+
+ //LL_INFOS() << "Fixed_val:" << fixed_val << LL_ENDL;
+
+ fixed_val /= (F32)(1 << frac_bits);
+ if (is_signed)
+ {
+ fixed_val -= max_val;
+ }
+ value = fixed_val;
+ //LL_INFOS() << "Value: " << value << LL_ENDL;
+ return success;
+}
+
+bool LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackU16(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackS16(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackF32(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackColor4U(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackUUID(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// LLDataPackerBinaryBuffer implementation
+//---------------------------------------------------------------------------
+
+bool LLDataPackerBinaryBuffer::packString(const std::string& value, const char *name)
+{
+ S32 length = value.length()+1;
+
+ if (!verifyLength(length, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);
+ }
+ mCurBufferp += length;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackString(std::string& value, const char *name)
+{
+ S32 length = (S32)strlen((char *)mCurBufferp) + 1; /*Flawfinder: ignore*/
+
+ if (!verifyLength(length, name))
+ {
+ return false;
+ }
+
+ value = std::string((char*)mCurBufferp); // We already assume NULL termination calling strlen()
+
+ mCurBufferp += length;
+ return true;
+}
+
+bool LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
+{
+ if (!verifyLength(size + 4, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &size, MVT_S32, 4);
+ }
+ mCurBufferp += 4;
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
+ }
+ mCurBufferp += size;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
+{
+ if (!verifyLength(4, name))
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
+ return false;
+ }
+
+ htolememcpy(&size, mCurBufferp, MVT_S32, 4);
+
+ if (size < 0)
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData unpacked invalid size, aborting!" << LL_ENDL;
+ return false;
+ }
+
+ mCurBufferp += 4;
+
+ if (!verifyLength(size, name))
+ {
+ LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL;
+ return false;
+ }
+
+ htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
+ mCurBufferp += size;
+
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
+{
+ if (!verifyLength(size, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);
+ }
+ mCurBufferp += size;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
+{
+ if (!verifyLength(size, name))
+ {
+ return false;
+ }
+ htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);
+ mCurBufferp += size;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packU8(const U8 value, const char *name)
+{
+ if (!verifyLength(sizeof(U8), name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ *mCurBufferp = value;
+ }
+ mCurBufferp++;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackU8(U8 &value, const char *name)
+{
+ if (!verifyLength(sizeof(U8), name))
+ {
+ return false;
+ }
+
+ value = *mCurBufferp;
+ mCurBufferp++;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)
+{
+ if (!verifyLength(sizeof(U16), name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_U16, 2);
+ }
+ mCurBufferp += 2;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
+{
+ if (!verifyLength(sizeof(U16), name))
+ {
+ return false;
+ }
+
+ htolememcpy(&value, mCurBufferp, MVT_U16, 2);
+ mCurBufferp += 2;
+ return true;
+}
+
+bool LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name)
+{
+ bool success = verifyLength(sizeof(S16), name);
+
+ if (mWriteEnabled && success)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_S16, 2);
+ }
+ mCurBufferp += 2;
+ return success;
+}
+
+bool LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)
+{
+ bool success = verifyLength(sizeof(S16), name);
+
+ if (success)
+ {
+ htolememcpy(&value, mCurBufferp, MVT_S16, 2);
+ }
+ mCurBufferp += 2;
+ return success;
+}
+
+bool LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
+{
+ if (!verifyLength(sizeof(U32), name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_U32, 4);
+ }
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)
+{
+ if (!verifyLength(sizeof(U32), name))
+ {
+ return false;
+ }
+
+ htolememcpy(&value, mCurBufferp, MVT_U32, 4);
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)
+{
+ if (!verifyLength(sizeof(S32), name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_S32, 4);
+ }
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)
+{
+ if(!verifyLength(sizeof(S32), name))
+ {
+ return false;
+ }
+
+ htolememcpy(&value, mCurBufferp, MVT_S32, 4);
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)
+{
+ if (!verifyLength(sizeof(F32), name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_F32, 4);
+ }
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)
+{
+ if (!verifyLength(sizeof(F32), name))
+ {
+ return false;
+ }
+
+ htolememcpy(&value, mCurBufferp, MVT_F32, 4);
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
+ }
+ mCurBufferp += 16;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
+ mCurBufferp += 16;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *name)
+{
+ if (!verifyLength(4, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);
+ }
+ mCurBufferp += 4;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)
+{
+ if (!verifyLength(4, name))
+ {
+ return false;
+ }
+
+ htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);
+ mCurBufferp += 4;
+ return true;
+}
+
+
+
+bool LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *name)
+{
+ if (!verifyLength(8, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, &value.mV[0], MVT_F32, 4);
+ htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);
+ }
+ mCurBufferp += 8;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)
+{
+ if (!verifyLength(8, name))
+ {
+ return false;
+ }
+
+ htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);
+ htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);
+ mCurBufferp += 8;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *name)
+{
+ if (!verifyLength(12, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);
+ }
+ mCurBufferp += 12;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)
+{
+ if (!verifyLength(12, name))
+ {
+ return false;
+ }
+
+ htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);
+ mCurBufferp += 12;
+ return true;
+}
+
+bool LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);
+ }
+ mCurBufferp += 16;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);
+ mCurBufferp += 16;
+ return true;
+}
+
+bool LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ if (mWriteEnabled)
+ {
+ htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);
+ }
+ mCurBufferp += 16;
+ return true;
+}
+
+
+bool LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)
+{
+ if (!verifyLength(16, name))
+ {
+ return false;
+ }
+
+ htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);
+ mCurBufferp += 16;
+ return true;
+}
+
+const LLDataPackerBinaryBuffer& LLDataPackerBinaryBuffer::operator=(const LLDataPackerBinaryBuffer &a)
+{
+ if (a.getBufferSize() > getBufferSize())
+ {
+ // We've got problems, ack!
+ LL_ERRS() << "Trying to do an assignment with not enough room in the target." << LL_ENDL;
+ }
+ memcpy(mBufferp, a.mBufferp, a.getBufferSize()); /*Flawfinder: ignore*/
+ return *this;
+}
+
+void LLDataPackerBinaryBuffer::dumpBufferToLog()
+{
+ LL_WARNS() << "Binary Buffer Dump, size: " << mBufferSize << LL_ENDL;
+ char line_buffer[256]; /*Flawfinder: ignore*/
+ S32 i;
+ S32 cur_line_pos = 0;
+
+ S32 cur_line = 0;
+ for (i = 0; i < mBufferSize; i++)
+ {
+ snprintf(line_buffer + cur_line_pos*3, sizeof(line_buffer) - cur_line_pos*3, "%02x ", mBufferp[i]); /* Flawfinder: ignore */
+ cur_line_pos++;
+ if (cur_line_pos >= 16)
+ {
+ cur_line_pos = 0;
+ LL_WARNS() << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << LL_ENDL;
+ cur_line++;
+ }
+ }
+ if (cur_line_pos)
+ {
+ LL_WARNS() << "Offset:" << std::hex << cur_line*16 << std::dec << " Data:" << line_buffer << LL_ENDL;
+ }
+}
+
+//---------------------------------------------------------------------------
+// LLDataPackerAsciiBuffer implementation
+//---------------------------------------------------------------------------
+bool LLDataPackerAsciiBuffer::packString(const std::string& value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", value.c_str()); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = value.length() + 1; /*Flawfinder: ignore*/
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ // *NOTE: I believe we need to mark a failure bit at this point.
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packString: string truncated: " << value << LL_ENDL;
+ }
+ mCurBufferp += numCopied;
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name)
+{
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
+ if (!getValueStr(name, valuestr, DP_BUFSIZE)) // NULL terminated
+ {
+ return false;
+ }
+ value = valuestr;
+ return true;
+}
+
+
+bool LLDataPackerAsciiBuffer::packBinaryData(const U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%010d ", size); /* Flawfinder: ignore */
+
+ // snprintf returns number of bytes that would have been
+ // written had the output not being truncated. In that case,
+ // it will retuen >= passed in size value. so a check needs
+ // to be added to detect truncation, and if there is any, only
+ // account for the actual number of bytes written..and not
+ // what could have been written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: number truncated: " << size << LL_ENDL;
+ }
+ mCurBufferp += numCopied;
+
+
+ S32 i;
+ bool bBufferFull = false;
+ for (i = 0; i < size && !bBufferFull; i++)
+ {
+ numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]); /* Flawfinder: ignore */
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: data truncated: " << LL_ENDL;
+ bBufferFull = true;
+ }
+ mCurBufferp += numCopied;
+ }
+
+ if (!bBufferFull)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n"); /* Flawfinder: ignore */
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryData: newline truncated: " << LL_ENDL;
+ }
+ mCurBufferp += numCopied;
+ }
+ }
+ else
+ {
+ // why +10 ?? XXXCHECK
+ numCopied = 10 + 1; // size plus newline
+ numCopied += size;
+ if (numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ }
+ mCurBufferp += numCopied;
+ }
+
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char *cur_pos = &valuestr[0];
+ sscanf(valuestr,"%010d", &size);
+ cur_pos += 11;
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ S32 val;
+ sscanf(cur_pos,"%02x", &val);
+ value[i] = val;
+ cur_pos += 3;
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+
+ if (mWriteEnabled)
+ {
+ S32 i;
+ int numCopied = 0;
+ bool bBufferFull = false;
+ for (i = 0; i < size && !bBufferFull; i++)
+ {
+ numCopied = snprintf(mCurBufferp, getBufferSize()-getCurrentSize(), "%02x ", value[i]); /* Flawfinder: ignore */
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryDataFixed: data truncated: " << LL_ENDL;
+ bBufferFull = true;
+ }
+ mCurBufferp += numCopied;
+
+ }
+ if (!bBufferFull)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(), "\n"); /* Flawfinder: ignore */
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packBinaryDataFixed: newline truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ }
+ }
+ else
+ {
+ int numCopied = 2 * size + 1; //hex bytes plus newline
+ if (numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ }
+ mCurBufferp += numCopied;
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char *cur_pos = &valuestr[0];
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ S32 val;
+ sscanf(cur_pos,"%02x", &val);
+ value[i] = val;
+ cur_pos += 3;
+ }
+ return success;
+}
+
+
+
+bool LLDataPackerAsciiBuffer::packU8(const U8 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ // just do the write to a temp buffer to get the length
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packU8: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackU8(U8 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr,"%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::packU16(const U16 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packU16: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr,"%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize())
+ {
+ numCopied = getBufferSize() - getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr, "%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%u\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%u\n", value); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packU32: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackU32(U32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%u", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packS32(const S32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packS32: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackS32(S32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%d", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packF32(const F32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%f\n", value); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packF32: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackF32(F32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packColor4(const LLColor4 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packColor4: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackColor4(LLColor4 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::packColor4U(const LLColor4U &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packColor4U: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackColor4U(LLColor4U &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 r, g, b, a;
+
+ sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
+ value.mV[0] = r;
+ value.mV[1] = g;
+ value.mV[2] = b;
+ value.mV[3] = a;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packVector2(const LLVector2 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f\n", value.mV[0], value.mV[1]); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f\n", value.mV[0], value.mV[1]); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packVector2: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackVector2(LLVector2 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packVector3(const LLVector3 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packVector3: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackVector3(LLVector3 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
+ return success;
+}
+
+bool LLDataPackerAsciiBuffer::packVector4(const LLVector4 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER,sizeof(DUMMY_BUFFER),"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]); /* Flawfinder: ignore */
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packVector4: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackVector4(LLVector4 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::packUUID(const LLUUID &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ std::string tmp_str;
+ value.toString(tmp_str);
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\n", tmp_str.c_str()); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = 64 + 1; // UUID + newline
+ }
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packUUID: truncated: " << LL_ENDL;
+ success = false;
+ }
+ mCurBufferp += numCopied;
+ return success;
+}
+
+
+bool LLDataPackerAsciiBuffer::unpackUUID(LLUUID &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char tmp_str[64]; /* Flawfinder: ignore */
+ sscanf(valuestr, "%63s", tmp_str); /* Flawfinder: ignore */
+ value.set(tmp_str);
+
+ return success;
+}
+
+void LLDataPackerAsciiBuffer::dump()
+{
+ LL_INFOS() << "Buffer: " << mBufferp << LL_ENDL;
+}
+
+void LLDataPackerAsciiBuffer::writeIndentedName(const char *name)
+{
+ if (mIncludeNames)
+ {
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp,getBufferSize()-getCurrentSize(),"%s\t", name); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = (S32)strlen(name) + 1; /* Flawfinder: ignore */ //name + tab
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (numCopied < 0 || numCopied > getBufferSize()-getCurrentSize())
+ {
+ numCopied = getBufferSize()-getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::writeIndentedName: truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+ }
+}
+
+bool LLDataPackerAsciiBuffer::getValueStr(const char *name, char *out_value, S32 value_len)
+{
+ bool success = true;
+ char buffer[DP_BUFSIZE]; /* Flawfinder: ignore */
+ char keyword[DP_BUFSIZE]; /* Flawfinder: ignore */
+ char value[DP_BUFSIZE]; /* Flawfinder: ignore */
+
+ buffer[0] = '\0';
+ keyword[0] = '\0';
+ value[0] = '\0';
+
+ if (mIncludeNames)
+ {
+ // Read both the name and the value, and validate the name.
+ sscanf(mCurBufferp, "%511[^\n]", buffer);
+ // Skip the \n
+ mCurBufferp += (S32)strlen(buffer) + 1; /* Flawfinder: ignore */
+
+ sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
+
+ if (strcmp(keyword, name))
+ {
+ LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
+ return false;
+ }
+ }
+ else
+ {
+ // Just the value exists
+ sscanf(mCurBufferp, "%511[^\n]", value);
+ // Skip the \n
+ mCurBufferp += (S32)strlen(value) + 1; /* Flawfinder: ignore */
+ }
+
+ S32 in_value_len = (S32)strlen(value)+1; /* Flawfinder: ignore */
+ S32 min_len = llmin(in_value_len, value_len);
+ memcpy(out_value, value, min_len); /* Flawfinder: ignore */
+ out_value[min_len-1] = 0;
+
+ return success;
+}
+
+// helper function used by LLDataPackerAsciiFile
+// to convert F32 into a string. This is to avoid
+// << operator writing F32 value into a stream
+// since it does not seem to preserve the float value
+std::string convertF32ToString(F32 val)
+{
+ std::string str;
+ char buf[20];
+ snprintf(buf, 20, "%f", val);
+ str = buf;
+ return str;
+}
+
+//---------------------------------------------------------------------------
+// LLDataPackerAsciiFile implementation
+//---------------------------------------------------------------------------
+bool LLDataPackerAsciiFile::packString(const std::string& value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%s\n", value.c_str());
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << value << "\n";
+ }
+ return success;
+}
+
+bool LLDataPackerAsciiFile::unpackString(std::string& value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+ value = valuestr;
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packBinaryData(const U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+
+ if (mFP)
+ {
+ fprintf(mFP, "%010d ", size);
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ fprintf(mFP, "%02x ", value[i]);
+ }
+ fprintf(mFP, "\n");
+ }
+ else if (mOutputStream)
+ {
+ char buffer[32]; /* Flawfinder: ignore */
+ snprintf(buffer,sizeof(buffer), "%010d ", size); /* Flawfinder: ignore */
+ *mOutputStream << buffer;
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ snprintf(buffer, sizeof(buffer), "%02x ", value[i]); /* Flawfinder: ignore */
+ *mOutputStream << buffer;
+ }
+ *mOutputStream << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackBinaryData(U8 *value, S32 &size, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char *cur_pos = &valuestr[0];
+ sscanf(valuestr,"%010d", &size);
+ cur_pos += 11;
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ S32 val;
+ sscanf(cur_pos,"%02x", &val);
+ value[i] = val;
+ cur_pos += 3;
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packBinaryDataFixed(const U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+
+ if (mFP)
+ {
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ fprintf(mFP, "%02x ", value[i]);
+ }
+ fprintf(mFP, "\n");
+ }
+ else if (mOutputStream)
+ {
+ char buffer[32]; /*Flawfinder: ignore*/
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ snprintf(buffer, sizeof(buffer), "%02x ", value[i]); /* Flawfinder: ignore */
+ *mOutputStream << buffer;
+ }
+ *mOutputStream << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char *cur_pos = &valuestr[0];
+
+ S32 i;
+ for (i = 0; i < size; i++)
+ {
+ S32 val;
+ sscanf(cur_pos,"%02x", &val);
+ value[i] = val;
+ cur_pos += 3;
+ }
+ return success;
+}
+
+
+
+bool LLDataPackerAsciiFile::packU8(const U8 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%d\n", value);
+ }
+ else if (mOutputStream)
+ {
+ // We have to cast this to an integer because streams serialize
+ // bytes as bytes - not as text.
+ *mOutputStream << (S32)value << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackU8(U8 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr,"%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiFile::packU16(const U16 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%d\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream <<"" << value << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr,"%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiFile::packS16(const S16 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP, "%d\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << "" << value << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 in_val;
+ sscanf(valuestr, "%d", &in_val);
+ value = in_val;
+ return success;
+}
+
+bool LLDataPackerAsciiFile::packU32(const U32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%u\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream <<"" << value << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackU32(U32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%u", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packS32(const S32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%d\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream <<"" << value << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackS32(S32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%d", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packF32(const F32 value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%f\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream <<"" << convertF32ToString(value) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackF32(F32 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f", &value);
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packColor4(const LLColor4 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackColor4(LLColor4 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
+ return success;
+}
+
+bool LLDataPackerAsciiFile::packColor4U(const LLColor4U &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%d %d %d %d\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << (S32)(value.mV[0]) << " " << (S32)(value.mV[1]) << " " << (S32)(value.mV[2]) << " " << (S32)(value.mV[3]) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackColor4U(LLColor4U &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ S32 r, g, b, a;
+
+ sscanf(valuestr,"%d %d %d %d", &r, &g, &b, &a);
+ value.mV[0] = r;
+ value.mV[1] = g;
+ value.mV[2] = b;
+ value.mV[3] = a;
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packVector2(const LLVector2 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%f %f\n", value.mV[0], value.mV[1]);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackVector2(LLVector2 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f", &value.mV[0], &value.mV[1]);
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packVector3(const LLVector3 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%f %f %f\n", value.mV[0], value.mV[1], value.mV[2]);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackVector3(LLVector3 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f", &value.mV[0], &value.mV[1], &value.mV[2]);
+ return success;
+}
+
+bool LLDataPackerAsciiFile::packVector4(const LLVector4 &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP,"%f %f %f %f\n", value.mV[0], value.mV[1], value.mV[2], value.mV[3]);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << convertF32ToString(value.mV[0]) << " " << convertF32ToString(value.mV[1]) << " " << convertF32ToString(value.mV[2]) << " " << convertF32ToString(value.mV[3]) << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackVector4(LLVector4 &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ sscanf(valuestr,"%f %f %f %f", &value.mV[0], &value.mV[1], &value.mV[2], &value.mV[3]);
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::packUUID(const LLUUID &value, const char *name)
+{
+ bool success = true;
+ writeIndentedName(name);
+ std::string tmp_str;
+ value.toString(tmp_str);
+ if (mFP)
+ {
+ fprintf(mFP,"%s\n", tmp_str.c_str());
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream <<"" << tmp_str << "\n";
+ }
+ return success;
+}
+
+
+bool LLDataPackerAsciiFile::unpackUUID(LLUUID &value, const char *name)
+{
+ bool success = true;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return false;
+ }
+
+ char tmp_str[64]; /*Flawfinder: ignore */
+ sscanf(valuestr,"%63s",tmp_str); /* Flawfinder: ignore */
+ value.set(tmp_str);
+
+ return success;
+}
+
+
+void LLDataPackerAsciiFile::writeIndentedName(const char *name)
+{
+ std::string indent_buf;
+ indent_buf.reserve(mIndent+1);
+
+ S32 i;
+ for(i = 0; i < mIndent; i++)
+ {
+ indent_buf[i] = '\t';
+ }
+ indent_buf[i] = 0;
+ if (mFP)
+ {
+ fprintf(mFP,"%s%s\t",indent_buf.c_str(), name);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << indent_buf << name << "\t";
+ }
+}
+
+bool LLDataPackerAsciiFile::getValueStr(const char *name, char *out_value, S32 value_len)
+{
+ bool success = false;
+ char buffer[DP_BUFSIZE]; /*Flawfinder: ignore*/
+ char keyword[DP_BUFSIZE]; /*Flawfinder: ignore*/
+ char value[DP_BUFSIZE]; /*Flawfinder: ignore*/
+
+ buffer[0] = '\0';
+ keyword[0] = '\0';
+ value[0] = '\0';
+
+ if (mFP)
+ {
+ fpos_t last_pos;
+ if (0 != fgetpos(mFP, &last_pos)) // 0==success for fgetpos
+ {
+ LL_WARNS() << "Data packer failed to fgetpos" << LL_ENDL;
+ return false;
+ }
+
+ if (fgets(buffer, DP_BUFSIZE, mFP) == NULL)
+ {
+ buffer[0] = '\0';
+ }
+
+ sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
+
+ if (!keyword[0])
+ {
+ LL_WARNS() << "Data packer could not get the keyword!" << LL_ENDL;
+ fsetpos(mFP, &last_pos);
+ return false;
+ }
+ if (strcmp(keyword, name))
+ {
+ LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
+ fsetpos(mFP, &last_pos);
+ return false;
+ }
+
+ S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
+ S32 min_len = llmin(in_value_len, value_len);
+ memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
+ out_value[min_len-1] = 0;
+ success = true;
+ }
+ else if (mInputStream)
+ {
+ mInputStream->getline(buffer, DP_BUFSIZE);
+
+ sscanf(buffer, "%511s %511[^\n]", keyword, value); /* Flawfinder: ignore */
+ if (!keyword[0])
+ {
+ LL_WARNS() << "Data packer could not get the keyword!" << LL_ENDL;
+ return false;
+ }
+ if (strcmp(keyword, name))
+ {
+ LL_WARNS() << "Data packer expecting keyword of type " << name << ", got " << keyword << " instead!" << LL_ENDL;
+ return false;
+ }
+
+ S32 in_value_len = (S32)strlen(value)+1; /*Flawfinder: ignore*/
+ S32 min_len = llmin(in_value_len, value_len);
+ memcpy(out_value, value, min_len); /*Flawfinder: ignore*/
+ out_value[min_len-1] = 0;
+ success = true;
+ }
+
+ return success;
+}
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h
index 8e980d8611..5c896d28fc 100644
--- a/indra/llmessage/lldatapacker.h
+++ b/indra/llmessage/lldatapacker.h
@@ -1,435 +1,435 @@
-/**
- * @file lldatapacker.h
- * @brief Data packer declaration for tightly storing binary data.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLDATAPACKER_H
-#define LL_LLDATAPACKER_H
-
-class LLColor4;
-class LLColor4U;
-class LLVector2;
-class LLVector3;
-class LLVector4;
-class LLUUID;
-
-class LLDataPacker
-{
-public:
- virtual ~LLDataPacker() {}
-
- // Not required to override, but error to call?
- virtual void reset();
- virtual void dumpBufferToLog();
-
- virtual bool hasNext() const = 0;
-
- virtual bool packString(const std::string& value, const char *name) = 0;
- virtual bool unpackString(std::string& value, const char *name) = 0;
-
- virtual bool packBinaryData(const U8 *value, S32 size, const char *name) = 0;
- virtual bool unpackBinaryData(U8 *value, S32 &size, const char *name) = 0;
-
- // Constant size binary data packing
- virtual bool packBinaryDataFixed(const U8 *value, S32 size, const char *name) = 0;
- virtual bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name) = 0;
-
- virtual bool packU8(const U8 value, const char *name) = 0;
- virtual bool unpackU8(U8 &value, const char *name) = 0;
-
- virtual bool packU16(const U16 value, const char *name) = 0;
- virtual bool unpackU16(U16 &value, const char *name) = 0;
- bool unpackU16s(U16 *value, S32 count, const char *name);
-
- virtual bool packS16(const S16 value, const char *name) = 0;
- virtual bool unpackS16(S16 &value, const char *name) = 0;
- bool unpackS16s(S16 *value, S32 count, const char *name);
-
- virtual bool packU32(const U32 value, const char *name) = 0;
- virtual bool unpackU32(U32 &value, const char *name) = 0;
-
- virtual bool packS32(const S32 value, const char *name) = 0;
- virtual bool unpackS32(S32 &value, const char *name) = 0;
-
- virtual bool packF32(const F32 value, const char *name) = 0;
- virtual bool unpackF32(F32 &value, const char *name) = 0;
- bool unpackF32s(F32 *values, S32 count, const char *name);
-
- // Packs a float into an integer, using the given size
- // and picks the right U* data type to pack into.
- bool packFixed(const F32 value, const char *name,
- const bool is_signed, const U32 int_bits, const U32 frac_bits);
- bool unpackFixed(F32 &value, const char *name,
- const bool is_signed, const U32 int_bits, const U32 frac_bits);
-
- virtual bool packColor4(const LLColor4 &value, const char *name) = 0;
- virtual bool unpackColor4(LLColor4 &value, const char *name) = 0;
-
- virtual bool packColor4U(const LLColor4U &value, const char *name) = 0;
- virtual bool unpackColor4U(LLColor4U &value, const char *name) = 0;
- bool unpackColor4Us(LLColor4U *values, S32 count, const char *name);
-
- virtual bool packVector2(const LLVector2 &value, const char *name) = 0;
- virtual bool unpackVector2(LLVector2 &value, const char *name) = 0;
-
- virtual bool packVector3(const LLVector3 &value, const char *name) = 0;
- virtual bool unpackVector3(LLVector3 &value, const char *name) = 0;
-
- virtual bool packVector4(const LLVector4 &value, const char *name) = 0;
- virtual bool unpackVector4(LLVector4 &value, const char *name) = 0;
-
- virtual bool packUUID(const LLUUID &value, const char *name) = 0;
- virtual bool unpackUUID(LLUUID &value, const char *name) = 0;
- bool unpackUUIDs(LLUUID *values, S32 count, const char *name);
- U32 getPassFlags() const { return mPassFlags; }
- void setPassFlags(U32 flags) { mPassFlags = flags; }
-protected:
- LLDataPacker();
-protected:
- U32 mPassFlags;
- bool mWriteEnabled; // disable this to do things like determine filesize without actually copying data
-};
-
-class LLDataPackerBinaryBuffer : public LLDataPacker
-{
-public:
- LLDataPackerBinaryBuffer(U8 *bufferp, S32 size)
- : LLDataPacker(),
- mBufferp(bufferp),
- mCurBufferp(bufferp),
- mBufferSize(size)
- {
- mWriteEnabled = true;
- }
-
- LLDataPackerBinaryBuffer()
- : LLDataPacker(),
- mBufferp(NULL),
- mCurBufferp(NULL),
- mBufferSize(0)
- {
- }
-
- /*virtual*/ bool packString(const std::string& value, const char *name);
- /*virtual*/ bool unpackString(std::string& value, const char *name);
-
- /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
-
- // Constant size binary data packing
- /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
-
- /*virtual*/ bool packU8(const U8 value, const char *name);
- /*virtual*/ bool unpackU8(U8 &value, const char *name);
-
- /*virtual*/ bool packU16(const U16 value, const char *name);
- /*virtual*/ bool unpackU16(U16 &value, const char *name);
-
- /*virtual*/ bool packS16(const S16 value, const char *name);
- /*virtual*/ bool unpackS16(S16 &value, const char *name);
-
- /*virtual*/ bool packU32(const U32 value, const char *name);
- /*virtual*/ bool unpackU32(U32 &value, const char *name);
-
- /*virtual*/ bool packS32(const S32 value, const char *name);
- /*virtual*/ bool unpackS32(S32 &value, const char *name);
-
- /*virtual*/ bool packF32(const F32 value, const char *name);
- /*virtual*/ bool unpackF32(F32 &value, const char *name);
-
- /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
- /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
-
- /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
- /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
-
- /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
- /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
-
- /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
- /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
-
- /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
- /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
-
- /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
- /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
-
- S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp); }
- S32 getBufferSize() const { return mBufferSize; }
- const U8* getBuffer() const { return mBufferp; }
- void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); }
- void shift(S32 offset) { reset(); mCurBufferp += offset;}
- void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = false; }
- void assignBuffer(U8 *bufferp, S32 size)
- {
- if(mBufferp && mBufferp != bufferp)
- {
- freeBuffer() ;
- }
- mBufferp = bufferp;
- mCurBufferp = bufferp;
- mBufferSize = size;
- mWriteEnabled = true;
- }
- const LLDataPackerBinaryBuffer& operator=(const LLDataPackerBinaryBuffer &a);
-
- /*virtual*/ bool hasNext() const { return getCurrentSize() < getBufferSize(); }
-
- /*virtual*/ void dumpBufferToLog();
-protected:
- inline bool verifyLength(const S32 data_size, const char *name);
-
- U8 *mBufferp;
- U8 *mCurBufferp;
- S32 mBufferSize;
-};
-
-inline bool LLDataPackerBinaryBuffer::verifyLength(const S32 data_size, const char *name)
-{
- if (mWriteEnabled && (mCurBufferp - mBufferp) > mBufferSize - data_size)
- {
- LL_WARNS() << "Buffer overflow in BinaryBuffer length verify, field name " << name << "!" << LL_ENDL;
- LL_WARNS() << "Current pos: " << (int)(mCurBufferp - mBufferp) << " Buffer size: " << mBufferSize << " Data size: " << data_size << LL_ENDL;
- return false;
- }
-
- return true;
-}
-
-class LLDataPackerAsciiBuffer : public LLDataPacker
-{
-public:
- LLDataPackerAsciiBuffer(char* bufferp, S32 size)
- {
- mBufferp = bufferp;
- mCurBufferp = bufferp;
- mBufferSize = size;
- mPassFlags = 0;
- mIncludeNames = false;
- mWriteEnabled = true;
- }
-
- LLDataPackerAsciiBuffer()
- {
- mBufferp = NULL;
- mCurBufferp = NULL;
- mBufferSize = 0;
- mPassFlags = 0;
- mIncludeNames = false;
- mWriteEnabled = false;
- }
-
- /*virtual*/ bool packString(const std::string& value, const char *name);
- /*virtual*/ bool unpackString(std::string& value, const char *name);
-
- /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
-
- // Constant size binary data packing
- /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
-
- /*virtual*/ bool packU8(const U8 value, const char *name);
- /*virtual*/ bool unpackU8(U8 &value, const char *name);
-
- /*virtual*/ bool packU16(const U16 value, const char *name);
- /*virtual*/ bool unpackU16(U16 &value, const char *name);
-
- /*virtual*/ bool packS16(const S16 value, const char *name);
- /*virtual*/ bool unpackS16(S16 &value, const char *name);
-
- /*virtual*/ bool packU32(const U32 value, const char *name);
- /*virtual*/ bool unpackU32(U32 &value, const char *name);
-
- /*virtual*/ bool packS32(const S32 value, const char *name);
- /*virtual*/ bool unpackS32(S32 &value, const char *name);
-
- /*virtual*/ bool packF32(const F32 value, const char *name);
- /*virtual*/ bool unpackF32(F32 &value, const char *name);
-
- /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
- /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
-
- /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
- /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
-
- /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
- /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
-
- /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
- /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
-
- /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
- /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
-
- /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
- /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
-
- void setIncludeNames(bool b) { mIncludeNames = b; }
-
- // Include the trailing NULL so it's always a valid string
- S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp) + 1; }
-
- S32 getBufferSize() const { return mBufferSize; }
- /*virtual*/ void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); }
-
- /*virtual*/ bool hasNext() const { return getCurrentSize() < getBufferSize(); }
-
- inline void freeBuffer();
- inline void assignBuffer(char* bufferp, S32 size);
- void dump();
-
-protected:
- void writeIndentedName(const char *name);
- bool getValueStr(const char *name, char *out_value, const S32 value_len);
-
-protected:
- inline bool verifyLength(const S32 data_size, const char *name);
-
- char *mBufferp;
- char *mCurBufferp;
- S32 mBufferSize;
- bool mIncludeNames; // useful for debugging, print the name of each field
-};
-
-inline void LLDataPackerAsciiBuffer::freeBuffer()
-{
- delete [] mBufferp;
- mBufferp = mCurBufferp = NULL;
- mBufferSize = 0;
- mWriteEnabled = false;
-}
-
-inline void LLDataPackerAsciiBuffer::assignBuffer(char* bufferp, S32 size)
-{
- mBufferp = bufferp;
- mCurBufferp = bufferp;
- mBufferSize = size;
- mWriteEnabled = true;
-}
-
-inline bool LLDataPackerAsciiBuffer::verifyLength(const S32 data_size, const char *name)
-{
- if (mWriteEnabled && (mCurBufferp - mBufferp) > mBufferSize - data_size)
- {
- LL_WARNS() << "Buffer overflow in AsciiBuffer length verify, field name " << name << "!" << LL_ENDL;
- LL_WARNS() << "Current pos: " << (int)(mCurBufferp - mBufferp) << " Buffer size: " << mBufferSize << " Data size: " << data_size << LL_ENDL;
- return false;
- }
-
- return true;
-}
-
-class LLDataPackerAsciiFile : public LLDataPacker
-{
-public:
- LLDataPackerAsciiFile(LLFILE *fp, const S32 indent = 2)
- : LLDataPacker(),
- mIndent(indent),
- mFP(fp),
- mOutputStream(NULL),
- mInputStream(NULL)
- {
- }
-
- LLDataPackerAsciiFile(std::ostream& output_stream, const S32 indent = 2)
- : LLDataPacker(),
- mIndent(indent),
- mFP(NULL),
- mOutputStream(&output_stream),
- mInputStream(NULL)
- {
- mWriteEnabled = true;
- }
-
- LLDataPackerAsciiFile(std::istream& input_stream, const S32 indent = 2)
- : LLDataPacker(),
- mIndent(indent),
- mFP(NULL),
- mOutputStream(NULL),
- mInputStream(&input_stream)
- {
- }
-
- /*virtual*/ bool packString(const std::string& value, const char *name);
- /*virtual*/ bool unpackString(std::string& value, const char *name);
-
- /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
-
- /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
- /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
-
- /*virtual*/ bool packU8(const U8 value, const char *name);
- /*virtual*/ bool unpackU8(U8 &value, const char *name);
-
- /*virtual*/ bool packU16(const U16 value, const char *name);
- /*virtual*/ bool unpackU16(U16 &value, const char *name);
-
- /*virtual*/ bool packS16(const S16 value, const char *name);
- /*virtual*/ bool unpackS16(S16 &value, const char *name);
-
- /*virtual*/ bool packU32(const U32 value, const char *name);
- /*virtual*/ bool unpackU32(U32 &value, const char *name);
-
- /*virtual*/ bool packS32(const S32 value, const char *name);
- /*virtual*/ bool unpackS32(S32 &value, const char *name);
-
- /*virtual*/ bool packF32(const F32 value, const char *name);
- /*virtual*/ bool unpackF32(F32 &value, const char *name);
-
- /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
- /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
-
- /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
- /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
-
- /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
- /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
-
- /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
- /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
-
- /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
- /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
-
- /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
- /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
-protected:
- void writeIndentedName(const char *name);
- bool getValueStr(const char *name, char *out_value, const S32 value_len);
-
- /*virtual*/ bool hasNext() const { return true; }
-
-protected:
- S32 mIndent;
- LLFILE *mFP;
- std::ostream* mOutputStream;
- std::istream* mInputStream;
-};
-
-#endif // LL_LLDATAPACKER
-
+/**
+ * @file lldatapacker.h
+ * @brief Data packer declaration for tightly storing binary data.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDATAPACKER_H
+#define LL_LLDATAPACKER_H
+
+class LLColor4;
+class LLColor4U;
+class LLVector2;
+class LLVector3;
+class LLVector4;
+class LLUUID;
+
+class LLDataPacker
+{
+public:
+ virtual ~LLDataPacker() {}
+
+ // Not required to override, but error to call?
+ virtual void reset();
+ virtual void dumpBufferToLog();
+
+ virtual bool hasNext() const = 0;
+
+ virtual bool packString(const std::string& value, const char *name) = 0;
+ virtual bool unpackString(std::string& value, const char *name) = 0;
+
+ virtual bool packBinaryData(const U8 *value, S32 size, const char *name) = 0;
+ virtual bool unpackBinaryData(U8 *value, S32 &size, const char *name) = 0;
+
+ // Constant size binary data packing
+ virtual bool packBinaryDataFixed(const U8 *value, S32 size, const char *name) = 0;
+ virtual bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name) = 0;
+
+ virtual bool packU8(const U8 value, const char *name) = 0;
+ virtual bool unpackU8(U8 &value, const char *name) = 0;
+
+ virtual bool packU16(const U16 value, const char *name) = 0;
+ virtual bool unpackU16(U16 &value, const char *name) = 0;
+ bool unpackU16s(U16 *value, S32 count, const char *name);
+
+ virtual bool packS16(const S16 value, const char *name) = 0;
+ virtual bool unpackS16(S16 &value, const char *name) = 0;
+ bool unpackS16s(S16 *value, S32 count, const char *name);
+
+ virtual bool packU32(const U32 value, const char *name) = 0;
+ virtual bool unpackU32(U32 &value, const char *name) = 0;
+
+ virtual bool packS32(const S32 value, const char *name) = 0;
+ virtual bool unpackS32(S32 &value, const char *name) = 0;
+
+ virtual bool packF32(const F32 value, const char *name) = 0;
+ virtual bool unpackF32(F32 &value, const char *name) = 0;
+ bool unpackF32s(F32 *values, S32 count, const char *name);
+
+ // Packs a float into an integer, using the given size
+ // and picks the right U* data type to pack into.
+ bool packFixed(const F32 value, const char *name,
+ const bool is_signed, const U32 int_bits, const U32 frac_bits);
+ bool unpackFixed(F32 &value, const char *name,
+ const bool is_signed, const U32 int_bits, const U32 frac_bits);
+
+ virtual bool packColor4(const LLColor4 &value, const char *name) = 0;
+ virtual bool unpackColor4(LLColor4 &value, const char *name) = 0;
+
+ virtual bool packColor4U(const LLColor4U &value, const char *name) = 0;
+ virtual bool unpackColor4U(LLColor4U &value, const char *name) = 0;
+ bool unpackColor4Us(LLColor4U *values, S32 count, const char *name);
+
+ virtual bool packVector2(const LLVector2 &value, const char *name) = 0;
+ virtual bool unpackVector2(LLVector2 &value, const char *name) = 0;
+
+ virtual bool packVector3(const LLVector3 &value, const char *name) = 0;
+ virtual bool unpackVector3(LLVector3 &value, const char *name) = 0;
+
+ virtual bool packVector4(const LLVector4 &value, const char *name) = 0;
+ virtual bool unpackVector4(LLVector4 &value, const char *name) = 0;
+
+ virtual bool packUUID(const LLUUID &value, const char *name) = 0;
+ virtual bool unpackUUID(LLUUID &value, const char *name) = 0;
+ bool unpackUUIDs(LLUUID *values, S32 count, const char *name);
+ U32 getPassFlags() const { return mPassFlags; }
+ void setPassFlags(U32 flags) { mPassFlags = flags; }
+protected:
+ LLDataPacker();
+protected:
+ U32 mPassFlags;
+ bool mWriteEnabled; // disable this to do things like determine filesize without actually copying data
+};
+
+class LLDataPackerBinaryBuffer : public LLDataPacker
+{
+public:
+ LLDataPackerBinaryBuffer(U8 *bufferp, S32 size)
+ : LLDataPacker(),
+ mBufferp(bufferp),
+ mCurBufferp(bufferp),
+ mBufferSize(size)
+ {
+ mWriteEnabled = true;
+ }
+
+ LLDataPackerBinaryBuffer()
+ : LLDataPacker(),
+ mBufferp(NULL),
+ mCurBufferp(NULL),
+ mBufferSize(0)
+ {
+ }
+
+ /*virtual*/ bool packString(const std::string& value, const char *name);
+ /*virtual*/ bool unpackString(std::string& value, const char *name);
+
+ /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+
+ // Constant size binary data packing
+ /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
+
+ /*virtual*/ bool packU8(const U8 value, const char *name);
+ /*virtual*/ bool unpackU8(U8 &value, const char *name);
+
+ /*virtual*/ bool packU16(const U16 value, const char *name);
+ /*virtual*/ bool unpackU16(U16 &value, const char *name);
+
+ /*virtual*/ bool packS16(const S16 value, const char *name);
+ /*virtual*/ bool unpackS16(S16 &value, const char *name);
+
+ /*virtual*/ bool packU32(const U32 value, const char *name);
+ /*virtual*/ bool unpackU32(U32 &value, const char *name);
+
+ /*virtual*/ bool packS32(const S32 value, const char *name);
+ /*virtual*/ bool unpackS32(S32 &value, const char *name);
+
+ /*virtual*/ bool packF32(const F32 value, const char *name);
+ /*virtual*/ bool unpackF32(F32 &value, const char *name);
+
+ /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
+ /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
+
+ /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
+ /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
+
+ /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
+ /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
+
+ /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
+ /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
+
+ /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
+ /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
+
+ /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
+ /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
+
+ S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp); }
+ S32 getBufferSize() const { return mBufferSize; }
+ const U8* getBuffer() const { return mBufferp; }
+ void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); }
+ void shift(S32 offset) { reset(); mCurBufferp += offset;}
+ void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = false; }
+ void assignBuffer(U8 *bufferp, S32 size)
+ {
+ if(mBufferp && mBufferp != bufferp)
+ {
+ freeBuffer() ;
+ }
+ mBufferp = bufferp;
+ mCurBufferp = bufferp;
+ mBufferSize = size;
+ mWriteEnabled = true;
+ }
+ const LLDataPackerBinaryBuffer& operator=(const LLDataPackerBinaryBuffer &a);
+
+ /*virtual*/ bool hasNext() const { return getCurrentSize() < getBufferSize(); }
+
+ /*virtual*/ void dumpBufferToLog();
+protected:
+ inline bool verifyLength(const S32 data_size, const char *name);
+
+ U8 *mBufferp;
+ U8 *mCurBufferp;
+ S32 mBufferSize;
+};
+
+inline bool LLDataPackerBinaryBuffer::verifyLength(const S32 data_size, const char *name)
+{
+ if (mWriteEnabled && (mCurBufferp - mBufferp) > mBufferSize - data_size)
+ {
+ LL_WARNS() << "Buffer overflow in BinaryBuffer length verify, field name " << name << "!" << LL_ENDL;
+ LL_WARNS() << "Current pos: " << (int)(mCurBufferp - mBufferp) << " Buffer size: " << mBufferSize << " Data size: " << data_size << LL_ENDL;
+ return false;
+ }
+
+ return true;
+}
+
+class LLDataPackerAsciiBuffer : public LLDataPacker
+{
+public:
+ LLDataPackerAsciiBuffer(char* bufferp, S32 size)
+ {
+ mBufferp = bufferp;
+ mCurBufferp = bufferp;
+ mBufferSize = size;
+ mPassFlags = 0;
+ mIncludeNames = false;
+ mWriteEnabled = true;
+ }
+
+ LLDataPackerAsciiBuffer()
+ {
+ mBufferp = NULL;
+ mCurBufferp = NULL;
+ mBufferSize = 0;
+ mPassFlags = 0;
+ mIncludeNames = false;
+ mWriteEnabled = false;
+ }
+
+ /*virtual*/ bool packString(const std::string& value, const char *name);
+ /*virtual*/ bool unpackString(std::string& value, const char *name);
+
+ /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+
+ // Constant size binary data packing
+ /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
+
+ /*virtual*/ bool packU8(const U8 value, const char *name);
+ /*virtual*/ bool unpackU8(U8 &value, const char *name);
+
+ /*virtual*/ bool packU16(const U16 value, const char *name);
+ /*virtual*/ bool unpackU16(U16 &value, const char *name);
+
+ /*virtual*/ bool packS16(const S16 value, const char *name);
+ /*virtual*/ bool unpackS16(S16 &value, const char *name);
+
+ /*virtual*/ bool packU32(const U32 value, const char *name);
+ /*virtual*/ bool unpackU32(U32 &value, const char *name);
+
+ /*virtual*/ bool packS32(const S32 value, const char *name);
+ /*virtual*/ bool unpackS32(S32 &value, const char *name);
+
+ /*virtual*/ bool packF32(const F32 value, const char *name);
+ /*virtual*/ bool unpackF32(F32 &value, const char *name);
+
+ /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
+ /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
+
+ /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
+ /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
+
+ /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
+ /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
+
+ /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
+ /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
+
+ /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
+ /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
+
+ /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
+ /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
+
+ void setIncludeNames(bool b) { mIncludeNames = b; }
+
+ // Include the trailing NULL so it's always a valid string
+ S32 getCurrentSize() const { return (S32)(mCurBufferp - mBufferp) + 1; }
+
+ S32 getBufferSize() const { return mBufferSize; }
+ /*virtual*/ void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); }
+
+ /*virtual*/ bool hasNext() const { return getCurrentSize() < getBufferSize(); }
+
+ inline void freeBuffer();
+ inline void assignBuffer(char* bufferp, S32 size);
+ void dump();
+
+protected:
+ void writeIndentedName(const char *name);
+ bool getValueStr(const char *name, char *out_value, const S32 value_len);
+
+protected:
+ inline bool verifyLength(const S32 data_size, const char *name);
+
+ char *mBufferp;
+ char *mCurBufferp;
+ S32 mBufferSize;
+ bool mIncludeNames; // useful for debugging, print the name of each field
+};
+
+inline void LLDataPackerAsciiBuffer::freeBuffer()
+{
+ delete [] mBufferp;
+ mBufferp = mCurBufferp = NULL;
+ mBufferSize = 0;
+ mWriteEnabled = false;
+}
+
+inline void LLDataPackerAsciiBuffer::assignBuffer(char* bufferp, S32 size)
+{
+ mBufferp = bufferp;
+ mCurBufferp = bufferp;
+ mBufferSize = size;
+ mWriteEnabled = true;
+}
+
+inline bool LLDataPackerAsciiBuffer::verifyLength(const S32 data_size, const char *name)
+{
+ if (mWriteEnabled && (mCurBufferp - mBufferp) > mBufferSize - data_size)
+ {
+ LL_WARNS() << "Buffer overflow in AsciiBuffer length verify, field name " << name << "!" << LL_ENDL;
+ LL_WARNS() << "Current pos: " << (int)(mCurBufferp - mBufferp) << " Buffer size: " << mBufferSize << " Data size: " << data_size << LL_ENDL;
+ return false;
+ }
+
+ return true;
+}
+
+class LLDataPackerAsciiFile : public LLDataPacker
+{
+public:
+ LLDataPackerAsciiFile(LLFILE *fp, const S32 indent = 2)
+ : LLDataPacker(),
+ mIndent(indent),
+ mFP(fp),
+ mOutputStream(NULL),
+ mInputStream(NULL)
+ {
+ }
+
+ LLDataPackerAsciiFile(std::ostream& output_stream, const S32 indent = 2)
+ : LLDataPacker(),
+ mIndent(indent),
+ mFP(NULL),
+ mOutputStream(&output_stream),
+ mInputStream(NULL)
+ {
+ mWriteEnabled = true;
+ }
+
+ LLDataPackerAsciiFile(std::istream& input_stream, const S32 indent = 2)
+ : LLDataPacker(),
+ mIndent(indent),
+ mFP(NULL),
+ mOutputStream(NULL),
+ mInputStream(&input_stream)
+ {
+ }
+
+ /*virtual*/ bool packString(const std::string& value, const char *name);
+ /*virtual*/ bool unpackString(std::string& value, const char *name);
+
+ /*virtual*/ bool packBinaryData(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryData(U8 *value, S32 &size, const char *name);
+
+ /*virtual*/ bool packBinaryDataFixed(const U8 *value, S32 size, const char *name);
+ /*virtual*/ bool unpackBinaryDataFixed(U8 *value, S32 size, const char *name);
+
+ /*virtual*/ bool packU8(const U8 value, const char *name);
+ /*virtual*/ bool unpackU8(U8 &value, const char *name);
+
+ /*virtual*/ bool packU16(const U16 value, const char *name);
+ /*virtual*/ bool unpackU16(U16 &value, const char *name);
+
+ /*virtual*/ bool packS16(const S16 value, const char *name);
+ /*virtual*/ bool unpackS16(S16 &value, const char *name);
+
+ /*virtual*/ bool packU32(const U32 value, const char *name);
+ /*virtual*/ bool unpackU32(U32 &value, const char *name);
+
+ /*virtual*/ bool packS32(const S32 value, const char *name);
+ /*virtual*/ bool unpackS32(S32 &value, const char *name);
+
+ /*virtual*/ bool packF32(const F32 value, const char *name);
+ /*virtual*/ bool unpackF32(F32 &value, const char *name);
+
+ /*virtual*/ bool packColor4(const LLColor4 &value, const char *name);
+ /*virtual*/ bool unpackColor4(LLColor4 &value, const char *name);
+
+ /*virtual*/ bool packColor4U(const LLColor4U &value, const char *name);
+ /*virtual*/ bool unpackColor4U(LLColor4U &value, const char *name);
+
+ /*virtual*/ bool packVector2(const LLVector2 &value, const char *name);
+ /*virtual*/ bool unpackVector2(LLVector2 &value, const char *name);
+
+ /*virtual*/ bool packVector3(const LLVector3 &value, const char *name);
+ /*virtual*/ bool unpackVector3(LLVector3 &value, const char *name);
+
+ /*virtual*/ bool packVector4(const LLVector4 &value, const char *name);
+ /*virtual*/ bool unpackVector4(LLVector4 &value, const char *name);
+
+ /*virtual*/ bool packUUID(const LLUUID &value, const char *name);
+ /*virtual*/ bool unpackUUID(LLUUID &value, const char *name);
+protected:
+ void writeIndentedName(const char *name);
+ bool getValueStr(const char *name, char *out_value, const S32 value_len);
+
+ /*virtual*/ bool hasNext() const { return true; }
+
+protected:
+ S32 mIndent;
+ LLFILE *mFP;
+ std::ostream* mOutputStream;
+ std::istream* mInputStream;
+};
+
+#endif // LL_LLDATAPACKER
+
diff --git a/indra/llmessage/lldbstrings.h b/indra/llmessage/lldbstrings.h
index e23d17d5b6..cca407b03d 100644
--- a/indra/llmessage/lldbstrings.h
+++ b/indra/llmessage/lldbstrings.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldbstrings.h
* @brief Database String Lengths.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,25 +32,25 @@
* the size of the buffer large enough to hold each one)
*/
-// asset.name varchar(63)
+// asset.name varchar(63)
// -also-
-// user_inventory_item.name varchar(63)
+// user_inventory_item.name varchar(63)
// -also-
-// user_inventory_folder.name varchar(63) was CAT_NAME_SIZE
+// user_inventory_folder.name varchar(63) was CAT_NAME_SIZE
// Must be >= DB_FULL_NAME_STR_LEN so that calling cards work
-const S32 DB_INV_ITEM_NAME_STR_LEN = 63; // was MAX_ASSET_NAME_LENGTH
-const S32 DB_INV_ITEM_NAME_BUF_SIZE = 64; // was ITEM_NAME_SIZE
+const S32 DB_INV_ITEM_NAME_STR_LEN = 63; // was MAX_ASSET_NAME_LENGTH
+const S32 DB_INV_ITEM_NAME_BUF_SIZE = 64; // was ITEM_NAME_SIZE
-// asset.description varchar(127)
+// asset.description varchar(127)
// -also-
-// user_inventory_item.description varchar(127)
-const S32 DB_INV_ITEM_DESC_STR_LEN = 127; // was MAX_ASSET_DESCRIPTION_LENGTH
-const S32 DB_INV_ITEM_DESC_BUF_SIZE = 128; // was ITEM_DESC_SIZE
+// user_inventory_item.description varchar(127)
+const S32 DB_INV_ITEM_DESC_STR_LEN = 127; // was MAX_ASSET_DESCRIPTION_LENGTH
+const S32 DB_INV_ITEM_DESC_BUF_SIZE = 128; // was ITEM_DESC_SIZE
-// groups.name varchar(35)
-const S32 DB_GROUP_NAME_STR_LEN = 35;
-const S32 DB_GROUP_NAME_BUF_SIZE = 36;
-const S32 DB_GROUP_NAME_MIN_LEN = 4;
+// groups.name varchar(35)
+const S32 DB_GROUP_NAME_STR_LEN = 35;
+const S32 DB_GROUP_NAME_BUF_SIZE = 36;
+const S32 DB_GROUP_NAME_MIN_LEN = 4;
//group_roles.name
const U32 DB_GROUP_ROLE_NAME_STR_LEN = 20;
@@ -61,154 +61,154 @@ const U32 DB_GROUP_ROLE_TITLE_STR_LEN = 20;
const U32 DB_GROUP_ROLE_TITLE_BUF_SIZE = DB_GROUP_ROLE_TITLE_STR_LEN + 1;
-// group.charter text
-const S32 DB_GROUP_CHARTER_STR_LEN = 511;
-const S32 DB_GROUP_CHARTER_BUF_SIZE = 512;
+// group.charter text
+const S32 DB_GROUP_CHARTER_STR_LEN = 511;
+const S32 DB_GROUP_CHARTER_BUF_SIZE = 512;
-// group.officer_title varchar(20)
+// group.officer_title varchar(20)
// -also-
-// group.member_title varchar(20)
-const S32 DB_GROUP_TITLE_STR_LEN = 20;
-const S32 DB_GROUP_TITLE_BUF_SIZE = 21;
+// group.member_title varchar(20)
+const S32 DB_GROUP_TITLE_STR_LEN = 20;
+const S32 DB_GROUP_TITLE_BUF_SIZE = 21;
// Since chat and im both dump into the database text message log,
// they derive their max size from the same constant.
const S32 MAX_MSG_STR_LEN = 1023;
const S32 MAX_MSG_BUF_SIZE = 1024;
-// instant_message.message text
-const S32 DB_IM_MSG_STR_LEN = MAX_MSG_STR_LEN;
-const S32 DB_IM_MSG_BUF_SIZE = MAX_MSG_BUF_SIZE;
+// instant_message.message text
+const S32 DB_IM_MSG_STR_LEN = MAX_MSG_STR_LEN;
+const S32 DB_IM_MSG_BUF_SIZE = MAX_MSG_BUF_SIZE;
// groupnotices
-const S32 DB_GROUP_NOTICE_SUBJ_STR_LEN = 63;
-const S32 DB_GROUP_NOTICE_SUBJ_STR_SIZE = 64;
-const S32 DB_GROUP_NOTICE_MSG_STR_LEN = MAX_MSG_STR_LEN - DB_GROUP_NOTICE_SUBJ_STR_LEN;
-const S32 DB_GROUP_NOTICE_MSG_STR_SIZE = MAX_MSG_BUF_SIZE - DB_GROUP_NOTICE_SUBJ_STR_SIZE;
-
-// log_text_message.message text
-const S32 DB_CHAT_MSG_STR_LEN = MAX_MSG_STR_LEN;
-const S32 DB_CHAT_MSG_BUF_SIZE = MAX_MSG_BUF_SIZE;
-
-// money_stipend.description varchar(254)
-const S32 DB_STIPEND_DESC_STR_LEN = 254;
-const S32 DB_STIPEND_DESC_BUF_SIZE = 255;
-
-// script_email_message.from_email varchar(78)
-const S32 DB_EMAIL_FROM_STR_LEN = 78;
-const S32 DB_EMAIL_FROM_BUF_SIZE = 79;
-
-// script_email_message.subject varchar(72)
-const S32 DB_EMAIL_SUBJECT_STR_LEN = 72;
-const S32 DB_EMAIL_SUBJECT_BUF_SIZE = 73;
-
-// system_globals.motd varchar(254)
-const S32 DB_MOTD_STR_LEN = 254;
-const S32 DB_MOTD_BUF_SIZE = 255;
-
-// Must be <= user_inventory_item.name so that calling cards work
+const S32 DB_GROUP_NOTICE_SUBJ_STR_LEN = 63;
+const S32 DB_GROUP_NOTICE_SUBJ_STR_SIZE = 64;
+const S32 DB_GROUP_NOTICE_MSG_STR_LEN = MAX_MSG_STR_LEN - DB_GROUP_NOTICE_SUBJ_STR_LEN;
+const S32 DB_GROUP_NOTICE_MSG_STR_SIZE = MAX_MSG_BUF_SIZE - DB_GROUP_NOTICE_SUBJ_STR_SIZE;
+
+// log_text_message.message text
+const S32 DB_CHAT_MSG_STR_LEN = MAX_MSG_STR_LEN;
+const S32 DB_CHAT_MSG_BUF_SIZE = MAX_MSG_BUF_SIZE;
+
+// money_stipend.description varchar(254)
+const S32 DB_STIPEND_DESC_STR_LEN = 254;
+const S32 DB_STIPEND_DESC_BUF_SIZE = 255;
+
+// script_email_message.from_email varchar(78)
+const S32 DB_EMAIL_FROM_STR_LEN = 78;
+const S32 DB_EMAIL_FROM_BUF_SIZE = 79;
+
+// script_email_message.subject varchar(72)
+const S32 DB_EMAIL_SUBJECT_STR_LEN = 72;
+const S32 DB_EMAIL_SUBJECT_BUF_SIZE = 73;
+
+// system_globals.motd varchar(254)
+const S32 DB_MOTD_STR_LEN = 254;
+const S32 DB_MOTD_BUF_SIZE = 255;
+
+// Must be <= user_inventory_item.name so that calling cards work
// First name + " " + last name...or a system assigned "from" name
-// instant_message.from_agent_name varchar(63)
+// instant_message.from_agent_name varchar(63)
// -also-
-// user_mute.mute_agent_name varchar(63)
-const S32 DB_FULL_NAME_STR_LEN = 63;
-const S32 DB_FULL_NAME_BUF_SIZE = 64; // was USER_NAME_SIZE
+// user_mute.mute_agent_name varchar(63)
+const S32 DB_FULL_NAME_STR_LEN = 63;
+const S32 DB_FULL_NAME_BUF_SIZE = 64; // was USER_NAME_SIZE
-// user.username varchar(31)
-const S32 DB_FIRST_NAME_STR_LEN = 31;
-const S32 DB_FIRST_NAME_BUF_SIZE = 32; // was MAX_FIRST_NAME
+// user.username varchar(31)
+const S32 DB_FIRST_NAME_STR_LEN = 31;
+const S32 DB_FIRST_NAME_BUF_SIZE = 32; // was MAX_FIRST_NAME
-// user_last_name.name varchar(31)
-const S32 DB_LAST_NAME_STR_LEN = 31;
-const S32 DB_LAST_NAME_BUF_SIZE = 32; // was MAX_LAST_NAME
+// user_last_name.name varchar(31)
+const S32 DB_LAST_NAME_STR_LEN = 31;
+const S32 DB_LAST_NAME_BUF_SIZE = 32; // was MAX_LAST_NAME
-// user.password varchar(100)
-const S32 DB_USER_PASSWORD_STR_LEN = 100;
-const S32 DB_USER_PASSWORD_BUF_SIZE = 101; // was MAX_PASSWORD
+// user.password varchar(100)
+const S32 DB_USER_PASSWORD_STR_LEN = 100;
+const S32 DB_USER_PASSWORD_BUF_SIZE = 101; // was MAX_PASSWORD
-// user.email varchar(254)
-const S32 DB_USER_EMAIL_ADDR_STR_LEN = 254;
-const S32 DB_USER_EMAIL_ADDR_BUF_SIZE = 255;
+// user.email varchar(254)
+const S32 DB_USER_EMAIL_ADDR_STR_LEN = 254;
+const S32 DB_USER_EMAIL_ADDR_BUF_SIZE = 255;
-// user.about text
-const S32 DB_USER_ABOUT_STR_LEN = 511;
-const S32 DB_USER_ABOUT_BUF_SIZE = 512;
+// user.about text
+const S32 DB_USER_ABOUT_STR_LEN = 511;
+const S32 DB_USER_ABOUT_BUF_SIZE = 512;
-// user.fl_about_text text
+// user.fl_about_text text
// Must be 255 not 256 as gets packed into message Variable 1
-const S32 DB_USER_FL_ABOUT_STR_LEN = 254;
-const S32 DB_USER_FL_ABOUT_BUF_SIZE = 255;
+const S32 DB_USER_FL_ABOUT_STR_LEN = 254;
+const S32 DB_USER_FL_ABOUT_BUF_SIZE = 255;
-// user.profile_url text
+// user.profile_url text
// Must be 255 not 256 as gets packed into message Variable 1
-const S32 DB_USER_PROFILE_URL_STR_LEN = 254;
-const S32 DB_USER_PROFILE_URL_BUF_SIZE = 255;
+const S32 DB_USER_PROFILE_URL_STR_LEN = 254;
+const S32 DB_USER_PROFILE_URL_BUF_SIZE = 255;
-// user.want_to varchar(254)
-const S32 DB_USER_WANT_TO_STR_LEN = 254;
-const S32 DB_USER_WANT_TO_BUF_SIZE = 255;
+// user.want_to varchar(254)
+const S32 DB_USER_WANT_TO_STR_LEN = 254;
+const S32 DB_USER_WANT_TO_BUF_SIZE = 255;
-// user.skills varchar(254)
-const S32 DB_USER_SKILLS_STR_LEN = 254;
-const S32 DB_USER_SKILLS_BUF_SIZE = 255;
+// user.skills varchar(254)
+const S32 DB_USER_SKILLS_STR_LEN = 254;
+const S32 DB_USER_SKILLS_BUF_SIZE = 255;
-// user_nv.name varchar(128)
-const S32 DB_NV_NAME_STR_LEN = 128;
-const S32 DB_NV_NAME_BUF_SIZE = 129;
+// user_nv.name varchar(128)
+const S32 DB_NV_NAME_STR_LEN = 128;
+const S32 DB_NV_NAME_BUF_SIZE = 129;
-// user_start_location.location_name varchar(254)
-const S32 DB_START_LOCATION_STR_LEN = 254;
-const S32 DB_START_LOCATION_BUF_SIZE = 255;
+// user_start_location.location_name varchar(254)
+const S32 DB_START_LOCATION_STR_LEN = 254;
+const S32 DB_START_LOCATION_BUF_SIZE = 255;
-// money_tax_assessment.sim varchar(100)
-//const S32 DB_SIM_NAME_STR_LEN = 100;
-//const S32 DB_SIM_NAME_BUF_SIZE = 101;
+// money_tax_assessment.sim varchar(100)
+//const S32 DB_SIM_NAME_STR_LEN = 100;
+//const S32 DB_SIM_NAME_BUF_SIZE = 101;
-// born on date date
-const S32 DB_BORN_STR_LEN = 15;
-const S32 DB_BORN_BUF_SIZE = 16;
+// born on date date
+const S32 DB_BORN_STR_LEN = 15;
+const S32 DB_BORN_BUF_SIZE = 16;
// place.name
-const S32 DB_PLACE_NAME_LEN = 63;
-const S32 DB_PLACE_NAME_SIZE = 64;
-const S32 DB_PARCEL_NAME_LEN = 63;
-const S32 DB_PARCEL_NAME_SIZE = 64;
+const S32 DB_PLACE_NAME_LEN = 63;
+const S32 DB_PLACE_NAME_SIZE = 64;
+const S32 DB_PARCEL_NAME_LEN = 63;
+const S32 DB_PARCEL_NAME_SIZE = 64;
// place.desc
-const S32 DB_PLACE_DESC_LEN = 255;
-const S32 DB_PLACE_DESC_SIZE = 256;
-const S32 DB_PARCEL_DESC_LEN = 255;
-const S32 DB_PARCEL_DESC_SIZE = 256;
-const S32 DB_PARCEL_MUSIC_URL_LEN = 255;
-const S32 DB_PARCEL_MEDIA_URL_LEN = 255;
-const S32 DB_PARCEL_MUSIC_URL_SIZE = 256;
+const S32 DB_PLACE_DESC_LEN = 255;
+const S32 DB_PLACE_DESC_SIZE = 256;
+const S32 DB_PARCEL_DESC_LEN = 255;
+const S32 DB_PARCEL_DESC_SIZE = 256;
+const S32 DB_PARCEL_MUSIC_URL_LEN = 255;
+const S32 DB_PARCEL_MEDIA_URL_LEN = 255;
+const S32 DB_PARCEL_MUSIC_URL_SIZE = 256;
// date time that is easily human readable
-const S32 DB_DATETIME_STR_LEN = 35;
-const S32 DB_DATETIME_BUF_SIZE = 36;
+const S32 DB_DATETIME_STR_LEN = 35;
+const S32 DB_DATETIME_BUF_SIZE = 36;
// date time that isn't easily human readable
-const S32 DB_TERSE_DATETIME_STR_LEN = 15;
-const S32 DB_TERSE_DATETIME_BUF_SIZE = 16;
+const S32 DB_TERSE_DATETIME_STR_LEN = 15;
+const S32 DB_TERSE_DATETIME_BUF_SIZE = 16;
// indra.simulator constants
-const S32 DB_SIM_NAME_STR_LEN = 35;
-const S32 DB_SIM_NAME_BUF_SIZE = 36;
-const S32 DB_HOST_NAME_STR_LEN = 100;
-const S32 DB_HOST_NAME_BUF_SIZE = 101;
-const S32 DB_ESTATE_NAME_STR_LEN = 63;
-const S32 DB_ESTATE_NAME_BUF_SIZE = DB_ESTATE_NAME_STR_LEN + 1;
+const S32 DB_SIM_NAME_STR_LEN = 35;
+const S32 DB_SIM_NAME_BUF_SIZE = 36;
+const S32 DB_HOST_NAME_STR_LEN = 100;
+const S32 DB_HOST_NAME_BUF_SIZE = 101;
+const S32 DB_ESTATE_NAME_STR_LEN = 63;
+const S32 DB_ESTATE_NAME_BUF_SIZE = DB_ESTATE_NAME_STR_LEN + 1;
// user_note.note
-const S32 DB_USER_NOTE_LEN = 1023;
-const S32 DB_USER_NOTE_SIZE = 1024;
+const S32 DB_USER_NOTE_LEN = 1023;
+const S32 DB_USER_NOTE_SIZE = 1024;
// pick.name
-const S32 DB_PICK_NAME_LEN = 63;
-const S32 DB_PICK_NAME_SIZE = 64;
+const S32 DB_PICK_NAME_LEN = 63;
+const S32 DB_PICK_NAME_SIZE = 64;
// pick.desc
-const S32 DB_PICK_DESC_LEN = 1023;
-const S32 DB_PICK_DESC_SIZE = 1024;
+const S32 DB_PICK_DESC_LEN = 1023;
+const S32 DB_PICK_DESC_SIZE = 1024;
#endif // LL_LLDBSTRINGS_H
diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp
index 717ef10f70..f02a5fd37f 100644
--- a/indra/llmessage/lldispatcher.cpp
+++ b/indra/llmessage/lldispatcher.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldispatcher.cpp
* @brief Implementation of the dispatcher object.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -48,55 +48,55 @@ LLDispatcher::~LLDispatcher()
bool LLDispatcher::isHandlerPresent(const key_t& name) const
{
- if(mHandlers.find(name) != mHandlers.end())
- {
- return true;
- }
- return false;
+ if(mHandlers.find(name) != mHandlers.end())
+ {
+ return true;
+ }
+ return false;
}
void LLDispatcher::copyAllHandlerNames(keys_t& names) const
{
- // copy the names onto the vector we are given
- std::transform(
- mHandlers.begin(),
- mHandlers.end(),
- std::back_insert_iterator<keys_t>(names),
- llselect1st<dispatch_map_t::value_type>());
+ // copy the names onto the vector we are given
+ std::transform(
+ mHandlers.begin(),
+ mHandlers.end(),
+ std::back_insert_iterator<keys_t>(names),
+ llselect1st<dispatch_map_t::value_type>());
}
bool LLDispatcher::dispatch(
- const key_t& name,
- const LLUUID& invoice,
- const sparam_t& strings) const
+ const key_t& name,
+ const LLUUID& invoice,
+ const sparam_t& strings) const
{
- dispatch_map_t::const_iterator it = mHandlers.find(name);
- if(it != mHandlers.end())
- {
- LLDispatchHandler* func = (*it).second;
- return (*func)(this, name, invoice, strings);
- }
- LL_WARNS() << "Unable to find handler for Generic message: " << name << LL_ENDL;
- return false;
+ dispatch_map_t::const_iterator it = mHandlers.find(name);
+ if(it != mHandlers.end())
+ {
+ LLDispatchHandler* func = (*it).second;
+ return (*func)(this, name, invoice, strings);
+ }
+ LL_WARNS() << "Unable to find handler for Generic message: " << name << LL_ENDL;
+ return false;
}
LLDispatchHandler* LLDispatcher::addHandler(
- const key_t& name, LLDispatchHandler* func)
+ const key_t& name, LLDispatchHandler* func)
{
- dispatch_map_t::iterator it = mHandlers.find(name);
- LLDispatchHandler* old_handler = NULL;
- if(it != mHandlers.end())
- {
- old_handler = (*it).second;
- mHandlers.erase(it);
- }
- if(func)
- {
- // only non-null handlers so that we don't have to worry about
- // it later.
- mHandlers.insert(dispatch_map_t::value_type(name, func));
- }
- return old_handler;
+ dispatch_map_t::iterator it = mHandlers.find(name);
+ LLDispatchHandler* old_handler = NULL;
+ if(it != mHandlers.end())
+ {
+ old_handler = (*it).second;
+ mHandlers.erase(it);
+ }
+ if(func)
+ {
+ // only non-null handlers so that we don't have to worry about
+ // it later.
+ mHandlers.insert(dispatch_map_t::value_type(name, func));
+ }
+ return old_handler;
}
// static
@@ -106,14 +106,14 @@ bool LLDispatcher::unpackMessage(
LLUUID& invoice,
LLDispatcher::sparam_t& parameters)
{
- char buf[MAX_STRING]; /*Flawfinder: ignore*/
+ char buf[MAX_STRING]; /*Flawfinder: ignore*/
msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
S32 size;
S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
for (S32 i = 0; i < count; ++i)
{
- // we treat the SParam as binary data (since it might be an
+ // we treat the SParam as binary data (since it might be an
// LLUUID in compressed form which may have embedded \0's,)
size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
if (size >= 0)
@@ -137,7 +137,7 @@ bool LLDispatcher::unpackMessage(
}
else
{
- // This is either a NULL string, or a string that was packed
+ // This is either a NULL string, or a string that was packed
// incorrectly as binary data, without the usual trailing '\0'.
std::string string_data(buf, size);
parameters.push_back(string_data);
@@ -160,7 +160,7 @@ bool LLDispatcher::unpackLargeMessage(
for (S32 i = 0; i < count; ++i)
{
// This method treats all Parameter List params as strings and unpacks
- // them regardless of length. If there is binary data it is the callers
+ // them regardless of length. If there is binary data it is the callers
// responsibility to decode it.
std::string param;
msg->getStringFast(_PREHASH_ParamList, _PREHASH_Parameter, param, i);
diff --git a/indra/llmessage/lldispatcher.h b/indra/llmessage/lldispatcher.h
index 43c63ac4df..87b029b8a4 100644
--- a/indra/llmessage/lldispatcher.h
+++ b/indra/llmessage/lldispatcher.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lldispatcher.h
* @brief LLDispatcher class header file.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -46,16 +46,16 @@ class LLUUID;
class LLDispatchHandler
{
public:
- typedef std::vector<std::string> sparam_t;
- //typedef std::vector<S32> iparam_t;
- LLDispatchHandler() {}
- virtual ~LLDispatchHandler() {}
- virtual bool operator()(
- const LLDispatcher* dispatcher,
- const std::string& key,
- const LLUUID& invoice,
- const sparam_t& string) = 0;
- //const iparam_t& integers) = 0;
+ typedef std::vector<std::string> sparam_t;
+ //typedef std::vector<S32> iparam_t;
+ LLDispatchHandler() {}
+ virtual ~LLDispatchHandler() {}
+ virtual bool operator()(
+ const LLDispatcher* dispatcher,
+ const std::string& key,
+ const LLUUID& invoice,
+ const sparam_t& string) = 0;
+ //const iparam_t& integers) = 0;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -67,43 +67,43 @@ public:
class LLDispatcher
{
public:
- typedef std::string key_t;
- typedef std::vector<std::string> keys_t;
- typedef std::vector<std::string> sparam_t;
- //typedef std::vector<S32> iparam_t;
+ typedef std::string key_t;
+ typedef std::vector<std::string> keys_t;
+ typedef std::vector<std::string> sparam_t;
+ //typedef std::vector<S32> iparam_t;
- // construct a dispatcher.
- LLDispatcher();
- virtual ~LLDispatcher();
+ // construct a dispatcher.
+ LLDispatcher();
+ virtual ~LLDispatcher();
- // Returns if they keyed handler exists in this dispatcher.
- bool isHandlerPresent(const key_t& name) const;
+ // Returns if they keyed handler exists in this dispatcher.
+ bool isHandlerPresent(const key_t& name) const;
- // copy all known keys onto keys_t structure
- void copyAllHandlerNames(keys_t& names) const;
+ // copy all known keys onto keys_t structure
+ void copyAllHandlerNames(keys_t& names) const;
- // Call this method with the name of the request that has come
- // in. If the handler is present, it is called with the params and
- // returns the return value from
- bool dispatch(
- const key_t& name,
- const LLUUID& invoice,
- const sparam_t& strings) const;
- //const iparam_t& itegers) const;
+ // Call this method with the name of the request that has come
+ // in. If the handler is present, it is called with the params and
+ // returns the return value from
+ bool dispatch(
+ const key_t& name,
+ const LLUUID& invoice,
+ const sparam_t& strings) const;
+ //const iparam_t& itegers) const;
- // Add a handler. If one with the same key already exists, its
- // pointer is returned, otherwise returns NULL. This object does
- // not do memory management of the LLDispatchHandler, and relies
- // on the caller to delete the object if necessary.
- LLDispatchHandler* addHandler(const key_t& name, LLDispatchHandler* func);
+ // Add a handler. If one with the same key already exists, its
+ // pointer is returned, otherwise returns NULL. This object does
+ // not do memory management of the LLDispatchHandler, and relies
+ // on the caller to delete the object if necessary.
+ LLDispatchHandler* addHandler(const key_t& name, LLDispatchHandler* func);
- // Helper method to unpack the dispatcher message bus
- // format. Returns true on success.
- static bool unpackMessage(
- LLMessageSystem* msg,
- key_t& method,
- LLUUID& invoice,
- sparam_t& parameters);
+ // Helper method to unpack the dispatcher message bus
+ // format. Returns true on success.
+ static bool unpackMessage(
+ LLMessageSystem* msg,
+ key_t& method,
+ LLUUID& invoice,
+ sparam_t& parameters);
static bool unpackLargeMessage(
LLMessageSystem* msg,
@@ -112,8 +112,8 @@ public:
sparam_t& parameters);
protected:
- typedef std::map<key_t, LLDispatchHandler*> dispatch_map_t;
- dispatch_map_t mHandlers;
+ typedef std::map<key_t, LLDispatchHandler*> dispatch_map_t;
+ dispatch_map_t mHandlers;
};
#endif // LL_LLDISPATCHER_H
diff --git a/indra/llmessage/lleventflags.h b/indra/llmessage/lleventflags.h
index 75d79071b1..e1b0f9f460 100644
--- a/indra/llmessage/lleventflags.h
+++ b/indra/llmessage/lleventflags.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lleventflags.h
* @brief Flags for events.
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index db22ad2ea3..b5d0c93376 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llexperiencecache.cpp
* @brief llexperiencecache and related class definitions
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,7 +40,7 @@
//=========================================================================
namespace LLExperienceCacheImpl
{
- void mapKeys(const LLSD& legacyKeys);
+ void mapKeys(const LLSD& legacyKeys);
F64 getErrorRetryDeltaTime(S32 status, LLSD headers);
bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age);
@@ -57,32 +57,32 @@ namespace LLExperienceCacheImpl
}
//=========================================================================
-const std::string LLExperienceCache::PRIVATE_KEY = "private_id";
-const std::string LLExperienceCache::MISSING = "DoesNotExist";
+const std::string LLExperienceCache::PRIVATE_KEY = "private_id";
+const std::string LLExperienceCache::MISSING = "DoesNotExist";
const std::string LLExperienceCache::AGENT_ID = "agent_id";
const std::string LLExperienceCache::GROUP_ID = "group_id";
-const std::string LLExperienceCache::EXPERIENCE_ID = "public_id";
-const std::string LLExperienceCache::NAME = "name";
-const std::string LLExperienceCache::PROPERTIES = "properties";
-const std::string LLExperienceCache::EXPIRES = "expiration";
-const std::string LLExperienceCache::DESCRIPTION = "description";
-const std::string LLExperienceCache::QUOTA = "quota";
+const std::string LLExperienceCache::EXPERIENCE_ID = "public_id";
+const std::string LLExperienceCache::NAME = "name";
+const std::string LLExperienceCache::PROPERTIES = "properties";
+const std::string LLExperienceCache::EXPIRES = "expiration";
+const std::string LLExperienceCache::DESCRIPTION = "description";
+const std::string LLExperienceCache::QUOTA = "quota";
const std::string LLExperienceCache::MATURITY = "maturity";
const std::string LLExperienceCache::METADATA = "extended_metadata";
-const std::string LLExperienceCache::SLURL = "slurl";
+const std::string LLExperienceCache::SLURL = "slurl";
// should be in sync with experience-api/experiences/models.py
-const int LLExperienceCache::PROPERTY_INVALID = 1 << 0;
-const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3;
-const int LLExperienceCache::PROPERTY_GRID = 1 << 4;
-const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5;
-const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6;
-const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7;
+const int LLExperienceCache::PROPERTY_INVALID = 1 << 0;
+const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3;
+const int LLExperienceCache::PROPERTY_GRID = 1 << 4;
+const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5;
+const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6;
+const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7;
// default values
-const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0;
-const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes
+const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0;
+const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes
const int LLExperienceCache::SEARCH_PAGE_SIZE = 30;
bool LLExperienceCache::sShutdown = false;
@@ -170,7 +170,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const
// *TODO$: Rider: This method does not seem to be used... it may be useful in testing.
void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)
{
- LLExperienceCacheImpl::mapKeys(legacyKeys);
+ LLExperienceCacheImpl::mapKeys(legacyKeys);
LLSD::array_const_iterator it = legacyKeys.beginArray();
for (/**/; it != legacyKeys.endArray(); ++it)
{
@@ -215,33 +215,33 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD&
{
LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL;
- mCache[public_key]=experience;
- LLSD & row = mCache[public_key];
+ mCache[public_key]=experience;
+ LLSD & row = mCache[public_key];
- if(row.has(EXPIRES))
- {
- row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
- }
+ if(row.has(EXPIRES))
+ {
+ row[EXPIRES] = row[EXPIRES].asReal() + LLFrameTimer::getTotalSeconds();
+ }
- if(row.has(EXPERIENCE_ID))
- {
- mPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
- }
+ if(row.has(EXPERIENCE_ID))
+ {
+ mPendingQueue.erase(row[EXPERIENCE_ID].asUUID());
+ }
- //signal
- signal_map_t::iterator sig_it = mSignalMap.find(public_key);
- if (sig_it != mSignalMap.end())
- {
- signal_ptr signal = sig_it->second;
- (*signal)(experience);
+ //signal
+ signal_map_t::iterator sig_it = mSignalMap.find(public_key);
+ if (sig_it != mSignalMap.end())
+ {
+ signal_ptr signal = sig_it->second;
+ (*signal)(experience);
- mSignalMap.erase(public_key);
- }
+ mSignalMap.erase(public_key);
+ }
}
const LLExperienceCache::cache_t& LLExperienceCache::getCached()
{
- return mCache;
+ return mCache;
}
void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests)
@@ -251,7 +251,7 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap
//LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL;
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-
+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -282,8 +282,8 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap
}
LLSD experiences = result["experience_keys"];
-
- for (LLSD::array_const_iterator it = experiences.beginArray();
+
+ for (LLSD::array_const_iterator it = experiences.beginArray();
it != experiences.endArray(); ++it)
{
const LLSD& row = *it;
@@ -296,8 +296,8 @@ void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdap
}
LLSD error_ids = result["error_ids"];
-
- for (LLSD::array_const_iterator errIt = error_ids.beginArray();
+
+ for (LLSD::array_const_iterator errIt = error_ids.beginArray();
errIt != error_ids.endArray(); ++errIt)
{
LLUUID id = errIt->asUUID();
@@ -337,7 +337,7 @@ void LLExperienceCache::requestExperiences()
urlBase += "id/";
- F64 now = LLFrameTimer::getTotalSeconds();
+ F64 now = LLFrameTimer::getTotalSeconds();
const U32 EXP_URL_SEND_THRESHOLD = 3000;
const U32 PAGE_SIZE1 = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH;
@@ -355,7 +355,7 @@ void LLExperienceCache::requestExperiences()
ostr << "&" << EXPERIENCE_ID << "=" << key.asString();
mPendingQueue[key] = now;
-
+
if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD))
{ // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself.
LLCoprocedureManager::instance().enqueueCoprocedure("ExpCache", "RequestExperiences",
@@ -372,18 +372,18 @@ void LLExperienceCache::requestExperiences()
bool LLExperienceCache::isRequestPending(const LLUUID& public_key)
{
- bool isPending = false;
- const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
+ bool isPending = false;
+ const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
PendingQueue_t::const_iterator it = mPendingQueue.find(public_key);
- if(it != mPendingQueue.end())
- {
- F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
- isPending = (it->second > expire_time);
- }
+ if(it != mPendingQueue.end())
+ {
+ F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
+ isPending = (it->second > expire_time);
+ }
- return isPending;
+ return isPending;
}
void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn)
@@ -398,7 +398,7 @@ void LLExperienceCache::idleCoro()
const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL;
- do
+ do
{
if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
{
@@ -420,116 +420,116 @@ void LLExperienceCache::idleCoro()
void LLExperienceCache::erase(const LLUUID& key)
{
- cache_t::iterator it = mCache.find(key);
-
- if(it != mCache.end())
- {
- mCache.erase(it);
- }
+ cache_t::iterator it = mCache.find(key);
+
+ if(it != mCache.end())
+ {
+ mCache.erase(it);
+ }
}
void LLExperienceCache::eraseExpired()
{
- F64 now = LLFrameTimer::getTotalSeconds();
- cache_t::iterator it = mCache.begin();
- while (it != mCache.end())
- {
- cache_t::iterator cur = it;
- LLSD& exp = cur->second;
- ++it;
+ F64 now = LLFrameTimer::getTotalSeconds();
+ cache_t::iterator it = mCache.begin();
+ while (it != mCache.end())
+ {
+ cache_t::iterator cur = it;
+ LLSD& exp = cur->second;
+ ++it;
//LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL;
- if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
- {
+ if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)
+ {
if(!exp.has(EXPERIENCE_ID))
- {
+ {
LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ;
mCache.erase(cur);
- }
+ }
else
{
LLUUID id = exp[EXPERIENCE_ID].asUUID();
LLUUID private_key = exp.has(LLExperienceCache::PRIVATE_KEY) ? exp[LLExperienceCache::PRIVATE_KEY].asUUID():LLUUID::null;
if(private_key.notNull() || !exp.has("DoesNotExist"))
- {
- fetch(id, true);
- }
- else
- {
+ {
+ fetch(id, true);
+ }
+ else
+ {
LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ;
- mCache.erase(cur);
- }
- }
- }
- }
+ mCache.erase(cur);
+ }
+ }
+ }
+ }
}
-
+
bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/)
{
- if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end()))
- {
- LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL;
+ if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end()))
+ {
+ LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL;
mRequestQueue.insert(key);
- return true;
- }
- return false;
+ return true;
+ }
+ return false;
}
void LLExperienceCache::insert(const LLSD& experience_data)
{
- if(experience_data.has(EXPERIENCE_ID))
- {
+ if(experience_data.has(EXPERIENCE_ID))
+ {
processExperience(experience_data[EXPERIENCE_ID].asUUID(), experience_data);
- }
- else
- {
- LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
- }
+ }
+ else
+ {
+ LL_WARNS("ExperienceCache") << ": Ignoring cache insert of experience which is missing " << EXPERIENCE_ID << LL_ENDL;
+ }
}
const LLSD& LLExperienceCache::get(const LLUUID& key)
{
- static const LLSD empty;
-
- if(key.isNull())
- return empty;
- cache_t::const_iterator it = mCache.find(key);
-
- if (it != mCache.end())
- {
- return it->second;
- }
- fetch(key);
-
- return empty;
+ static const LLSD empty;
+
+ if(key.isNull())
+ return empty;
+ cache_t::const_iterator it = mCache.find(key);
+
+ if (it != mCache.end())
+ {
+ return it->second;
+ }
+ fetch(key);
+
+ return empty;
}
void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::ExperienceGetFn_t slot)
{
- if(key.isNull())
- return;
-
- cache_t::const_iterator it = mCache.find(key);
- if (it != mCache.end())
- {
- // ...name already exists in cache, fire callback now
- callback_signal_t signal;
- signal.connect(slot);
-
- signal(it->second);
- return;
- }
-
- fetch(key);
-
- signal_ptr signal = signal_ptr(new callback_signal_t());
-
- std::pair<signal_map_t::iterator, bool> result = mSignalMap.insert(signal_map_t::value_type(key, signal));
- if (!result.second)
- signal = (*result.first).second;
- signal->connect(slot);
+ if(key.isNull())
+ return;
+
+ cache_t::const_iterator it = mCache.find(key);
+ if (it != mCache.end())
+ {
+ // ...name already exists in cache, fire callback now
+ callback_signal_t signal;
+ signal.connect(slot);
+
+ signal(it->second);
+ return;
+ }
+
+ fetch(key);
+
+ signal_ptr signal = signal_ptr(new callback_signal_t());
+
+ std::pair<signal_map_t::iterator, bool> result = mSignalMap.insert(signal_map_t::value_type(key, signal));
+ if (!result.second)
+ signal = (*result.first).second;
+ signal->connect(slot);
}
//=========================================================================
@@ -592,7 +592,7 @@ void LLExperienceCache::fetchAssociatedExperienceCoro(LLCoreHttpUtil::HttpCorout
failure["error"] = (LLSD::Integer)status.getType();
failure["message"] = status.getMessage();
}
- else
+ else
{
failure["error"] = -1;
failure["message"] = "no experience";
@@ -747,7 +747,7 @@ void LLExperienceCache::getExperiencePermission(const LLUUID &experienceId, Expe
}
std::string url = mCapability("ExperiencePreferences") + "?" + experienceId.asString();
-
+
permissionInvoker_fn invoker(boost::bind(
// Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
static_cast<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
@@ -903,15 +903,15 @@ void LLExperienceCache::updateExperienceCoro(LLCoreHttpUtil::HttpCoroutineAdapte
//=========================================================================
void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys)
{
- LLSD::array_const_iterator exp = legacyKeys.beginArray();
- for (/**/; exp != legacyKeys.endArray(); ++exp)
- {
+ LLSD::array_const_iterator exp = legacyKeys.beginArray();
+ for (/**/; exp != legacyKeys.endArray(); ++exp)
+ {
if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY))
- {
- LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] =
+ {
+ LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] =
(*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID();
- }
- }
+ }
+ }
}
// Return time to retry a request that generated an error, based on
@@ -972,56 +972,56 @@ F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers)
bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age)
{
- // Split the string on "," to get a list of directives
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- tokenizer directives(cache_control, COMMA_SEPARATOR);
-
- tokenizer::iterator token_it = directives.begin();
- for ( ; token_it != directives.end(); ++token_it)
- {
- // Tokens may have leading or trailing whitespace
- std::string token = *token_it;
- LLStringUtil::trim(token);
-
- if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
- {
- // ...this token starts with max-age, so let's chop it up by "="
- tokenizer subtokens(token, EQUALS_SEPARATOR);
- tokenizer::iterator subtoken_it = subtokens.begin();
-
- // Must have a token
- if (subtoken_it == subtokens.end()) return false;
- std::string subtoken = *subtoken_it;
-
- // Must exactly equal "max-age"
- LLStringUtil::trim(subtoken);
- if (subtoken != MAX_AGE) return false;
-
- // Must have another token
- ++subtoken_it;
- if (subtoken_it == subtokens.end()) return false;
- subtoken = *subtoken_it;
-
- // Must be a valid integer
- // *NOTE: atoi() returns 0 for invalid values, so we have to
- // check the string first.
- // *TODO: Do servers ever send "0000" for zero? We don't handle it
- LLStringUtil::trim(subtoken);
- if (subtoken == "0")
- {
- *max_age = 0;
- return true;
- }
- S32 val = atoi( subtoken.c_str() );
- if (val > 0 && val < S32_MAX)
- {
- *max_age = val;
- return true;
- }
- return false;
- }
- }
- return false;
+ // Split the string on "," to get a list of directives
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ tokenizer directives(cache_control, COMMA_SEPARATOR);
+
+ tokenizer::iterator token_it = directives.begin();
+ for ( ; token_it != directives.end(); ++token_it)
+ {
+ // Tokens may have leading or trailing whitespace
+ std::string token = *token_it;
+ LLStringUtil::trim(token);
+
+ if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+ {
+ // ...this token starts with max-age, so let's chop it up by "="
+ tokenizer subtokens(token, EQUALS_SEPARATOR);
+ tokenizer::iterator subtoken_it = subtokens.begin();
+
+ // Must have a token
+ if (subtoken_it == subtokens.end()) return false;
+ std::string subtoken = *subtoken_it;
+
+ // Must exactly equal "max-age"
+ LLStringUtil::trim(subtoken);
+ if (subtoken != MAX_AGE) return false;
+
+ // Must have another token
+ ++subtoken_it;
+ if (subtoken_it == subtokens.end()) return false;
+ subtoken = *subtoken_it;
+
+ // Must be a valid integer
+ // *NOTE: atoi() returns 0 for invalid values, so we have to
+ // check the string first.
+ // *TODO: Do servers ever send "0000" for zero? We don't handle it
+ LLStringUtil::trim(subtoken);
+ if (subtoken == "0")
+ {
+ *max_age = 0;
+ return true;
+ }
+ S32 val = atoi( subtoken.c_str() );
+ if (val > 0 && val < S32_MAX)
+ {
+ *max_age = val;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
}
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index 3ee45da2e7..81e904107f 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llexperiencecache.h
* @brief Caches information relating to experience keys
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -53,7 +53,7 @@ public:
void cleanup();
//-------------------------------------------
- // Cache methods
+ // Cache methods
void erase(const LLUUID& key);
bool fetch(const LLUUID& key, bool refresh = false);
void insert(const LLSD& experience_data);
@@ -68,7 +68,7 @@ public:
void findExperienceByName(const std::string text, int page, ExperienceGetFn_t fn);
void getGroupExperiences(const LLUUID &groupId, ExperienceGetFn_t fn);
- // the Get/Set Region Experiences take a CapabilityQuery to get the capability since
+ // the Get/Set Region Experiences take a CapabilityQuery to get the capability since
// the region being queried may not be the region that the agent is standing on.
void getRegionExperiences(CapabilityQuery_t regioncaps, ExperienceGetFn_t fn);
void setRegionExperiences(CapabilityQuery_t regioncaps, const LLSD &experiences, ExperienceGetFn_t fn);
@@ -81,13 +81,13 @@ public:
void updateExperience(LLSD updateData, ExperienceGetFn_t fn);
//-------------------------------------------
- static const std::string NAME; // "name"
- static const std::string EXPERIENCE_ID; // "public_id"
+ static const std::string NAME; // "name"
+ static const std::string EXPERIENCE_ID; // "public_id"
static const std::string AGENT_ID; // "agent_id"
static const std::string GROUP_ID; // "group_id"
- static const std::string PROPERTIES; // "properties"
- static const std::string EXPIRES; // "expiration"
- static const std::string DESCRIPTION; // "description"
+ static const std::string PROPERTIES; // "properties"
+ static const std::string EXPIRES; // "expiration"
+ static const std::string DESCRIPTION; // "description"
static const std::string QUOTA; // "quota"
static const std::string MATURITY; // "maturity"
static const std::string METADATA; // "extended_metadata"
@@ -96,12 +96,12 @@ public:
static const std::string MISSING; // "DoesNotExist"
// should be in sync with experience-api/experiences/models.py
- static const int PROPERTY_INVALID; // 1 << 0
- static const int PROPERTY_PRIVILEGED; // 1 << 3
- static const int PROPERTY_GRID; // 1 << 4
- static const int PROPERTY_PRIVATE; // 1 << 5
- static const int PROPERTY_DISABLED; // 1 << 6
- static const int PROPERTY_SUSPENDED; // 1 << 7
+ static const int PROPERTY_INVALID; // 1 << 0
+ static const int PROPERTY_PRIVILEGED; // 1 << 3
+ static const int PROPERTY_GRID; // 1 << 4
+ static const int PROPERTY_PRIVATE; // 1 << 5
+ static const int PROPERTY_DISABLED; // 1 << 6
+ static const int PROPERTY_SUSPENDED; // 1 << 7
private:
virtual ~LLExperienceCache();
@@ -110,33 +110,33 @@ private:
typedef boost::function<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, LLCore::HttpRequest::ptr_t, std::string)> permissionInvoker_fn;
- // Callback types for get()
+ // Callback types for get()
typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
- typedef std::shared_ptr<callback_signal_t> signal_ptr;
- // May have multiple callbacks for a single ID, which are
- // represented as multiple slots bound to the signal.
- // Avoid copying signals via pointers.
- typedef std::map<LLUUID, signal_ptr> signal_map_t;
- typedef std::map<LLUUID, LLSD> cache_t;
-
- typedef std::set<LLUUID> RequestQueue_t;
+ typedef std::shared_ptr<callback_signal_t> signal_ptr;
+ // May have multiple callbacks for a single ID, which are
+ // represented as multiple slots bound to the signal.
+ // Avoid copying signals via pointers.
+ typedef std::map<LLUUID, signal_ptr> signal_map_t;
+ typedef std::map<LLUUID, LLSD> cache_t;
+
+ typedef std::set<LLUUID> RequestQueue_t;
typedef std::map<LLUUID, F64> PendingQueue_t;
- //--------------------------------------------
- static const std::string PRIVATE_KEY; // "private_id"
-
- // default values
- static const F64 DEFAULT_EXPIRATION; // 600.0
- static const S32 DEFAULT_QUOTA; // 128 this is megabytes
+ //--------------------------------------------
+ static const std::string PRIVATE_KEY; // "private_id"
+
+ // default values
+ static const F64 DEFAULT_EXPIRATION; // 600.0
+ static const S32 DEFAULT_QUOTA; // 128 this is megabytes
static const int SEARCH_PAGE_SIZE;
-
+
//--------------------------------------------
void processExperience(const LLUUID& public_key, const LLSD& experience);
//--------------------------------------------
- cache_t mCache;
- signal_map_t mSignalMap;
- RequestQueue_t mRequestQueue;
+ cache_t mCache;
+ signal_map_t mSignalMap;
+ RequestQueue_t mRequestQueue;
PendingQueue_t mPendingQueue;
LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache
@@ -145,7 +145,7 @@ private:
static bool sShutdown; // control for coroutines, they exist out of LLExperienceCache's scope, so they need a static control
void idleCoro();
- void eraseExpired();
+ void eraseExpired();
void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t);
void requestExperiences();
@@ -161,11 +161,11 @@ private:
void exportFile(std::ostream& ostr) const;
void importFile(std::istream& istr);
- //
- const cache_t& getCached();
+ //
+ const cache_t& getCached();
- // maps an experience private key to the experience id
- LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
+ // maps an experience private key to the experience id
+ LLUUID getExperienceId(const LLUUID& private_key, bool null_if_not_found=false);
//=====================================================================
inline friend std::ostream &operator << (std::ostream &os, const LLExperienceCache &cache)
diff --git a/indra/llmessage/llextendedstatus.h b/indra/llmessage/llextendedstatus.h
index 2a53dced80..ed8338daa3 100644
--- a/indra/llmessage/llextendedstatus.h
+++ b/indra/llmessage/llextendedstatus.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llextendedstatus.h
* @date August 2007
* @brief extended status codes for curl/resident asset storage and delivery
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,33 +30,33 @@
enum class LLExtStat: uint32_t
{
- // Status provider groups - Top bits indicate which status type it is
- // Zero is common status code (next section)
- CURL_RESULT = 1UL<<30, // serviced by curl - use 1L if we really implement the below
- RES_RESULT = 2UL<<30, // serviced by resident copy
- CACHE_RESULT = 3UL<<30, // serviced by cache
-
-
- // Common Status Codes
- //
- NONE = 0x00000, // No extra info here - sorry!
- NULL_UUID = 0x10001, // null asset ID
- NO_UPSTREAM = 0x10002, // attempt to upload without a valid upstream method/provider
- REQUEST_DROPPED = 0x10003, // request was dropped unserviced
- NONEXISTENT_FILE= 0x10004, // trying to upload a file that doesn't exist
- BLOCKED_FILE = 0x10005, // trying to upload a file that we can't open
-
- // curl status codes:
- //
- // Mask off CURL_RESULT for original result and
- // see: libraries/include/curl/curl.h
-
- // Memory-Resident status codes:
- // None at present
-
- // CACHE status codes:
- CACHE_CACHED = CACHE_RESULT | 0x0001,
- CACHE_CORRUPT = CACHE_RESULT | 0x0002,
+ // Status provider groups - Top bits indicate which status type it is
+ // Zero is common status code (next section)
+ CURL_RESULT = 1UL<<30, // serviced by curl - use 1L if we really implement the below
+ RES_RESULT = 2UL<<30, // serviced by resident copy
+ CACHE_RESULT = 3UL<<30, // serviced by cache
+
+
+ // Common Status Codes
+ //
+ NONE = 0x00000, // No extra info here - sorry!
+ NULL_UUID = 0x10001, // null asset ID
+ NO_UPSTREAM = 0x10002, // attempt to upload without a valid upstream method/provider
+ REQUEST_DROPPED = 0x10003, // request was dropped unserviced
+ NONEXISTENT_FILE= 0x10004, // trying to upload a file that doesn't exist
+ BLOCKED_FILE = 0x10005, // trying to upload a file that we can't open
+
+ // curl status codes:
+ //
+ // Mask off CURL_RESULT for original result and
+ // see: libraries/include/curl/curl.h
+
+ // Memory-Resident status codes:
+ // None at present
+
+ // CACHE status codes:
+ CACHE_CACHED = CACHE_RESULT | 0x0001,
+ CACHE_CORRUPT = CACHE_RESULT | 0x0002,
};
diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp
index c63ce5f441..df78652361 100644
--- a/indra/llmessage/llfiltersd2xmlrpc.cpp
+++ b/indra/llmessage/llfiltersd2xmlrpc.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfiltersd2xmlrpc.cpp
* @author Phoenix
* @date 2005-04-26
@@ -6,27 +6,27 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-/**
- * xml rpc request:
+/**
+ * xml rpc request:
* <code>
* <?xml version="1.0"?>
* <methodCall><methodName>examples.getStateName</methodName>
@@ -57,17 +57,17 @@
* <code>
* { 'method':'...', 'parameter':...]}
* </code>
- *
+ *
* llsd rpc response:
* <code>
* { 'response':... }
* </code>
- *
- * llsd rpc fault:
+ *
+ * llsd rpc fault:
* <code>
* { 'fault': {'code':i..., 'description':'...'} }
* </code>
- *
+ *
*/
#include "linden_common.h"
@@ -132,174 +132,174 @@ LLFilterSD2XMLRPC::~LLFilterSD2XMLRPC()
std::string xml_escape_string(const std::string& in)
{
- std::ostringstream out;
- std::string::const_iterator it = in.begin();
- std::string::const_iterator end = in.end();
- for(; it != end; ++it)
- {
- switch((*it))
- {
- case '<':
- out << "&lt;";
- break;
- case '>':
- out << "&gt;";
- break;
- case '&':
- out << "&amp;";
- break;
- case '\'':
- out << "&apos;";
- break;
- case '"':
- out << "&quot;";
- break;
- default:
- out << (*it);
- break;
- }
- }
- return out.str();
+ std::ostringstream out;
+ std::string::const_iterator it = in.begin();
+ std::string::const_iterator end = in.end();
+ for(; it != end; ++it)
+ {
+ switch((*it))
+ {
+ case '<':
+ out << "&lt;";
+ break;
+ case '>':
+ out << "&gt;";
+ break;
+ case '&':
+ out << "&amp;";
+ break;
+ case '\'':
+ out << "&apos;";
+ break;
+ case '"':
+ out << "&quot;";
+ break;
+ default:
+ out << (*it);
+ break;
+ }
+ }
+ return out.str();
}
void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
{
- ostr << "<value>";
- switch(sd.type())
- {
- case LLSD::TypeMap:
- {
+ ostr << "<value>";
+ switch(sd.type())
+ {
+ case LLSD::TypeMap:
+ {
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(map) BEGIN" << LL_ENDL;
+ LL_INFOS() << "streamOut(map) BEGIN" << LL_ENDL;
#endif
- ostr << "<struct>";
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing struct" << LL_ENDL;
- }
- LLSD::map_const_iterator it = sd.beginMap();
- LLSD::map_const_iterator end = sd.endMap();
- for(; it != end; ++it)
- {
- ostr << "<member><name>" << xml_escape_string((*it).first)
- << "</name>";
- streamOut(ostr, (*it).second);
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing '" << (*it).first
- << "' with sd type " << (*it).second.type() << LL_ENDL;
- }
- ostr << "</member>";
- }
- ostr << "</struct>";
+ ostr << "<struct>";
+ if(ostr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE writing struct" << LL_ENDL;
+ }
+ LLSD::map_const_iterator it = sd.beginMap();
+ LLSD::map_const_iterator end = sd.endMap();
+ for(; it != end; ++it)
+ {
+ ostr << "<member><name>" << xml_escape_string((*it).first)
+ << "</name>";
+ streamOut(ostr, (*it).second);
+ if(ostr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE writing '" << (*it).first
+ << "' with sd type " << (*it).second.type() << LL_ENDL;
+ }
+ ostr << "</member>";
+ }
+ ostr << "</struct>";
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(map) END" << LL_ENDL;
+ LL_INFOS() << "streamOut(map) END" << LL_ENDL;
#endif
- break;
- }
- case LLSD::TypeArray:
- {
+ break;
+ }
+ case LLSD::TypeArray:
+ {
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(array) BEGIN" << LL_ENDL;
+ LL_INFOS() << "streamOut(array) BEGIN" << LL_ENDL;
#endif
- ostr << "<array><data>";
- LLSD::array_const_iterator it = sd.beginArray();
- LLSD::array_const_iterator end = sd.endArray();
- for(; it != end; ++it)
- {
- streamOut(ostr, *it);
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing array element sd type "
- << (*it).type() << LL_ENDL;
- }
- }
+ ostr << "<array><data>";
+ LLSD::array_const_iterator it = sd.beginArray();
+ LLSD::array_const_iterator end = sd.endArray();
+ for(; it != end; ++it)
+ {
+ streamOut(ostr, *it);
+ if(ostr.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE writing array element sd type "
+ << (*it).type() << LL_ENDL;
+ }
+ }
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(array) END" << LL_ENDL;
+ LL_INFOS() << "streamOut(array) END" << LL_ENDL;
#endif
- ostr << "</data></array>";
- break;
- }
- case LLSD::TypeUndefined:
- // treat undefined as a bool with a false value.
- case LLSD::TypeBoolean:
+ ostr << "</data></array>";
+ break;
+ }
+ case LLSD::TypeUndefined:
+ // treat undefined as a bool with a false value.
+ case LLSD::TypeBoolean:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(bool)" << LL_ENDL;
+ LL_INFOS() << "streamOut(bool)" << LL_ENDL;
#endif
- ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>";
- break;
- case LLSD::TypeInteger:
+ ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>";
+ break;
+ case LLSD::TypeInteger:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(int)" << LL_ENDL;
+ LL_INFOS() << "streamOut(int)" << LL_ENDL;
#endif
- ostr << "<i4>" << sd.asInteger() << "</i4>";
- break;
- case LLSD::TypeReal:
+ ostr << "<i4>" << sd.asInteger() << "</i4>";
+ break;
+ case LLSD::TypeReal:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(real)" << LL_ENDL;
+ LL_INFOS() << "streamOut(real)" << LL_ENDL;
#endif
- ostr << "<double>" << sd.asReal() << "</double>";
- break;
- case LLSD::TypeString:
+ ostr << "<double>" << sd.asReal() << "</double>";
+ break;
+ case LLSD::TypeString:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(string)" << LL_ENDL;
+ LL_INFOS() << "streamOut(string)" << LL_ENDL;
#endif
- ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
- break;
- case LLSD::TypeUUID:
+ ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
+ break;
+ case LLSD::TypeUUID:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(uuid)" << LL_ENDL;
+ LL_INFOS() << "streamOut(uuid)" << LL_ENDL;
#endif
- // serialize it as a string
- ostr << "<string>" << sd.asString() << "</string>";
- break;
- case LLSD::TypeURI:
- {
+ // serialize it as a string
+ ostr << "<string>" << sd.asString() << "</string>";
+ break;
+ case LLSD::TypeURI:
+ {
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(uri)" << LL_ENDL;
+ LL_INFOS() << "streamOut(uri)" << LL_ENDL;
#endif
- // serialize it as a string
- ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
- break;
- }
- case LLSD::TypeBinary:
- {
+ // serialize it as a string
+ ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
+ break;
+ }
+ case LLSD::TypeBinary:
+ {
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(binary)" << LL_ENDL;
+ LL_INFOS() << "streamOut(binary)" << LL_ENDL;
#endif
- // this is pretty inefficient, but we'll deal with that
- // problem when it becomes one.
- ostr << "<base64>";
- LLSD::Binary buffer = sd.asBinary();
- if(!buffer.empty())
- {
- // *TODO: convert to LLBase64
- int b64_buffer_length = apr_base64_encode_len(buffer.size());
- char* b64_buffer = new char[b64_buffer_length];
- b64_buffer_length = apr_base64_encode_binary(
- b64_buffer,
- &buffer[0],
- buffer.size());
- ostr.write(b64_buffer, b64_buffer_length - 1);
- delete[] b64_buffer;
- }
- ostr << "</base64>";
- break;
- }
- case LLSD::TypeDate:
+ // this is pretty inefficient, but we'll deal with that
+ // problem when it becomes one.
+ ostr << "<base64>";
+ LLSD::Binary buffer = sd.asBinary();
+ if(!buffer.empty())
+ {
+ // *TODO: convert to LLBase64
+ int b64_buffer_length = apr_base64_encode_len(buffer.size());
+ char* b64_buffer = new char[b64_buffer_length];
+ b64_buffer_length = apr_base64_encode_binary(
+ b64_buffer,
+ &buffer[0],
+ buffer.size());
+ ostr.write(b64_buffer, b64_buffer_length - 1);
+ delete[] b64_buffer;
+ }
+ ostr << "</base64>";
+ break;
+ }
+ case LLSD::TypeDate:
#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(date)" << LL_ENDL;
+ LL_INFOS() << "streamOut(date)" << LL_ENDL;
#endif
- // no need to escape this since it will be alpha-numeric.
- ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>";
- break;
- default:
- // unhandled type
- LL_WARNS() << "Unhandled structured data type: " << sd.type()
- << LL_ENDL;
- break;
- }
- ostr << "</value>";
+ // no need to escape this since it will be alpha-numeric.
+ ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>";
+ break;
+ default:
+ // unhandled type
+ LL_WARNS() << "Unhandled structured data type: " << sd.type()
+ << LL_ENDL;
+ break;
+ }
+ ostr << "</value>";
}
/**
@@ -317,59 +317,59 @@ LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse()
// virtual
LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- // This pipe does not work if it does not have everyting. This
- // could be addressed by making a stream parser for llsd which
- // handled partial information.
- if(!eos)
- {
- return STATUS_BREAK;
- }
-
- PUMP_DEBUG;
- // we have everyting in the buffer, so turn the structure data rpc
- // response into an xml rpc response.
- LLBufferStream stream(channels, buffer.get());
- stream << XML_HEADER << XMLRPC_METHOD_RESPONSE_HEADER;
- LLSD sd;
- LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
-
- PUMP_DEBUG;
- LLIOPipe::EStatus rv = STATUS_ERROR;
- if(sd.has("response"))
- {
- PUMP_DEBUG;
- // it is a normal response. pack it up and ship it out.
- stream.precision(DEFAULT_PRECISION);
- stream << XMLRPC_RESPONSE_HEADER;
- streamOut(stream, sd["response"]);
- stream << XMLRPC_RESPONSE_FOOTER << XMLRPC_METHOD_RESPONSE_FOOTER;
- rv = STATUS_DONE;
- }
- else if(sd.has("fault"))
- {
- PUMP_DEBUG;
- // it is a fault.
- stream << XMLRPC_FAULT_1 << sd["fault"]["code"].asInteger()
- << XMLRPC_FAULT_2
- << xml_escape_string(sd["fault"]["description"].asString())
- << XMLRPC_FAULT_3 << XMLRPC_METHOD_RESPONSE_FOOTER;
- rv = STATUS_DONE;
- }
- else
- {
- LL_WARNS() << "Unable to determine the type of LLSD response." << LL_ENDL;
- }
- PUMP_DEBUG;
- return rv;
+ PUMP_DEBUG;
+ // This pipe does not work if it does not have everyting. This
+ // could be addressed by making a stream parser for llsd which
+ // handled partial information.
+ if(!eos)
+ {
+ return STATUS_BREAK;
+ }
+
+ PUMP_DEBUG;
+ // we have everyting in the buffer, so turn the structure data rpc
+ // response into an xml rpc response.
+ LLBufferStream stream(channels, buffer.get());
+ stream << XML_HEADER << XMLRPC_METHOD_RESPONSE_HEADER;
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
+
+ PUMP_DEBUG;
+ LLIOPipe::EStatus rv = STATUS_ERROR;
+ if(sd.has("response"))
+ {
+ PUMP_DEBUG;
+ // it is a normal response. pack it up and ship it out.
+ stream.precision(DEFAULT_PRECISION);
+ stream << XMLRPC_RESPONSE_HEADER;
+ streamOut(stream, sd["response"]);
+ stream << XMLRPC_RESPONSE_FOOTER << XMLRPC_METHOD_RESPONSE_FOOTER;
+ rv = STATUS_DONE;
+ }
+ else if(sd.has("fault"))
+ {
+ PUMP_DEBUG;
+ // it is a fault.
+ stream << XMLRPC_FAULT_1 << sd["fault"]["code"].asInteger()
+ << XMLRPC_FAULT_2
+ << xml_escape_string(sd["fault"]["description"].asString())
+ << XMLRPC_FAULT_3 << XMLRPC_METHOD_RESPONSE_FOOTER;
+ rv = STATUS_DONE;
+ }
+ else
+ {
+ LL_WARNS() << "Unable to determine the type of LLSD response." << LL_ENDL;
+ }
+ PUMP_DEBUG;
+ return rv;
}
/**
@@ -381,10 +381,10 @@ LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest()
LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest(const char* method)
{
- if(method)
- {
- mMethod.assign(method);
- }
+ if(method)
+ {
+ mMethod.assign(method);
+ }
}
LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
@@ -393,103 +393,103 @@ LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
// virtual
LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- // This pipe does not work if it does not have everyting. This
- // could be addressed by making a stream parser for llsd which
- // handled partial information.
- PUMP_DEBUG;
- if(!eos)
- {
- LL_INFOS() << "!eos" << LL_ENDL;
- return STATUS_BREAK;
- }
-
- // See if we can parse it
- LLBufferStream stream(channels, buffer.get());
- LLSD sd;
- LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
- if(stream.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading structure data." << LL_ENDL;
- }
-
- PUMP_DEBUG;
- // We can get the method and parameters from either the member
- // function or passed in via the buffer. We prefer the buffer if
- // we found a parameter and a method, or fall back to using
- // mMethod and putting everyting in the buffer into the parameter.
- std::string method;
- LLSD param_sd;
- if(sd.has("method") && sd.has("parameter"))
- {
- method = sd["method"].asString();
- param_sd = sd["parameter"];
- }
- else
- {
- method = mMethod;
- param_sd = sd;
- }
- if(method.empty())
- {
- LL_WARNS() << "SD -> XML Request no method found." << LL_ENDL;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- // We have a method, and some kind of parameter, so package it up
- // and send it out.
- LLBufferStream ostream(channels, buffer.get());
- ostream.precision(DEFAULT_PRECISION);
- if(ostream.fail())
- {
- LL_INFOS() << "STREAM FAILURE setting precision" << LL_ENDL;
- }
- ostream << XML_HEADER << XMLRPC_REQUEST_HEADER_1
- << xml_escape_string(method) << XMLRPC_REQUEST_HEADER_2;
- if(ostream.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing method headers" << LL_ENDL;
- }
- switch(param_sd.type())
- {
- case LLSD::TypeMap:
- // If the params are a map, then we do not want to iterate
- // through them since the iterators returned will be map
- // ordered un-named values, which will lose the names, and
- // only stream the values, turning it into an array.
- ostream << "<param>";
- streamOut(ostream, param_sd);
- ostream << "</param>";
- break;
- case LLSD::TypeArray:
- {
-
- LLSD::array_iterator it = param_sd.beginArray();
- LLSD::array_iterator end = param_sd.endArray();
- for(; it != end; ++it)
- {
- ostream << "<param>";
- streamOut(ostream, *it);
- ostream << "</param>";
- }
- break;
- }
- default:
- ostream << "<param>";
- streamOut(ostream, param_sd);
- ostream << "</param>";
- break;
- }
-
- stream << XMLRPC_REQUEST_FOOTER;
- return STATUS_DONE;
+ // This pipe does not work if it does not have everyting. This
+ // could be addressed by making a stream parser for llsd which
+ // handled partial information.
+ PUMP_DEBUG;
+ if(!eos)
+ {
+ LL_INFOS() << "!eos" << LL_ENDL;
+ return STATUS_BREAK;
+ }
+
+ // See if we can parse it
+ LLBufferStream stream(channels, buffer.get());
+ LLSD sd;
+ LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
+ if(stream.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE reading structure data." << LL_ENDL;
+ }
+
+ PUMP_DEBUG;
+ // We can get the method and parameters from either the member
+ // function or passed in via the buffer. We prefer the buffer if
+ // we found a parameter and a method, or fall back to using
+ // mMethod and putting everyting in the buffer into the parameter.
+ std::string method;
+ LLSD param_sd;
+ if(sd.has("method") && sd.has("parameter"))
+ {
+ method = sd["method"].asString();
+ param_sd = sd["parameter"];
+ }
+ else
+ {
+ method = mMethod;
+ param_sd = sd;
+ }
+ if(method.empty())
+ {
+ LL_WARNS() << "SD -> XML Request no method found." << LL_ENDL;
+ return STATUS_ERROR;
+ }
+
+ PUMP_DEBUG;
+ // We have a method, and some kind of parameter, so package it up
+ // and send it out.
+ LLBufferStream ostream(channels, buffer.get());
+ ostream.precision(DEFAULT_PRECISION);
+ if(ostream.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE setting precision" << LL_ENDL;
+ }
+ ostream << XML_HEADER << XMLRPC_REQUEST_HEADER_1
+ << xml_escape_string(method) << XMLRPC_REQUEST_HEADER_2;
+ if(ostream.fail())
+ {
+ LL_INFOS() << "STREAM FAILURE writing method headers" << LL_ENDL;
+ }
+ switch(param_sd.type())
+ {
+ case LLSD::TypeMap:
+ // If the params are a map, then we do not want to iterate
+ // through them since the iterators returned will be map
+ // ordered un-named values, which will lose the names, and
+ // only stream the values, turning it into an array.
+ ostream << "<param>";
+ streamOut(ostream, param_sd);
+ ostream << "</param>";
+ break;
+ case LLSD::TypeArray:
+ {
+
+ LLSD::array_iterator it = param_sd.beginArray();
+ LLSD::array_iterator end = param_sd.endArray();
+ for(; it != end; ++it)
+ {
+ ostream << "<param>";
+ streamOut(ostream, *it);
+ ostream << "</param>";
+ }
+ break;
+ }
+ default:
+ ostream << "<param>";
+ streamOut(ostream, param_sd);
+ ostream << "</param>";
+ break;
+ }
+
+ stream << XMLRPC_REQUEST_FOOTER;
+ return STATUS_DONE;
}
/**
@@ -500,92 +500,92 @@ LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
// parameters.
LLIOPipe::EStatus stream_out(std::ostream& ostr, XMLRPC_VALUE value)
{
- XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(value);
- LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
- switch(type)
- {
- case xmlrpc_type_base64:
- {
- S32 len = XMLRPC_GetValueStringLen(value);
- const char* buf = XMLRPC_GetValueBase64(value);
- ostr << " b(";
- if((len > 0) && buf)
- {
- ostr << len << ")\"";
- ostr.write(buf, len);
- ostr << "\"";
- }
- else
- {
- ostr << "0)\"\"";
- }
- break;
- }
- case xmlrpc_type_boolean:
- //LL_DEBUGS() << "stream_out() bool" << LL_ENDL;
- ostr << " " << (XMLRPC_GetValueBoolean(value) ? "true" : "false");
- break;
- case xmlrpc_type_datetime:
- ostr << " d\"" << XMLRPC_GetValueDateTime_ISO8601(value) << "\"";
- break;
- case xmlrpc_type_double:
- ostr << " r" << XMLRPC_GetValueDouble(value);
- //LL_DEBUGS() << "stream_out() double" << XMLRPC_GetValueDouble(value)
- // << LL_ENDL;
- break;
- case xmlrpc_type_int:
- ostr << " i" << XMLRPC_GetValueInt(value);
- //LL_DEBUGS() << "stream_out() integer:" << XMLRPC_GetValueInt(value)
- // << LL_ENDL;
- break;
- case xmlrpc_type_string:
- //LL_DEBUGS() << "stream_out() string: " << str << LL_ENDL;
- ostr << " s(" << XMLRPC_GetValueStringLen(value) << ")'"
- << XMLRPC_GetValueString(value) << "'";
- break;
- case xmlrpc_type_array: // vector
- case xmlrpc_type_mixed: // vector
- {
- //LL_DEBUGS() << "stream_out() array" << LL_ENDL;
- ostr << " [";
- U32 needs_comma = 0;
- XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
- while(current && (LLIOPipe::STATUS_OK == status))
- {
- if(needs_comma++) ostr << ",";
- status = stream_out(ostr, current);
- current = XMLRPC_VectorNext(value);
- }
- ostr << "]";
- break;
- }
- case xmlrpc_type_struct: // still vector
- {
- //LL_DEBUGS() << "stream_out() struct" << LL_ENDL;
- ostr << " {";
- std::string name;
- U32 needs_comma = 0;
- XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
- while(current && (LLIOPipe::STATUS_OK == status))
- {
- if(needs_comma++) ostr << ",";
- name.assign(XMLRPC_GetValueID(current));
- ostr << "'" << LLSDNotationFormatter::escapeString(name) << "':";
- status = stream_out(ostr, current);
- current = XMLRPC_VectorNext(value);
- }
- ostr << "}";
- break;
- }
- case xmlrpc_type_empty:
- case xmlrpc_type_none:
- default:
- status = LLIOPipe::STATUS_ERROR;
- LL_WARNS() << "Found an empty xmlrpc type.." << LL_ENDL;
- // not much we can do here...
- break;
- };
- return status;
+ XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(value);
+ LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
+ switch(type)
+ {
+ case xmlrpc_type_base64:
+ {
+ S32 len = XMLRPC_GetValueStringLen(value);
+ const char* buf = XMLRPC_GetValueBase64(value);
+ ostr << " b(";
+ if((len > 0) && buf)
+ {
+ ostr << len << ")\"";
+ ostr.write(buf, len);
+ ostr << "\"";
+ }
+ else
+ {
+ ostr << "0)\"\"";
+ }
+ break;
+ }
+ case xmlrpc_type_boolean:
+ //LL_DEBUGS() << "stream_out() bool" << LL_ENDL;
+ ostr << " " << (XMLRPC_GetValueBoolean(value) ? "true" : "false");
+ break;
+ case xmlrpc_type_datetime:
+ ostr << " d\"" << XMLRPC_GetValueDateTime_ISO8601(value) << "\"";
+ break;
+ case xmlrpc_type_double:
+ ostr << " r" << XMLRPC_GetValueDouble(value);
+ //LL_DEBUGS() << "stream_out() double" << XMLRPC_GetValueDouble(value)
+ // << LL_ENDL;
+ break;
+ case xmlrpc_type_int:
+ ostr << " i" << XMLRPC_GetValueInt(value);
+ //LL_DEBUGS() << "stream_out() integer:" << XMLRPC_GetValueInt(value)
+ // << LL_ENDL;
+ break;
+ case xmlrpc_type_string:
+ //LL_DEBUGS() << "stream_out() string: " << str << LL_ENDL;
+ ostr << " s(" << XMLRPC_GetValueStringLen(value) << ")'"
+ << XMLRPC_GetValueString(value) << "'";
+ break;
+ case xmlrpc_type_array: // vector
+ case xmlrpc_type_mixed: // vector
+ {
+ //LL_DEBUGS() << "stream_out() array" << LL_ENDL;
+ ostr << " [";
+ U32 needs_comma = 0;
+ XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
+ while(current && (LLIOPipe::STATUS_OK == status))
+ {
+ if(needs_comma++) ostr << ",";
+ status = stream_out(ostr, current);
+ current = XMLRPC_VectorNext(value);
+ }
+ ostr << "]";
+ break;
+ }
+ case xmlrpc_type_struct: // still vector
+ {
+ //LL_DEBUGS() << "stream_out() struct" << LL_ENDL;
+ ostr << " {";
+ std::string name;
+ U32 needs_comma = 0;
+ XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
+ while(current && (LLIOPipe::STATUS_OK == status))
+ {
+ if(needs_comma++) ostr << ",";
+ name.assign(XMLRPC_GetValueID(current));
+ ostr << "'" << LLSDNotationFormatter::escapeString(name) << "':";
+ status = stream_out(ostr, current);
+ current = XMLRPC_VectorNext(value);
+ }
+ ostr << "}";
+ break;
+ }
+ case xmlrpc_type_empty:
+ case xmlrpc_type_none:
+ default:
+ status = LLIOPipe::STATUS_ERROR;
+ LL_WARNS() << "Found an empty xmlrpc type.." << LL_ENDL;
+ // not much we can do here...
+ break;
+ };
+ return status;
}
LLFilterXMLRPCResponse2LLSD::LLFilterXMLRPCResponse2LLSD()
@@ -597,76 +597,76 @@ LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD()
}
LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!eos) return STATUS_BREAK;
- if(!buffer) return STATUS_ERROR;
-
- PUMP_DEBUG;
- // *FIX: This technique for reading data is far from optimal. We
- // need to have some kind of istream interface into the xml
- // parser...
- S32 bytes = buffer->countAfter(channels.in(), NULL);
- if(!bytes) return STATUS_ERROR;
- char* buf = new char[bytes + 1];
- buf[bytes] = '\0';
- buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
-
- //LL_DEBUGS() << "xmlrpc response: " << buf << LL_ENDL;
-
- PUMP_DEBUG;
- XMLRPC_REQUEST response = XMLRPC_REQUEST_FromXML(
- buf,
- bytes,
- NULL);
- if(!response)
- {
- LL_WARNS() << "XML -> SD Response unable to parse xml." << LL_ENDL;
- delete[] buf;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- LLBufferStream stream(channels, buffer.get());
- stream.precision(DEFAULT_PRECISION);
- if(XMLRPC_ResponseIsFault(response))
- {
- PUMP_DEBUG;
- stream << LLSDRPC_FAULT_HADER_1
- << XMLRPC_GetResponseFaultCode(response)
- << LLSDRPC_FAULT_HADER_2;
- const char* fault_str = XMLRPC_GetResponseFaultString(response);
- std::string fault_string;
- if(fault_str)
- {
- fault_string.assign(fault_str);
- }
- stream << "'" << LLSDNotationFormatter::escapeString(fault_string)
- << "'" <<LLSDRPC_FAULT_FOOTER;
- }
- else
- {
- PUMP_DEBUG;
- stream << LLSDRPC_RESPONSE_HEADER;
- XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
- if(param)
- {
- stream_out(stream, param);
- }
- stream << LLSDRPC_RESPONSE_FOOTER;
- }
- PUMP_DEBUG;
- XMLRPC_RequestFree(response, 1);
- delete[] buf;
- PUMP_DEBUG;
- return STATUS_DONE;
+ PUMP_DEBUG;
+ if(!eos) return STATUS_BREAK;
+ if(!buffer) return STATUS_ERROR;
+
+ PUMP_DEBUG;
+ // *FIX: This technique for reading data is far from optimal. We
+ // need to have some kind of istream interface into the xml
+ // parser...
+ S32 bytes = buffer->countAfter(channels.in(), NULL);
+ if(!bytes) return STATUS_ERROR;
+ char* buf = new char[bytes + 1];
+ buf[bytes] = '\0';
+ buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
+
+ //LL_DEBUGS() << "xmlrpc response: " << buf << LL_ENDL;
+
+ PUMP_DEBUG;
+ XMLRPC_REQUEST response = XMLRPC_REQUEST_FromXML(
+ buf,
+ bytes,
+ NULL);
+ if(!response)
+ {
+ LL_WARNS() << "XML -> SD Response unable to parse xml." << LL_ENDL;
+ delete[] buf;
+ return STATUS_ERROR;
+ }
+
+ PUMP_DEBUG;
+ LLBufferStream stream(channels, buffer.get());
+ stream.precision(DEFAULT_PRECISION);
+ if(XMLRPC_ResponseIsFault(response))
+ {
+ PUMP_DEBUG;
+ stream << LLSDRPC_FAULT_HADER_1
+ << XMLRPC_GetResponseFaultCode(response)
+ << LLSDRPC_FAULT_HADER_2;
+ const char* fault_str = XMLRPC_GetResponseFaultString(response);
+ std::string fault_string;
+ if(fault_str)
+ {
+ fault_string.assign(fault_str);
+ }
+ stream << "'" << LLSDNotationFormatter::escapeString(fault_string)
+ << "'" <<LLSDRPC_FAULT_FOOTER;
+ }
+ else
+ {
+ PUMP_DEBUG;
+ stream << LLSDRPC_RESPONSE_HEADER;
+ XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
+ if(param)
+ {
+ stream_out(stream, param);
+ }
+ stream << LLSDRPC_RESPONSE_FOOTER;
+ }
+ PUMP_DEBUG;
+ XMLRPC_RequestFree(response, 1);
+ delete[] buf;
+ PUMP_DEBUG;
+ return STATUS_DONE;
}
/**
@@ -681,98 +681,98 @@ LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD()
}
LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!eos) return STATUS_BREAK;
- if(!buffer) return STATUS_ERROR;
-
- PUMP_DEBUG;
- // *FIX: This technique for reading data is far from optimal. We
- // need to have some kind of istream interface into the xml
- // parser...
- S32 bytes = buffer->countAfter(channels.in(), NULL);
- if(!bytes) return STATUS_ERROR;
- char* buf = new char[bytes + 1];
- buf[bytes] = '\0';
- buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
-
- //LL_DEBUGS() << "xmlrpc request: " << buf << LL_ENDL;
-
- // Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if
- // values that are less than 0x20 are passed to it, except
- // 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage
- U8* cur_pBuf = (U8*)buf;
+ PUMP_DEBUG;
+ if(!eos) return STATUS_BREAK;
+ if(!buffer) return STATUS_ERROR;
+
+ PUMP_DEBUG;
+ // *FIX: This technique for reading data is far from optimal. We
+ // need to have some kind of istream interface into the xml
+ // parser...
+ S32 bytes = buffer->countAfter(channels.in(), NULL);
+ if(!bytes) return STATUS_ERROR;
+ char* buf = new char[bytes + 1];
+ buf[bytes] = '\0';
+ buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
+
+ //LL_DEBUGS() << "xmlrpc request: " << buf << LL_ENDL;
+
+ // Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if
+ // values that are less than 0x20 are passed to it, except
+ // 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage
+ U8* cur_pBuf = (U8*)buf;
U8 cur_char;
- for (S32 i=0; i<bytes; i++)
- {
+ for (S32 i=0; i<bytes; i++)
+ {
cur_char = *cur_pBuf;
- if ( cur_char < 0x20
+ if ( cur_char < 0x20
&& 0x09 != cur_char
&& 0x0a != cur_char
&& 0x0d != cur_char )
{
- *cur_pBuf = '?';
+ *cur_pBuf = '?';
+ }
+ ++cur_pBuf;
+ }
+
+ PUMP_DEBUG;
+ XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML(
+ buf,
+ bytes,
+ NULL);
+ if(!request)
+ {
+ LL_WARNS() << "XML -> SD Request process parse error." << LL_ENDL;
+ delete[] buf;
+ return STATUS_ERROR;
+ }
+
+ PUMP_DEBUG;
+ LLBufferStream stream(channels, buffer.get());
+ stream.precision(DEFAULT_PRECISION);
+ const char* name = XMLRPC_RequestGetMethodName(request);
+ stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "")
+ << LLSDRPC_REQUEST_HEADER_2;
+ XMLRPC_VALUE param = XMLRPC_RequestGetData(request);
+ if(param)
+ {
+ PUMP_DEBUG;
+ S32 size = XMLRPC_VectorSize(param);
+ if(size > 1)
+ {
+ // if there are multiple parameters, stuff the values into
+ // an array so that the next step in the chain can read them.
+ stream << "[";
+ }
+ XMLRPC_VALUE current = XMLRPC_VectorRewind(param);
+ bool needs_comma = false;
+ while(current)
+ {
+ if(needs_comma)
+ {
+ stream << ",";
+ }
+ needs_comma = true;
+ stream_out(stream, current);
+ current = XMLRPC_VectorNext(param);
+ }
+ if(size > 1)
+ {
+ // close the array
+ stream << "]";
}
- ++cur_pBuf;
- }
-
- PUMP_DEBUG;
- XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML(
- buf,
- bytes,
- NULL);
- if(!request)
- {
- LL_WARNS() << "XML -> SD Request process parse error." << LL_ENDL;
- delete[] buf;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- LLBufferStream stream(channels, buffer.get());
- stream.precision(DEFAULT_PRECISION);
- const char* name = XMLRPC_RequestGetMethodName(request);
- stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "")
- << LLSDRPC_REQUEST_HEADER_2;
- XMLRPC_VALUE param = XMLRPC_RequestGetData(request);
- if(param)
- {
- PUMP_DEBUG;
- S32 size = XMLRPC_VectorSize(param);
- if(size > 1)
- {
- // if there are multiple parameters, stuff the values into
- // an array so that the next step in the chain can read them.
- stream << "[";
- }
- XMLRPC_VALUE current = XMLRPC_VectorRewind(param);
- bool needs_comma = false;
- while(current)
- {
- if(needs_comma)
- {
- stream << ",";
- }
- needs_comma = true;
- stream_out(stream, current);
- current = XMLRPC_VectorNext(param);
- }
- if(size > 1)
- {
- // close the array
- stream << "]";
- }
- }
- stream << LLSDRPC_REQUEST_FOOTER;
- XMLRPC_RequestFree(request, 1);
- delete[] buf;
- PUMP_DEBUG;
- return STATUS_DONE;
+ }
+ stream << LLSDRPC_REQUEST_FOOTER;
+ XMLRPC_RequestFree(request, 1);
+ delete[] buf;
+ PUMP_DEBUG;
+ return STATUS_DONE;
}
diff --git a/indra/llmessage/llfiltersd2xmlrpc.h b/indra/llmessage/llfiltersd2xmlrpc.h
index 0c9a0dc95b..55938d3e2b 100644
--- a/indra/llmessage/llfiltersd2xmlrpc.h
+++ b/indra/llmessage/llfiltersd2xmlrpc.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfiltersd2xmlrpc.h
* @author Phoenix
* @date 2005-04-26
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,9 +38,9 @@
#include <iosfwd>
#include "lliopipe.h"
-/**
+/**
* @class LLFilterSD2XMLRPC
- * @brief Filter from serialized LLSD to an XMLRPC method call
+ * @brief Filter from serialized LLSD to an XMLRPC method call
*
* This clas provides common functionality for the LLFilterSD2XMLRPRC
* request and response classes.
@@ -48,19 +48,19 @@
class LLFilterSD2XMLRPC : public LLIOPipe
{
public:
- LLFilterSD2XMLRPC();
- virtual ~LLFilterSD2XMLRPC();
+ LLFilterSD2XMLRPC();
+ virtual ~LLFilterSD2XMLRPC();
protected:
- /**
- * @brief helper method
- */
- void streamOut(std::ostream& ostr, const LLSD& sd);
+ /**
+ * @brief helper method
+ */
+ void streamOut(std::ostream& ostr, const LLSD& sd);
};
-/**
+/**
* @class LLFilterSD2XMLRPCResponse
- * @brief Filter from serialized LLSD to an XMLRPC response
+ * @brief Filter from serialized LLSD to an XMLRPC response
*
* This class filters a serialized LLSD object to an xmlrpc
* repsonse. Since resonses are limited to a single param, the xmlrprc
@@ -85,31 +85,31 @@ protected:
class LLFilterSD2XMLRPCResponse : public LLFilterSD2XMLRPC
{
public:
- // constructor
- LLFilterSD2XMLRPCResponse();
+ // constructor
+ LLFilterSD2XMLRPCResponse();
- // destructor
- virtual ~LLFilterSD2XMLRPCResponse();
+ // destructor
+ virtual ~LLFilterSD2XMLRPCResponse();
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
};
-/**
+/**
* @class LLFilterSD2XMLRPCRequest
- * @brief Filter from serialized LLSD to an XMLRPC method call
+ * @brief Filter from serialized LLSD to an XMLRPC method call
*
* This class will accept any kind of serialized LLSD object, but you
* probably want to have an array on the outer boundary since this
@@ -141,38 +141,38 @@ protected:
class LLFilterSD2XMLRPCRequest : public LLFilterSD2XMLRPC
{
public:
- // constructor
- LLFilterSD2XMLRPCRequest();
+ // constructor
+ LLFilterSD2XMLRPCRequest();
- // constructor
- LLFilterSD2XMLRPCRequest(const char* method);
+ // constructor
+ LLFilterSD2XMLRPCRequest(const char* method);
- // destructor
- virtual ~LLFilterSD2XMLRPCRequest();
+ // destructor
+ virtual ~LLFilterSD2XMLRPCRequest();
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- // The method name of this request.
- std::string mMethod;
+ // The method name of this request.
+ std::string mMethod;
};
-/**
+/**
* @class LLFilterXMLRPCResponse2LLSD
- * @brief Filter from serialized XMLRPC method response to LLSD
+ * @brief Filter from serialized XMLRPC method response to LLSD
*
* The xmlrpc spec states that responses can only have one element
* which can be of any supported type.
@@ -188,33 +188,33 @@ protected:
class LLFilterXMLRPCResponse2LLSD : public LLIOPipe
{
public:
- // constructor
- LLFilterXMLRPCResponse2LLSD();
+ // constructor
+ LLFilterXMLRPCResponse2LLSD();
- // destructor
- virtual ~LLFilterXMLRPCResponse2LLSD();
+ // destructor
+ virtual ~LLFilterXMLRPCResponse2LLSD();
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
};
-/**
+/**
* @class LLFilterXMLRPCRequest2LLSD
- * @brief Filter from serialized XMLRPC method call to LLSD
+ * @brief Filter from serialized XMLRPC method call to LLSD
*
* This takes in xml of the form:
* <code>
@@ -231,26 +231,26 @@ protected:
class LLFilterXMLRPCRequest2LLSD : public LLIOPipe
{
public:
- // constructor
- LLFilterXMLRPCRequest2LLSD();
+ // constructor
+ LLFilterXMLRPCRequest2LLSD();
- // destructor
- virtual ~LLFilterXMLRPCRequest2LLSD();
+ // destructor
+ virtual ~LLFilterXMLRPCRequest2LLSD();
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
};
diff --git a/indra/llmessage/llfollowcamparams.h b/indra/llmessage/llfollowcamparams.h
index 25208031db..f24b362c08 100644
--- a/indra/llmessage/llfollowcamparams.h
+++ b/indra/llmessage/llfollowcamparams.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfollowcamparams.h
* @brief Follow camera parameters.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,30 +30,30 @@
//Ventrella Follow Cam Script Stuff
enum EFollowCamAttributes {
- FOLLOWCAM_PITCH = 0,
- FOLLOWCAM_FOCUS_OFFSET,
- FOLLOWCAM_FOCUS_OFFSET_X, //this HAS to come after FOLLOWCAM_FOCUS_OFFSET in this list
- FOLLOWCAM_FOCUS_OFFSET_Y,
- FOLLOWCAM_FOCUS_OFFSET_Z,
- FOLLOWCAM_POSITION_LAG,
- FOLLOWCAM_FOCUS_LAG,
- FOLLOWCAM_DISTANCE,
- FOLLOWCAM_BEHINDNESS_ANGLE,
- FOLLOWCAM_BEHINDNESS_LAG,
- FOLLOWCAM_POSITION_THRESHOLD,
- FOLLOWCAM_FOCUS_THRESHOLD,
- FOLLOWCAM_ACTIVE,
- FOLLOWCAM_POSITION,
- FOLLOWCAM_POSITION_X, //this HAS to come after FOLLOWCAM_POSITION in this list
- FOLLOWCAM_POSITION_Y,
- FOLLOWCAM_POSITION_Z,
- FOLLOWCAM_FOCUS,
- FOLLOWCAM_FOCUS_X, //this HAS to come after FOLLOWCAM_FOCUS in this list
- FOLLOWCAM_FOCUS_Y,
- FOLLOWCAM_FOCUS_Z,
- FOLLOWCAM_POSITION_LOCKED,
- FOLLOWCAM_FOCUS_LOCKED,
- NUM_FOLLOWCAM_ATTRIBUTES
+ FOLLOWCAM_PITCH = 0,
+ FOLLOWCAM_FOCUS_OFFSET,
+ FOLLOWCAM_FOCUS_OFFSET_X, //this HAS to come after FOLLOWCAM_FOCUS_OFFSET in this list
+ FOLLOWCAM_FOCUS_OFFSET_Y,
+ FOLLOWCAM_FOCUS_OFFSET_Z,
+ FOLLOWCAM_POSITION_LAG,
+ FOLLOWCAM_FOCUS_LAG,
+ FOLLOWCAM_DISTANCE,
+ FOLLOWCAM_BEHINDNESS_ANGLE,
+ FOLLOWCAM_BEHINDNESS_LAG,
+ FOLLOWCAM_POSITION_THRESHOLD,
+ FOLLOWCAM_FOCUS_THRESHOLD,
+ FOLLOWCAM_ACTIVE,
+ FOLLOWCAM_POSITION,
+ FOLLOWCAM_POSITION_X, //this HAS to come after FOLLOWCAM_POSITION in this list
+ FOLLOWCAM_POSITION_Y,
+ FOLLOWCAM_POSITION_Z,
+ FOLLOWCAM_FOCUS,
+ FOLLOWCAM_FOCUS_X, //this HAS to come after FOLLOWCAM_FOCUS in this list
+ FOLLOWCAM_FOCUS_Y,
+ FOLLOWCAM_FOCUS_Z,
+ FOLLOWCAM_POSITION_LOCKED,
+ FOLLOWCAM_FOCUS_LOCKED,
+ NUM_FOLLOWCAM_ATTRIBUTES
};
//end Ventrella
diff --git a/indra/llmessage/llgenericstreamingmessage.cpp b/indra/llmessage/llgenericstreamingmessage.cpp
index 8627675c54..d7f4860a5f 100644
--- a/indra/llmessage/llgenericstreamingmessage.cpp
+++ b/indra/llmessage/llgenericstreamingmessage.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/llgenericstreamingmessage.h b/indra/llmessage/llgenericstreamingmessage.h
index 9ac9719ea1..a24e6435bd 100644
--- a/indra/llmessage/llgenericstreamingmessage.h
+++ b/indra/llmessage/llgenericstreamingmessage.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp
index 30e4109729..264d64bb50 100644
--- a/indra/llmessage/llhost.cpp
+++ b/indra/llmessage/llhost.cpp
@@ -1,176 +1,176 @@
-/**
- * @file llhost.cpp
- * @brief Encapsulates an IP address and a port.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llhost.h"
-
-#include "llerror.h"
-
-#if LL_WINDOWS
- #define WIN32_LEAN_AND_MEAN
- #include <winsock2.h>
-#else
- #include <netdb.h>
- #include <netinet/in.h> // ntonl()
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-#endif
-
-LLHost::LLHost(const std::string& ip_and_port)
-{
- std::string::size_type colon_index = ip_and_port.find(":");
- if (colon_index == std::string::npos)
- {
- mIP = ip_string_to_u32(ip_and_port.c_str());
- mPort = 0;
- }
- else
- {
- std::string ip_str(ip_and_port, 0, colon_index);
- std::string port_str(ip_and_port, colon_index+1);
-
- mIP = ip_string_to_u32(ip_str.c_str());
- mPort = atol(port_str.c_str());
- }
-}
-
-std::string LLHost::getString() const
-{
- return llformat("%s:%u", u32_to_ip_string(mIP), mPort);
-}
-
-
-std::string LLHost::getIPandPort() const
-{
- return getString();
-}
-
-
-std::string LLHost::getIPString() const
-{
- return std::string( u32_to_ip_string( mIP ) );
-}
-
-
-std::string LLHost::getHostName() const
-{
- hostent* he;
- if (INVALID_HOST_IP_ADDRESS == mIP)
- {
- LL_WARNS() << "LLHost::getHostName() : Invalid IP address" << LL_ENDL;
- return std::string();
- }
- he = gethostbyaddr((char *)&mIP, sizeof(mIP), AF_INET);
- if (!he)
- {
-#if LL_WINDOWS
- LL_WARNS() << "LLHost::getHostName() : Couldn't find host name for address " << mIP << ", Error: "
- << WSAGetLastError() << LL_ENDL;
-#else
- LL_WARNS() << "LLHost::getHostName() : Couldn't find host name for address " << mIP << ", Error: "
- << h_errno << LL_ENDL;
-#endif
- return std::string();
- }
- else
- {
- return ll_safe_string(he->h_name);
- }
-}
-
-bool LLHost::setHostByName(const std::string& hostname)
-{
- hostent *he;
- std::string local_name(hostname);
-
-#if LL_WINDOWS
- // We may need an equivalent for Linux, but not sure - djs
- LLStringUtil::toUpper(local_name);
-#endif
-
- he = gethostbyname(local_name.c_str());
- if(!he)
- {
- U32 ip_address = ip_string_to_u32(hostname.c_str());
- he = gethostbyaddr((char *)&ip_address, sizeof(ip_address), AF_INET);
- }
-
- if (he)
- {
- mIP = *(U32 *)he->h_addr_list[0];
- return true;
- }
- else
- {
- setAddress(local_name);
-
- // In windows, h_errno is a macro for WSAGetLastError(), so store value here
- S32 error_number = h_errno;
- switch(error_number)
- {
- case TRY_AGAIN: // XXX how to handle this case?
- LL_WARNS() << "LLHost::setAddress(): try again" << LL_ENDL;
- break;
- case HOST_NOT_FOUND:
- case NO_ADDRESS: // NO_DATA
- LL_WARNS() << "LLHost::setAddress(): host not found" << LL_ENDL;
- break;
- case NO_RECOVERY:
- LL_WARNS() << "LLHost::setAddress(): unrecoverable error" << LL_ENDL;
- break;
- default:
- LL_WARNS() << "LLHost::setAddress(): unknown error - " << error_number << LL_ENDL;
- break;
- }
- return false;
- }
-}
-
-LLHost& LLHost::operator=(const LLHost &rhs)
-{
- if (this != &rhs)
- {
- set(rhs.getAddress(), rhs.getPort());
- }
- return *this;
-}
-
-
-std::ostream& operator<< (std::ostream& os, const LLHost &hh)
-{
- os << u32_to_ip_string(hh.mIP) << ":" << hh.mPort ;
- return os;
-}
-
-
-//std::istream& operator>> (std::istream& is, LLHost &rh)
-//{
-// is >> rh.mIP;
-// is >> rh.mPort;
-// return is;
-//}
+/**
+ * @file llhost.cpp
+ * @brief Encapsulates an IP address and a port.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llhost.h"
+
+#include "llerror.h"
+
+#if LL_WINDOWS
+ #define WIN32_LEAN_AND_MEAN
+ #include <winsock2.h>
+#else
+ #include <netdb.h>
+ #include <netinet/in.h> // ntonl()
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+#endif
+
+LLHost::LLHost(const std::string& ip_and_port)
+{
+ std::string::size_type colon_index = ip_and_port.find(":");
+ if (colon_index == std::string::npos)
+ {
+ mIP = ip_string_to_u32(ip_and_port.c_str());
+ mPort = 0;
+ }
+ else
+ {
+ std::string ip_str(ip_and_port, 0, colon_index);
+ std::string port_str(ip_and_port, colon_index+1);
+
+ mIP = ip_string_to_u32(ip_str.c_str());
+ mPort = atol(port_str.c_str());
+ }
+}
+
+std::string LLHost::getString() const
+{
+ return llformat("%s:%u", u32_to_ip_string(mIP), mPort);
+}
+
+
+std::string LLHost::getIPandPort() const
+{
+ return getString();
+}
+
+
+std::string LLHost::getIPString() const
+{
+ return std::string( u32_to_ip_string( mIP ) );
+}
+
+
+std::string LLHost::getHostName() const
+{
+ hostent* he;
+ if (INVALID_HOST_IP_ADDRESS == mIP)
+ {
+ LL_WARNS() << "LLHost::getHostName() : Invalid IP address" << LL_ENDL;
+ return std::string();
+ }
+ he = gethostbyaddr((char *)&mIP, sizeof(mIP), AF_INET);
+ if (!he)
+ {
+#if LL_WINDOWS
+ LL_WARNS() << "LLHost::getHostName() : Couldn't find host name for address " << mIP << ", Error: "
+ << WSAGetLastError() << LL_ENDL;
+#else
+ LL_WARNS() << "LLHost::getHostName() : Couldn't find host name for address " << mIP << ", Error: "
+ << h_errno << LL_ENDL;
+#endif
+ return std::string();
+ }
+ else
+ {
+ return ll_safe_string(he->h_name);
+ }
+}
+
+bool LLHost::setHostByName(const std::string& hostname)
+{
+ hostent *he;
+ std::string local_name(hostname);
+
+#if LL_WINDOWS
+ // We may need an equivalent for Linux, but not sure - djs
+ LLStringUtil::toUpper(local_name);
+#endif
+
+ he = gethostbyname(local_name.c_str());
+ if(!he)
+ {
+ U32 ip_address = ip_string_to_u32(hostname.c_str());
+ he = gethostbyaddr((char *)&ip_address, sizeof(ip_address), AF_INET);
+ }
+
+ if (he)
+ {
+ mIP = *(U32 *)he->h_addr_list[0];
+ return true;
+ }
+ else
+ {
+ setAddress(local_name);
+
+ // In windows, h_errno is a macro for WSAGetLastError(), so store value here
+ S32 error_number = h_errno;
+ switch(error_number)
+ {
+ case TRY_AGAIN: // XXX how to handle this case?
+ LL_WARNS() << "LLHost::setAddress(): try again" << LL_ENDL;
+ break;
+ case HOST_NOT_FOUND:
+ case NO_ADDRESS: // NO_DATA
+ LL_WARNS() << "LLHost::setAddress(): host not found" << LL_ENDL;
+ break;
+ case NO_RECOVERY:
+ LL_WARNS() << "LLHost::setAddress(): unrecoverable error" << LL_ENDL;
+ break;
+ default:
+ LL_WARNS() << "LLHost::setAddress(): unknown error - " << error_number << LL_ENDL;
+ break;
+ }
+ return false;
+ }
+}
+
+LLHost& LLHost::operator=(const LLHost &rhs)
+{
+ if (this != &rhs)
+ {
+ set(rhs.getAddress(), rhs.getPort());
+ }
+ return *this;
+}
+
+
+std::ostream& operator<< (std::ostream& os, const LLHost &hh)
+{
+ os << u32_to_ip_string(hh.mIP) << ":" << hh.mPort ;
+ return os;
+}
+
+
+//std::istream& operator>> (std::istream& is, LLHost &rh)
+//{
+// is >> rh.mIP;
+// is >> rh.mPort;
+// return is;
+//}
diff --git a/indra/llmessage/llhost.h b/indra/llmessage/llhost.h
index dd12e381d4..1a3a48eede 100644
--- a/indra/llmessage/llhost.h
+++ b/indra/llmessage/llhost.h
@@ -1,154 +1,154 @@
-/**
- * @file llhost.h
- * @brief a LLHost uniquely defines a host (Simulator, Proxy or other)
- * across the network
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLHOST_H
-#define LL_LLHOST_H
-
-#include <iostream>
-#include <string>
-
-#include "net.h"
-
-const U32 INVALID_PORT = 0;
-const U32 INVALID_HOST_IP_ADDRESS = 0x0;
-
-class LLHost {
-protected:
- U32 mPort;
- U32 mIP;
- std::string mUntrustedSimCap;
-public:
-
- // CREATORS
- LLHost()
- : mPort(INVALID_PORT),
- mIP(INVALID_HOST_IP_ADDRESS)
- { } // STL's hash_map expect this T()
-
- LLHost( U32 ipv4_addr, U32 port )
- : mPort( port )
- {
- mIP = ipv4_addr;
- }
-
- LLHost( const std::string& ipv4_addr, U32 port )
- : mPort( port )
- {
- mIP = ip_string_to_u32(ipv4_addr.c_str());
- }
-
- explicit LLHost(const U64 ip_port)
- {
- U32 ip = (U32)(ip_port >> 32);
- U32 port = (U32)(ip_port & (U64)0xFFFFFFFF);
- mIP = ip;
- mPort = port;
- }
-
- explicit LLHost(const std::string& ip_and_port);
-
- ~LLHost()
- { }
-
- // MANIPULATORS
- void set( U32 ip, U32 port ) { mIP = ip; mPort = port; }
- void set( const std::string& ipstr, U32 port ) { mIP = ip_string_to_u32(ipstr.c_str()); mPort = port; }
- void setAddress( const std::string& ipstr ) { mIP = ip_string_to_u32(ipstr.c_str()); }
- void setAddress( U32 ip ) { mIP = ip; }
- void setPort( U32 port ) { mPort = port; }
- bool setHostByName(const std::string& hname);
-
- LLHost& operator=(const LLHost &rhs);
- void invalidate() { mIP = INVALID_HOST_IP_ADDRESS; mPort = INVALID_PORT;};
-
- // READERS
- U32 getAddress() const { return mIP; }
- U32 getPort() const { return mPort; }
- bool isOk() const { return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
- bool isInvalid() { return (mIP == INVALID_HOST_IP_ADDRESS) || (mPort == INVALID_PORT); }
- size_t hash() const { return (mIP << 16) | (mPort & 0xffff); }
- std::string getString() const;
- std::string getIPString() const;
- std::string getHostName() const;
- std::string getIPandPort() const;
-
- std::string getUntrustedSimulatorCap() const { return mUntrustedSimCap; }
- void setUntrustedSimulatorCap(const std::string &capurl) { mUntrustedSimCap = capurl; }
-
- friend std::ostream& operator<< (std::ostream& os, const LLHost &hh);
-
- // This operator is not well defined. does it expect a
- // "192.168.1.1:80" notation or "int int" format? Phoenix 2007-05-18
- //friend std::istream& operator>> (std::istream& is, LLHost &hh);
-
- friend bool operator==( const LLHost &lhs, const LLHost &rhs );
- friend bool operator!=( const LLHost &lhs, const LLHost &rhs );
- friend bool operator<(const LLHost &lhs, const LLHost &rhs);
-};
-
-
-// Function Object required for STL templates using LLHost as key
-class LLHostHash
-{
-public:
- size_t operator() (const LLHost &hh) const { return hh.hash(); }
-};
-
-
-inline bool operator==( const LLHost &lhs, const LLHost &rhs )
-{
- return (lhs.mIP == rhs.mIP) && (lhs.mPort == rhs.mPort);
-}
-
-inline bool operator!=( const LLHost &lhs, const LLHost &rhs )
-{
- return (lhs.mIP != rhs.mIP) || (lhs.mPort != rhs.mPort);
-}
-
-inline bool operator<(const LLHost &lhs, const LLHost &rhs)
-{
- if (lhs.mIP < rhs.mIP)
- {
- return true;
- }
- if (lhs.mIP > rhs.mIP)
- {
- return false;
- }
-
- if (lhs.mPort < rhs.mPort)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
-#endif // LL_LLHOST_H
+/**
+ * @file llhost.h
+ * @brief a LLHost uniquely defines a host (Simulator, Proxy or other)
+ * across the network
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLHOST_H
+#define LL_LLHOST_H
+
+#include <iostream>
+#include <string>
+
+#include "net.h"
+
+const U32 INVALID_PORT = 0;
+const U32 INVALID_HOST_IP_ADDRESS = 0x0;
+
+class LLHost {
+protected:
+ U32 mPort;
+ U32 mIP;
+ std::string mUntrustedSimCap;
+public:
+
+ // CREATORS
+ LLHost()
+ : mPort(INVALID_PORT),
+ mIP(INVALID_HOST_IP_ADDRESS)
+ { } // STL's hash_map expect this T()
+
+ LLHost( U32 ipv4_addr, U32 port )
+ : mPort( port )
+ {
+ mIP = ipv4_addr;
+ }
+
+ LLHost( const std::string& ipv4_addr, U32 port )
+ : mPort( port )
+ {
+ mIP = ip_string_to_u32(ipv4_addr.c_str());
+ }
+
+ explicit LLHost(const U64 ip_port)
+ {
+ U32 ip = (U32)(ip_port >> 32);
+ U32 port = (U32)(ip_port & (U64)0xFFFFFFFF);
+ mIP = ip;
+ mPort = port;
+ }
+
+ explicit LLHost(const std::string& ip_and_port);
+
+ ~LLHost()
+ { }
+
+ // MANIPULATORS
+ void set( U32 ip, U32 port ) { mIP = ip; mPort = port; }
+ void set( const std::string& ipstr, U32 port ) { mIP = ip_string_to_u32(ipstr.c_str()); mPort = port; }
+ void setAddress( const std::string& ipstr ) { mIP = ip_string_to_u32(ipstr.c_str()); }
+ void setAddress( U32 ip ) { mIP = ip; }
+ void setPort( U32 port ) { mPort = port; }
+ bool setHostByName(const std::string& hname);
+
+ LLHost& operator=(const LLHost &rhs);
+ void invalidate() { mIP = INVALID_HOST_IP_ADDRESS; mPort = INVALID_PORT;};
+
+ // READERS
+ U32 getAddress() const { return mIP; }
+ U32 getPort() const { return mPort; }
+ bool isOk() const { return (mIP != INVALID_HOST_IP_ADDRESS) && (mPort != INVALID_PORT); }
+ bool isInvalid() { return (mIP == INVALID_HOST_IP_ADDRESS) || (mPort == INVALID_PORT); }
+ size_t hash() const { return (mIP << 16) | (mPort & 0xffff); }
+ std::string getString() const;
+ std::string getIPString() const;
+ std::string getHostName() const;
+ std::string getIPandPort() const;
+
+ std::string getUntrustedSimulatorCap() const { return mUntrustedSimCap; }
+ void setUntrustedSimulatorCap(const std::string &capurl) { mUntrustedSimCap = capurl; }
+
+ friend std::ostream& operator<< (std::ostream& os, const LLHost &hh);
+
+ // This operator is not well defined. does it expect a
+ // "192.168.1.1:80" notation or "int int" format? Phoenix 2007-05-18
+ //friend std::istream& operator>> (std::istream& is, LLHost &hh);
+
+ friend bool operator==( const LLHost &lhs, const LLHost &rhs );
+ friend bool operator!=( const LLHost &lhs, const LLHost &rhs );
+ friend bool operator<(const LLHost &lhs, const LLHost &rhs);
+};
+
+
+// Function Object required for STL templates using LLHost as key
+class LLHostHash
+{
+public:
+ size_t operator() (const LLHost &hh) const { return hh.hash(); }
+};
+
+
+inline bool operator==( const LLHost &lhs, const LLHost &rhs )
+{
+ return (lhs.mIP == rhs.mIP) && (lhs.mPort == rhs.mPort);
+}
+
+inline bool operator!=( const LLHost &lhs, const LLHost &rhs )
+{
+ return (lhs.mIP != rhs.mIP) || (lhs.mPort != rhs.mPort);
+}
+
+inline bool operator<(const LLHost &lhs, const LLHost &rhs)
+{
+ if (lhs.mIP < rhs.mIP)
+ {
+ return true;
+ }
+ if (lhs.mIP > rhs.mIP)
+ {
+ return false;
+ }
+
+ if (lhs.mPort < rhs.mPort)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+#endif // LL_LLHOST_H
diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp
index 6e9598a0a3..65bdfaff7e 100644
--- a/indra/llmessage/llhttpnode.cpp
+++ b/indra/llmessage/llhttpnode.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llhttpnode.cpp
* @brief Implementation of classes for generic HTTP/LSL/REST handling.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,77 +44,77 @@ const std::string CONTEXT_WILDCARD("wildcard");
/**
* LLHTTPNode
*/
-
+
class LLHTTPNode::Impl
{
public:
- typedef std::map<std::string, LLHTTPNode*> ChildMap;
-
- ChildMap mNamedChildren;
- LLHTTPNode* mWildcardChild;
- std::string mWildcardName;
- std::string mWildcardKey;
- LLHTTPNode* mParentNode;
-
- Impl() : mWildcardChild(NULL), mParentNode(NULL) { }
-
- LLHTTPNode* findNamedChild(const std::string& name) const;
+ typedef std::map<std::string, LLHTTPNode*> ChildMap;
+
+ ChildMap mNamedChildren;
+ LLHTTPNode* mWildcardChild;
+ std::string mWildcardName;
+ std::string mWildcardKey;
+ LLHTTPNode* mParentNode;
+
+ Impl() : mWildcardChild(NULL), mParentNode(NULL) { }
+
+ LLHTTPNode* findNamedChild(const std::string& name) const;
};
LLHTTPNode* LLHTTPNode::Impl::findNamedChild(const std::string& name) const
{
- LLHTTPNode* child = get_ptr_in_map(mNamedChildren, name);
+ LLHTTPNode* child = get_ptr_in_map(mNamedChildren, name);
- if (!child && ((name[0] == '*') || (name == mWildcardName)))
- {
- child = mWildcardChild;
- }
-
- return child;
+ if (!child && ((name[0] == '*') || (name == mWildcardName)))
+ {
+ child = mWildcardChild;
+ }
+
+ return child;
}
LLHTTPNode::LLHTTPNode()
- : impl(* new Impl)
+ : impl(* new Impl)
{
}
// virtual
LLHTTPNode::~LLHTTPNode()
{
- std::for_each(impl.mNamedChildren.begin(), impl.mNamedChildren.end(), DeletePairedPointer());
- impl.mNamedChildren.clear();
+ std::for_each(impl.mNamedChildren.begin(), impl.mNamedChildren.end(), DeletePairedPointer());
+ impl.mNamedChildren.clear();
+
+ delete impl.mWildcardChild;
- delete impl.mWildcardChild;
-
- delete &impl;
+ delete &impl;
}
namespace {
- struct NotImplemented: public LLException
- {
- NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
- };
+ struct NotImplemented: public LLException
+ {
+ NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
+ };
}
// virtual
LLSD LLHTTPNode::simpleGet() const
{
- LLTHROW(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePut(const LLSD& input) const
{
- LLTHROW(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
LLSD LLHTTPNode::simplePost(const LLSD& input) const
{
- LLTHROW(NotImplemented());
+ LLTHROW(NotImplemented());
}
@@ -122,42 +122,42 @@ LLSD LLHTTPNode::simplePost(const LLSD& input) const
void LLHTTPNode::get(LLHTTPNode::ResponsePtr response, const LLSD& context) const
{
LL_PROFILE_ZONE_SCOPED;
- try
- {
- response->result(simpleGet());
- }
- catch (NotImplemented&)
- {
- response->methodNotAllowed();
- }
+ try
+ {
+ response->result(simpleGet());
+ }
+ catch (NotImplemented&)
+ {
+ response->methodNotAllowed();
+ }
}
// virtual
void LLHTTPNode::put(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const
{
LL_PROFILE_ZONE_SCOPED;
- try
- {
- response->result(simplePut(input));
- }
- catch (NotImplemented&)
- {
- response->methodNotAllowed();
- }
+ try
+ {
+ response->result(simplePut(input));
+ }
+ catch (NotImplemented&)
+ {
+ response->methodNotAllowed();
+ }
}
// virtual
void LLHTTPNode::post(LLHTTPNode::ResponsePtr response, const LLSD& context, const LLSD& input) const
{
LL_PROFILE_ZONE_SCOPED;
- try
- {
- response->result(simplePost(input));
- }
- catch (NotImplemented&)
- {
- response->methodNotAllowed();
- }
+ try
+ {
+ response->result(simplePost(input));
+ }
+ catch (NotImplemented&)
+ {
+ response->methodNotAllowed();
+ }
}
// virtual
@@ -166,11 +166,11 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
LL_PROFILE_ZONE_SCOPED;
try
{
- response->result(simpleDel(context));
+ response->result(simpleDel(context));
}
catch (NotImplemented&)
{
- response->methodNotAllowed();
+ response->methodNotAllowed();
}
}
@@ -178,218 +178,218 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
// virtual
LLSD LLHTTPNode::simpleDel(const LLSD&) const
{
- LLTHROW(NotImplemented());
+ LLTHROW(NotImplemented());
}
// virtual
void LLHTTPNode::options(ResponsePtr response, const LLSD& context) const
{
- //LL_INFOS() << "options context: " << context << LL_ENDL;
- LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
+ //LL_INFOS() << "options context: " << context << LL_ENDL;
+ LL_DEBUGS("LLHTTPNode") << "context: " << context << LL_ENDL;
- // default implementation constructs an url to the documentation.
- // *TODO: Check for 'Host' header instead of 'host' header?
- std::string host(
- context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_IN_HEADER_HOST].asString());
- if(host.empty())
- {
- response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
- return;
- }
- std::ostringstream ostr;
- ostr << "http://" << host << "/web/server/api";
- ostr << context[CONTEXT_REQUEST][CONTEXT_PATH].asString();
- static const std::string DOC_HEADER("X-Documentation-URL");
- response->addHeader(DOC_HEADER, ostr.str());
- response->status(HTTP_OK, "OK");
+ // default implementation constructs an url to the documentation.
+ // *TODO: Check for 'Host' header instead of 'host' header?
+ std::string host(
+ context[CONTEXT_REQUEST][CONTEXT_HEADERS][HTTP_IN_HEADER_HOST].asString());
+ if(host.empty())
+ {
+ response->status(HTTP_BAD_REQUEST, "Bad Request -- need Host header");
+ return;
+ }
+ std::ostringstream ostr;
+ ostr << "http://" << host << "/web/server/api";
+ ostr << context[CONTEXT_REQUEST][CONTEXT_PATH].asString();
+ static const std::string DOC_HEADER("X-Documentation-URL");
+ response->addHeader(DOC_HEADER, ostr.str());
+ response->status(HTTP_OK, "OK");
}
// virtual
LLHTTPNode* LLHTTPNode::getChild(const std::string& name, LLSD& context) const
{
- LLHTTPNode* namedChild = get_ptr_in_map(impl.mNamedChildren, name);
- if (namedChild)
- {
- return namedChild;
- }
-
- if (impl.mWildcardChild
- && impl.mWildcardChild->validate(name, context))
- {
- context[CONTEXT_REQUEST][CONTEXT_WILDCARD][impl.mWildcardKey] = name;
- return impl.mWildcardChild;
- }
-
- return NULL;
+ LLHTTPNode* namedChild = get_ptr_in_map(impl.mNamedChildren, name);
+ if (namedChild)
+ {
+ return namedChild;
+ }
+
+ if (impl.mWildcardChild
+ && impl.mWildcardChild->validate(name, context))
+ {
+ context[CONTEXT_REQUEST][CONTEXT_WILDCARD][impl.mWildcardKey] = name;
+ return impl.mWildcardChild;
+ }
+
+ return NULL;
}
// virtual
bool LLHTTPNode::handles(const LLSD& remainder, LLSD& context) const
{
- return remainder.size() == 0;
+ return remainder.size() == 0;
}
// virtual
bool LLHTTPNode::validate(const std::string& name, LLSD& context) const
{
- return false;
+ return false;
}
const LLHTTPNode* LLHTTPNode::traverse(
- const std::string& path, LLSD& context) const
+ const std::string& path, LLSD& context) const
{
- typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
- tokenizer tokens(path, sep);
- tokenizer::iterator iter = tokens.begin();
- tokenizer::iterator end = tokens.end();
+ typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
+ tokenizer tokens(path, sep);
+ tokenizer::iterator iter = tokens.begin();
+ tokenizer::iterator end = tokens.end();
- const LLHTTPNode* node = this;
- for(; iter != end; ++iter)
- {
- LLHTTPNode* child = node->getChild(*iter, context);
- if(!child)
- {
- LL_DEBUGS() << "LLHTTPNode::traverse: Couldn't find '" << *iter << "'" << LL_ENDL;
- break;
- }
- LL_DEBUGS() << "LLHTTPNode::traverse: Found '" << *iter << "'" << LL_ENDL;
-
- node = child;
- }
+ const LLHTTPNode* node = this;
+ for(; iter != end; ++iter)
+ {
+ LLHTTPNode* child = node->getChild(*iter, context);
+ if(!child)
+ {
+ LL_DEBUGS() << "LLHTTPNode::traverse: Couldn't find '" << *iter << "'" << LL_ENDL;
+ break;
+ }
+ LL_DEBUGS() << "LLHTTPNode::traverse: Found '" << *iter << "'" << LL_ENDL;
+
+ node = child;
+ }
- LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
- for(; iter != end; ++iter)
- {
- remainder.append(*iter);
- }
+ LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
+ for(; iter != end; ++iter)
+ {
+ remainder.append(*iter);
+ }
- return node->handles(remainder, context) ? node : NULL;
+ return node->handles(remainder, context) ? node : NULL;
}
void LLHTTPNode::addNode(const std::string& path, LLHTTPNode* nodeToAdd)
{
- typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
- tokenizer tokens(path, sep);
- tokenizer::iterator iter = tokens.begin();
- tokenizer::iterator end = tokens.end();
-
- LLHTTPNode* node = this;
- for(; iter != end; ++iter)
- {
- LLHTTPNode* child = node->impl.findNamedChild(*iter);
- if (!child) { break; }
- node = child;
- }
-
- if (iter == end)
- {
- LL_WARNS() << "LLHTTPNode::addNode: already a node that handles "
- << path << LL_ENDL;
- return;
- }
-
- while (true)
- {
- std::string pathPart = *iter;
-
- ++iter;
- bool lastOne = iter == end;
-
- LLHTTPNode* nextNode = lastOne ? nodeToAdd : new LLHTTPNode();
-
- switch (pathPart[0])
- {
- case '<':
- // *NOTE: This should really validate that it is of
- // the proper form: <wildcardkey> so that the substr()
- // generates the correct key name.
- node->impl.mWildcardChild = nextNode;
- node->impl.mWildcardName = pathPart;
- if(node->impl.mWildcardKey.empty())
- {
- node->impl.mWildcardKey = pathPart.substr(
- 1,
- pathPart.size() - 2);
- }
- break;
- case '*':
- node->impl.mWildcardChild = nextNode;
- if(node->impl.mWildcardName.empty())
- {
- node->impl.mWildcardName = pathPart;
- }
- break;
-
- default:
- node->impl.mNamedChildren[pathPart] = nextNode;
- }
- nextNode->impl.mParentNode = node;
-
- if (lastOne) break;
- node = nextNode;
- }
+ typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
+ tokenizer tokens(path, sep);
+ tokenizer::iterator iter = tokens.begin();
+ tokenizer::iterator end = tokens.end();
+
+ LLHTTPNode* node = this;
+ for(; iter != end; ++iter)
+ {
+ LLHTTPNode* child = node->impl.findNamedChild(*iter);
+ if (!child) { break; }
+ node = child;
+ }
+
+ if (iter == end)
+ {
+ LL_WARNS() << "LLHTTPNode::addNode: already a node that handles "
+ << path << LL_ENDL;
+ return;
+ }
+
+ while (true)
+ {
+ std::string pathPart = *iter;
+
+ ++iter;
+ bool lastOne = iter == end;
+
+ LLHTTPNode* nextNode = lastOne ? nodeToAdd : new LLHTTPNode();
+
+ switch (pathPart[0])
+ {
+ case '<':
+ // *NOTE: This should really validate that it is of
+ // the proper form: <wildcardkey> so that the substr()
+ // generates the correct key name.
+ node->impl.mWildcardChild = nextNode;
+ node->impl.mWildcardName = pathPart;
+ if(node->impl.mWildcardKey.empty())
+ {
+ node->impl.mWildcardKey = pathPart.substr(
+ 1,
+ pathPart.size() - 2);
+ }
+ break;
+ case '*':
+ node->impl.mWildcardChild = nextNode;
+ if(node->impl.mWildcardName.empty())
+ {
+ node->impl.mWildcardName = pathPart;
+ }
+ break;
+
+ default:
+ node->impl.mNamedChildren[pathPart] = nextNode;
+ }
+ nextNode->impl.mParentNode = node;
+
+ if (lastOne) break;
+ node = nextNode;
+ }
}
static void append_node_paths(LLSD& result,
- const std::string& name, const LLHTTPNode* node)
+ const std::string& name, const LLHTTPNode* node)
{
- result.append(name);
-
- LLSD paths = node->allNodePaths();
- LLSD::array_const_iterator i = paths.beginArray();
- LLSD::array_const_iterator end = paths.endArray();
-
- for (; i != end; ++i)
- {
- result.append(name + "/" + (*i).asString());
- }
+ result.append(name);
+
+ LLSD paths = node->allNodePaths();
+ LLSD::array_const_iterator i = paths.beginArray();
+ LLSD::array_const_iterator end = paths.endArray();
+
+ for (; i != end; ++i)
+ {
+ result.append(name + "/" + (*i).asString());
+ }
}
LLSD LLHTTPNode::allNodePaths() const
{
- LLSD result;
-
- Impl::ChildMap::const_iterator i = impl.mNamedChildren.begin();
- Impl::ChildMap::const_iterator end = impl.mNamedChildren.end();
- for (; i != end; ++i)
- {
- append_node_paths(result, i->first, i->second);
- }
-
- if (impl.mWildcardChild)
- {
- append_node_paths(result, impl.mWildcardName, impl.mWildcardChild);
- }
-
- return result;
+ LLSD result;
+
+ Impl::ChildMap::const_iterator i = impl.mNamedChildren.begin();
+ Impl::ChildMap::const_iterator end = impl.mNamedChildren.end();
+ for (; i != end; ++i)
+ {
+ append_node_paths(result, i->first, i->second);
+ }
+
+ if (impl.mWildcardChild)
+ {
+ append_node_paths(result, impl.mWildcardName, impl.mWildcardChild);
+ }
+
+ return result;
}
const LLHTTPNode* LLHTTPNode::rootNode() const
{
- const LLHTTPNode* node = this;
-
- while (true)
- {
- const LLHTTPNode* next = node->impl.mParentNode;
- if (!next)
- {
- return node;
- }
- node = next;
- }
+ const LLHTTPNode* node = this;
+
+ while (true)
+ {
+ const LLHTTPNode* next = node->impl.mParentNode;
+ if (!next)
+ {
+ return node;
+ }
+ node = next;
+ }
}
const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const
{
- return impl.findNamedChild(name);
+ return impl.findNamedChild(name);
}
LLHTTPNode::Response::~Response()
@@ -398,40 +398,40 @@ LLHTTPNode::Response::~Response()
void LLHTTPNode::Response::statusUnknownError(S32 code)
{
- status(code, "Unknown Error");
+ status(code, "Unknown Error");
}
void LLHTTPNode::Response::notFound(const std::string& message)
{
- status(HTTP_NOT_FOUND, message);
+ status(HTTP_NOT_FOUND, message);
}
void LLHTTPNode::Response::notFound()
{
- status(HTTP_NOT_FOUND, "Not Found");
+ status(HTTP_NOT_FOUND, "Not Found");
}
void LLHTTPNode::Response::methodNotAllowed()
{
- status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed");
+ status(HTTP_METHOD_NOT_ALLOWED, "Method Not Allowed");
}
void LLHTTPNode::Response::addHeader(
- const std::string& name,
- const std::string& value)
+ const std::string& name,
+ const std::string& value)
{
- mHeaders[name] = value;
+ mHeaders[name] = value;
}
void LLHTTPNode::describe(Description& desc) const
{
- desc.shortInfo("unknown service (missing describe() method)");
+ desc.shortInfo("unknown service (missing describe() method)");
}
const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const
{
- return NULL;
+ return NULL;
}
@@ -439,7 +439,7 @@ const LLChainIOFactory* LLHTTPNode::getProtocolHandler() const
namespace
{
typedef std::map<std::string, LLHTTPRegistrar::NodeFactory*> FactoryMap;
-
+
FactoryMap& factoryMap()
{
static FactoryMap theMap;
@@ -452,27 +452,27 @@ LLHTTPRegistrar::NodeFactory::~NodeFactory() { }
void LLHTTPRegistrar::registerFactory(
const std::string& path, NodeFactory& factory)
{
- factoryMap()[path] = &factory;
+ factoryMap()[path] = &factory;
}
void LLHTTPRegistrar::buildAllServices(LLHTTPNode& root)
{
const FactoryMap& map = factoryMap();
-
+
FactoryMap::const_iterator i = map.begin();
FactoryMap::const_iterator end = map.end();
for (; i != end; ++i)
{
- LL_DEBUGS("AppInit") << "LLHTTPRegistrar::buildAllServices adding node for path "
- << i->first << LL_ENDL;
-
+ LL_DEBUGS("AppInit") << "LLHTTPRegistrar::buildAllServices adding node for path "
+ << i->first << LL_ENDL;
+
root.addNode(i->first, i->second->build());
}
}
LLPointer<LLSimpleResponse> LLSimpleResponse::create()
{
- return new LLSimpleResponse();
+ return new LLSimpleResponse();
}
LLSimpleResponse::~LLSimpleResponse()
@@ -481,33 +481,33 @@ LLSimpleResponse::~LLSimpleResponse()
void LLSimpleResponse::result(const LLSD& result)
{
- status(HTTP_OK, "OK");
+ status(HTTP_OK, "OK");
}
void LLSimpleResponse::extendedResult(S32 code, const std::string& body, const LLSD& headers)
{
- status(code,body);
+ status(code,body);
}
void LLSimpleResponse::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
{
- status(code,"(LLSD)");
+ status(code,"(LLSD)");
}
void LLSimpleResponse::status(S32 code, const std::string& message)
{
- mCode = code;
- mMessage = message;
+ mCode = code;
+ mMessage = message;
}
void LLSimpleResponse::print(std::ostream& out) const
{
- out << mCode << " " << mMessage;
+ out << mCode << " " << mMessage;
}
std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp)
{
- resp.print(out);
- return out;
+ resp.print(out);
+ return out;
}
diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h
index 1144d88be1..b7b6053f48 100644
--- a/indra/llmessage/llhttpnode.h
+++ b/indra/llmessage/llhttpnode.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llhttpnode.h
* @brief Declaration of classes for generic HTTP/LSL/REST handling.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,16 +47,16 @@ class LLChainIOFactory;
/**
* These classes represent the HTTP framework: The URL tree, and the LLSD
* REST interface that such nodes implement.
- *
+ *
* To implement a service, in most cases, subclass LLHTTPNode, implement
* get() or post(), and create a global instance of LLHTTPRegistration<>.
* This can all be done in a .cpp file, with no publically declared parts.
- *
+ *
* To implement a server see lliohttpserver.h
* @see LLHTTPWireServer
*/
-/**
+/**
* @class LLHTTPNode
* @brief Base class which handles url traversal, response routing
* and support for standard LLSD services
@@ -74,226 +74,226 @@ class LLHTTPNode
protected:
LOG_CLASS(LLHTTPNode);
public:
- LLHTTPNode();
- virtual ~LLHTTPNode();
-
- /** @name Responses
- Most subclasses override one or more of these methods to provide
- the service. By default, the rest of the LLHTTPNode architecture
- will handle requests, create the needed LLIOPump, parse the input
- to LLSD, and format the LLSD result to the output.
-
- The default implementation of each of these is to call
- response->methodNotAllowed(); The "simple" versions can be
- overridden instead in those cases where the service can return
- an immediately computed response.
- */
- //@{
-public:
-
- virtual LLSD simpleGet() const;
- virtual LLSD simplePut(const LLSD& input) const;
- virtual LLSD simplePost(const LLSD& input) const;
- virtual LLSD simpleDel(const LLSD& context) const;
-
- /**
- * @brief Abstract Base Class declaring Response interface.
- */
- class Response : public LLRefCount
- {
- protected:
- virtual ~Response();
-
- public:
- /**
- * @brief Return the LLSD content and a 200 OK.
- */
- virtual void result(const LLSD&) = 0;
-
- /**
- * @brief return status code and message with headers.
- */
- virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0;
-
- /**
- * @brief return status code and LLSD result with headers.
- */
- virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0;
-
- /**
- * @brief return status code and reason string on http header,
- * but do not return a payload.
- */
- virtual void status(S32 code, const std::string& message) = 0;
-
- /**
- * @brief Return no body, just status code and 'UNKNOWN ERROR'.
- */
- virtual void statusUnknownError(S32 code);
-
- virtual void notFound(const std::string& message);
- virtual void notFound();
- virtual void methodNotAllowed();
-
- /**
- * @brief Add a name: value http header.
- *
- * No effort is made to ensure the response is a valid http
- * header.
- * The headers are stored as a map of header name : value.
- * Though HTTP allows the same header name to be transmitted
- * more than once, this implementation only stores a header
- * name once.
- * @param name The name of the header, eg, "Content-Encoding"
- * @param value The value of the header, eg, "gzip"
- */
- virtual void addHeader(const std::string& name, const std::string& value);
-
- protected:
- /**
- * @brief Headers to be sent back with the HTTP response.
- *
- * Protected class membership since derived classes are
- * expected to use it and there is no use case yet for other
- * uses. If such a use case arises, I suggest making a
- * headers() public method, and moving this member data into
- * private.
- */
- LLSD mHeaders;
- };
-
- typedef LLPointer<Response> ResponsePtr;
-
- virtual void get(ResponsePtr, const LLSD& context) const;
- virtual void put(
- ResponsePtr,
- const LLSD& context,
- const LLSD& input) const;
- virtual void post(
- ResponsePtr,
- const LLSD& context,
- const LLSD& input) const;
- virtual void del(ResponsePtr, const LLSD& context) const;
- virtual void options(ResponsePtr, const LLSD& context) const;
- //@}
-
-
- /** @name URL traversal
- The tree is traversed by calling getChild() with successive
- path components, on successive results. When getChild() returns
- null, or there are no more components, the last child responds to
- the request.
-
- The default behavior is generally correct, though wildcard nodes
- will want to implement validate().
- */
- //@{
+ LLHTTPNode();
+ virtual ~LLHTTPNode();
+
+ /** @name Responses
+ Most subclasses override one or more of these methods to provide
+ the service. By default, the rest of the LLHTTPNode architecture
+ will handle requests, create the needed LLIOPump, parse the input
+ to LLSD, and format the LLSD result to the output.
+
+ The default implementation of each of these is to call
+ response->methodNotAllowed(); The "simple" versions can be
+ overridden instead in those cases where the service can return
+ an immediately computed response.
+ */
+ //@{
+public:
+
+ virtual LLSD simpleGet() const;
+ virtual LLSD simplePut(const LLSD& input) const;
+ virtual LLSD simplePost(const LLSD& input) const;
+ virtual LLSD simpleDel(const LLSD& context) const;
+
+ /**
+ * @brief Abstract Base Class declaring Response interface.
+ */
+ class Response : public LLRefCount
+ {
+ protected:
+ virtual ~Response();
+
+ public:
+ /**
+ * @brief Return the LLSD content and a 200 OK.
+ */
+ virtual void result(const LLSD&) = 0;
+
+ /**
+ * @brief return status code and message with headers.
+ */
+ virtual void extendedResult(S32 code, const std::string& message, const LLSD& headers = LLSD()) = 0;
+
+ /**
+ * @brief return status code and LLSD result with headers.
+ */
+ virtual void extendedResult(S32 code, const LLSD& result, const LLSD& headers = LLSD()) = 0;
+
+ /**
+ * @brief return status code and reason string on http header,
+ * but do not return a payload.
+ */
+ virtual void status(S32 code, const std::string& message) = 0;
+
+ /**
+ * @brief Return no body, just status code and 'UNKNOWN ERROR'.
+ */
+ virtual void statusUnknownError(S32 code);
+
+ virtual void notFound(const std::string& message);
+ virtual void notFound();
+ virtual void methodNotAllowed();
+
+ /**
+ * @brief Add a name: value http header.
+ *
+ * No effort is made to ensure the response is a valid http
+ * header.
+ * The headers are stored as a map of header name : value.
+ * Though HTTP allows the same header name to be transmitted
+ * more than once, this implementation only stores a header
+ * name once.
+ * @param name The name of the header, eg, "Content-Encoding"
+ * @param value The value of the header, eg, "gzip"
+ */
+ virtual void addHeader(const std::string& name, const std::string& value);
+
+ protected:
+ /**
+ * @brief Headers to be sent back with the HTTP response.
+ *
+ * Protected class membership since derived classes are
+ * expected to use it and there is no use case yet for other
+ * uses. If such a use case arises, I suggest making a
+ * headers() public method, and moving this member data into
+ * private.
+ */
+ LLSD mHeaders;
+ };
+
+ typedef LLPointer<Response> ResponsePtr;
+
+ virtual void get(ResponsePtr, const LLSD& context) const;
+ virtual void put(
+ ResponsePtr,
+ const LLSD& context,
+ const LLSD& input) const;
+ virtual void post(
+ ResponsePtr,
+ const LLSD& context,
+ const LLSD& input) const;
+ virtual void del(ResponsePtr, const LLSD& context) const;
+ virtual void options(ResponsePtr, const LLSD& context) const;
+ //@}
+
+
+ /** @name URL traversal
+ The tree is traversed by calling getChild() with successive
+ path components, on successive results. When getChild() returns
+ null, or there are no more components, the last child responds to
+ the request.
+
+ The default behavior is generally correct, though wildcard nodes
+ will want to implement validate().
+ */
+ //@{
public:
- virtual LLHTTPNode* getChild(const std::string& name, LLSD& context) const;
- /**< returns a child node, if any, at the given name
- default looks at children and wildcard child (see below)
- */
-
- virtual bool handles(const LLSD& remainder, LLSD& context) const;
- /**< return true if this node can service the remaining components;
- default returns true if there are no remaining components
- */
-
- virtual bool validate(const std::string& name, LLSD& context) const;
- /**< called only on wildcard nodes, to check if they will handle
- the name; default is false; overrides will want to check
- name, and return true if the name will construct to a valid url.
- For convenience, the <code>getChild()</code> method above will
- automatically insert the name in
- context[CONTEXT_REQUEST][CONTEXT_WILDCARD][key] if this method returns true.
- For example, the node "agent/<agent_id>/detail" will set
- context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["agent_id"] eqaul to the value
- found during traversal.
- */
-
- const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
- /**< find a node, if any, that can service this path
- set up context[CONTEXT_REQUEST] information
- */
- //@}
-
- /** @name Child Nodes
- The standard node can have any number of child nodes under
- fixed names, and optionally one "wildcard" node that can
- handle all other names.
-
- Usually, child nodes are add through LLHTTPRegistration, not
- by calling this interface directly.
-
- The added node will be now owned by the parent node.
- */
- //@{
-
- virtual void addNode(const std::string& path, LLHTTPNode* nodeToAdd);
-
- LLSD allNodePaths() const;
- ///< Returns an arrary of node paths at and under this node
-
- const LLHTTPNode* rootNode() const;
- const LLHTTPNode* findNode(const std::string& name) const;
-
-
- enum EHTTPNodeContentType
- {
- CONTENT_TYPE_LLSD,
- CONTENT_TYPE_TEXT
- };
-
- virtual EHTTPNodeContentType getContentType() const { return CONTENT_TYPE_LLSD; }
- //@}
-
- /* @name Description system
- The Description object contains information about a service.
- All subclasses of LLHTTPNode should override describe() and use
- the methods of the Description class to set the various properties.
- */
- //@{
- class Description
- {
- public:
- void shortInfo(const std::string& s){ mInfo["description"] = s; }
- void longInfo(const std::string& s) { mInfo["details"] = s; }
-
- // Call this method when the service supports the specified verb.
- void getAPI() { mInfo["api"].append("GET"); }
- void putAPI() { mInfo["api"].append("PUT"); }
- void postAPI() { mInfo["api"].append("POST"); }
- void delAPI() { mInfo["api"].append("DELETE"); }
-
- void input(const std::string& s) { mInfo["input"] = s; }
- void output(const std::string& s) { mInfo["output"] = s; }
- void source(const char* f, int l) { mInfo["__file__"] = f;
- mInfo["__line__"] = l; }
-
- LLSD getInfo() const { return mInfo; }
-
- private:
- LLSD mInfo;
- };
-
- virtual void describe(Description&) const;
-
- //@}
-
-
- virtual const LLChainIOFactory* getProtocolHandler() const;
- /**< Return a factory object for handling wire protocols.
- * The base class returns NULL, as it doesn't know about
- * wire protocols at all. This is okay for most nodes
- * as LLIOHTTPServer is smart enough to use a default
- * wire protocol for HTTP for such nodes. Specialized
- * subclasses that handle things like XML-RPC will want
- * to implement this. (See LLXMLSDRPCServerFactory.)
- */
+ virtual LLHTTPNode* getChild(const std::string& name, LLSD& context) const;
+ /**< returns a child node, if any, at the given name
+ default looks at children and wildcard child (see below)
+ */
+
+ virtual bool handles(const LLSD& remainder, LLSD& context) const;
+ /**< return true if this node can service the remaining components;
+ default returns true if there are no remaining components
+ */
+
+ virtual bool validate(const std::string& name, LLSD& context) const;
+ /**< called only on wildcard nodes, to check if they will handle
+ the name; default is false; overrides will want to check
+ name, and return true if the name will construct to a valid url.
+ For convenience, the <code>getChild()</code> method above will
+ automatically insert the name in
+ context[CONTEXT_REQUEST][CONTEXT_WILDCARD][key] if this method returns true.
+ For example, the node "agent/<agent_id>/detail" will set
+ context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["agent_id"] eqaul to the value
+ found during traversal.
+ */
+
+ const LLHTTPNode* traverse(const std::string& path, LLSD& context) const;
+ /**< find a node, if any, that can service this path
+ set up context[CONTEXT_REQUEST] information
+ */
+ //@}
+
+ /** @name Child Nodes
+ The standard node can have any number of child nodes under
+ fixed names, and optionally one "wildcard" node that can
+ handle all other names.
+
+ Usually, child nodes are add through LLHTTPRegistration, not
+ by calling this interface directly.
+
+ The added node will be now owned by the parent node.
+ */
+ //@{
+
+ virtual void addNode(const std::string& path, LLHTTPNode* nodeToAdd);
+
+ LLSD allNodePaths() const;
+ ///< Returns an arrary of node paths at and under this node
+
+ const LLHTTPNode* rootNode() const;
+ const LLHTTPNode* findNode(const std::string& name) const;
+
+
+ enum EHTTPNodeContentType
+ {
+ CONTENT_TYPE_LLSD,
+ CONTENT_TYPE_TEXT
+ };
+
+ virtual EHTTPNodeContentType getContentType() const { return CONTENT_TYPE_LLSD; }
+ //@}
+
+ /* @name Description system
+ The Description object contains information about a service.
+ All subclasses of LLHTTPNode should override describe() and use
+ the methods of the Description class to set the various properties.
+ */
+ //@{
+ class Description
+ {
+ public:
+ void shortInfo(const std::string& s){ mInfo["description"] = s; }
+ void longInfo(const std::string& s) { mInfo["details"] = s; }
+
+ // Call this method when the service supports the specified verb.
+ void getAPI() { mInfo["api"].append("GET"); }
+ void putAPI() { mInfo["api"].append("PUT"); }
+ void postAPI() { mInfo["api"].append("POST"); }
+ void delAPI() { mInfo["api"].append("DELETE"); }
+
+ void input(const std::string& s) { mInfo["input"] = s; }
+ void output(const std::string& s) { mInfo["output"] = s; }
+ void source(const char* f, int l) { mInfo["__file__"] = f;
+ mInfo["__line__"] = l; }
+
+ LLSD getInfo() const { return mInfo; }
+
+ private:
+ LLSD mInfo;
+ };
+
+ virtual void describe(Description&) const;
+
+ //@}
+
+
+ virtual const LLChainIOFactory* getProtocolHandler() const;
+ /**< Return a factory object for handling wire protocols.
+ * The base class returns NULL, as it doesn't know about
+ * wire protocols at all. This is okay for most nodes
+ * as LLIOHTTPServer is smart enough to use a default
+ * wire protocol for HTTP for such nodes. Specialized
+ * subclasses that handle things like XML-RPC will want
+ * to implement this. (See LLXMLSDRPCServerFactory.)
+ */
private:
- class Impl;
- Impl& impl;
+ class Impl;
+ Impl& impl;
};
@@ -301,20 +301,20 @@ private:
class LLSimpleResponse : public LLHTTPNode::Response
{
public:
- static LLPointer<LLSimpleResponse> create();
-
- void result(const LLSD& result);
- void extendedResult(S32 code, const std::string& body, const LLSD& headers);
- void extendedResult(S32 code, const LLSD& result, const LLSD& headers);
- void status(S32 code, const std::string& message);
+ static LLPointer<LLSimpleResponse> create();
+
+ void result(const LLSD& result);
+ void extendedResult(S32 code, const std::string& body, const LLSD& headers);
+ void extendedResult(S32 code, const LLSD& result, const LLSD& headers);
+ void status(S32 code, const std::string& message);
- void print(std::ostream& out) const;
+ void print(std::ostream& out) const;
- S32 mCode;
- std::string mMessage;
+ S32 mCode;
+ std::string mMessage;
protected:
- ~LLSimpleResponse();
+ ~LLSimpleResponse();
private:
LLSimpleResponse() : mCode(0) {} // Must be accessed through LLPointer.
@@ -324,13 +324,13 @@ std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp);
-/**
- * @name Automatic LLHTTPNode registration
+/**
+ * @name Automatic LLHTTPNode registration
*
* To register a node type at a particular url path, construct a global instance
* of LLHTTPRegistration:
*
- * LLHTTPRegistration<LLMyNodeType> gHTTPServiceAlphaBeta("/alpha/beta");
+ * LLHTTPRegistration<LLMyNodeType> gHTTPServiceAlphaBeta("/alpha/beta");
*
* (Note the naming convention carefully.) This object must be global and not
* static. However, it needn't be declared in your .h file. It can exist
@@ -340,68 +340,68 @@ std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp);
* When constructing a web server, use LLHTTPRegistrar to add all the registered
* nodes to the url tree:
*
- * LLHTTPRegistrar::buidlAllServices(mRootNode);
+ * LLHTTPRegistrar::buidlAllServices(mRootNode);
*/
//@{
class LLHTTPRegistrar
{
public:
- class NodeFactory
- {
- public:
- virtual ~NodeFactory();
- virtual LLHTTPNode* build() const = 0;
- };
+ class NodeFactory
+ {
+ public:
+ virtual ~NodeFactory();
+ virtual LLHTTPNode* build() const = 0;
+ };
- static void buildAllServices(LLHTTPNode& root);
+ static void buildAllServices(LLHTTPNode& root);
- static void registerFactory(const std::string& path, NodeFactory& factory);
- ///< construct an LLHTTPRegistration below to call this
+ static void registerFactory(const std::string& path, NodeFactory& factory);
+ ///< construct an LLHTTPRegistration below to call this
};
template < class NodeType >
class LLHTTPRegistration
{
public:
- LLHTTPRegistration(const std::string& path)
- {
- LLHTTPRegistrar::registerFactory(path, mFactory);
- }
+ LLHTTPRegistration(const std::string& path)
+ {
+ LLHTTPRegistrar::registerFactory(path, mFactory);
+ }
private:
- class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
- {
- public:
- virtual LLHTTPNode* build() const { return new NodeType; }
- };
-
- ThisNodeFactory mFactory;
+ class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
+ {
+ public:
+ virtual LLHTTPNode* build() const { return new NodeType; }
+ };
+
+ ThisNodeFactory mFactory;
};
template < class NodeType>
class LLHTTPParamRegistration
{
public:
- LLHTTPParamRegistration(const std::string& path, LLSD params) :
- mFactory(params)
- {
- LLHTTPRegistrar::registerFactory(path, mFactory);
- }
+ LLHTTPParamRegistration(const std::string& path, LLSD params) :
+ mFactory(params)
+ {
+ LLHTTPRegistrar::registerFactory(path, mFactory);
+ }
private:
- class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
- {
- public:
- ThisNodeFactory(LLSD params) : mParams(params) {}
- virtual LLHTTPNode* build() const { return new NodeType(mParams); }
- private:
- LLSD mParams;
- };
-
- ThisNodeFactory mFactory;
+ class ThisNodeFactory : public LLHTTPRegistrar::NodeFactory
+ {
+ public:
+ ThisNodeFactory(LLSD params) : mParams(params) {}
+ virtual LLHTTPNode* build() const { return new NodeType(mParams); }
+ private:
+ LLSD mParams;
+ };
+
+ ThisNodeFactory mFactory;
};
-
+
//@}
#endif // LL_LLHTTPNODE_H
diff --git a/indra/llmessage/llhttpnodeadapter.h b/indra/llmessage/llhttpnodeadapter.h
index 22984c4478..436de6224f 100644
--- a/indra/llmessage/llhttpnodeadapter.h
+++ b/indra/llmessage/llhttpnodeadapter.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,19 +34,19 @@ class LLHTTPNodeAdapter : public LLHTTPNode
{
public:
- virtual bool validate(const std::string& name, LLSD& context) const
- {
- T node;
- return node.validate(name, context);
- }
-
- virtual void post(LLHTTPNode::ResponsePtr response,
- const LLSD& context,
- const LLSD& input) const
- {
- T node;
- return node.post(response, context, input);
- }
+ virtual bool validate(const std::string& name, LLSD& context) const
+ {
+ T node;
+ return node.validate(name, context);
+ }
+
+ virtual void post(LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ T node;
+ return node.post(response, context, input);
+ }
};
#endif // LL_HTTP_NODE_ADAPTER_H
diff --git a/indra/llmessage/llhttpsdhandler.cpp b/indra/llmessage/llhttpsdhandler.cpp
index 648bc5cfd8..1c5928e187 100644
--- a/indra/llmessage/llhttpsdhandler.cpp
+++ b/indra/llmessage/llhttpsdhandler.cpp
@@ -42,36 +42,36 @@ LLHttpSDHandler::LLHttpSDHandler()
void LLHttpSDHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
{
- LLCore::HttpStatus status = response->getStatus();
+ LLCore::HttpStatus status = response->getStatus();
- if (!status)
- {
- this->onFailure(response, status);
- }
- else
- {
- LLSD resplsd;
- const bool emit_parse_errors = false;
+ if (!status)
+ {
+ this->onFailure(response, status);
+ }
+ else
+ {
+ LLSD resplsd;
+ const bool emit_parse_errors = false;
- bool parsed = !((response->getBodySize() == 0) ||
- !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, resplsd));
+ bool parsed = !((response->getBodySize() == 0) ||
+ !LLCoreHttpUtil::responseToLLSD(response, emit_parse_errors, resplsd));
- if (!parsed)
- {
- // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
- LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
- const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
+ if (!parsed)
+ {
+ // Only emit a warning if we failed to parse when 'content-type' == 'application/llsd+xml'
+ LLCore::HttpHeaders::ptr_t headers(response->getHeaders());
+ const std::string *contentType = (headers) ? headers->find(HTTP_IN_HEADER_CONTENT_TYPE) : NULL;
- if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
- {
- std::string thebody = LLCoreHttpUtil::responseToString(response);
+ if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
+ {
+ std::string thebody = LLCoreHttpUtil::responseToString(response);
- LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
- << " body: " << thebody << LL_ENDL;
- }
- }
+ LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
+ << " body: " << thebody << LL_ENDL;
+ }
+ }
- this->onSuccess(response, resplsd);
- }
+ this->onSuccess(response, resplsd);
+ }
}
diff --git a/indra/llmessage/llhttpsdhandler.h b/indra/llmessage/llhttpsdhandler.h
index ce40bdfc08..6390073339 100644
--- a/indra/llmessage/llhttpsdhandler.h
+++ b/indra/llmessage/llhttpsdhandler.h
@@ -24,30 +24,30 @@
* $/LicenseInfo$
*/
-#ifndef _LLHTTPSDHANDLER_H_
-#define _LLHTTPSDHANDLER_H_
+#ifndef _LLHTTPSDHANDLER_H_
+#define _LLHTTPSDHANDLER_H_
#include "httpcommon.h"
#include "httphandler.h"
#include "lluri.h"
-/// Handler class LLCore's HTTP library. Splitting with separate success and
-/// failure routines and parsing the result body into LLSD on success. It
+/// Handler class LLCore's HTTP library. Splitting with separate success and
+/// failure routines and parsing the result body into LLSD on success. It
/// is intended to be subclassed for specific capability handling.
-///
-// *TODO: This class self deletes at the end of onCompleted method. This is
+///
+// *TODO: This class self deletes at the end of onCompleted method. This is
// less than ideal and should be revisited.
class LLHttpSDHandler : public LLCore::HttpHandler //,
// public std::enable_shared_from_this<LLHttpSDHandler>
{
public:
- virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
-
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
protected:
LLHttpSDHandler();
- virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0;
- virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
+ virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content) = 0;
+ virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) = 0;
};
diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp
index 52102e55c8..0563613cfa 100644
--- a/indra/llmessage/llinstantmessage.cpp
+++ b/indra/llmessage/llinstantmessage.cpp
@@ -1,164 +1,164 @@
-/**
- * @file llinstantmessage.cpp
- * @author Phoenix
- * @date 2005-08-29
- * @brief Constants and functions used in IM.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lldbstrings.h"
-#include "llinstantmessage.h"
-#include "llhost.h"
-#include "lluuid.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "llsdutil_math.h"
-#include "llpointer.h"
-#include "message.h"
-
-#include "message.h"
-
-const U8 IM_ONLINE = 0;
-const U8 IM_OFFLINE = 1;
-
-const char EMPTY_BINARY_BUCKET[] = "";
-const S32 EMPTY_BINARY_BUCKET_SIZE = 1;
-const U32 NO_TIMESTAMP = 0;
-const std::string SYSTEM_FROM("Second Life");
-const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");
-const S32 IM_TTL = 1;
-
-
-void pack_instant_message(
- LLMessageSystem* msg,
- const LLUUID& from_id,
- bool from_group,
- const LLUUID& session_id,
- const LLUUID& to_id,
- const std::string& name,
- const std::string& message,
- U8 offline,
- EInstantMessage dialog,
- const LLUUID& id,
- U32 parent_estate_id,
- const LLUUID& region_id,
- const LLVector3& position,
- U32 timestamp,
- const U8* binary_bucket,
- S32 binary_bucket_size)
-{
- LL_DEBUGS() << "pack_instant_message()" << LL_ENDL;
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- pack_instant_message_block(
- msg,
- from_id,
- from_group,
- session_id,
- to_id,
- name,
- message,
- offline,
- dialog,
- id,
- parent_estate_id,
- region_id,
- position,
- timestamp,
- binary_bucket,
- binary_bucket_size);
-}
-
-void pack_instant_message_block(
- LLMessageSystem* msg,
- const LLUUID& from_id,
- bool from_group,
- const LLUUID& session_id,
- const LLUUID& to_id,
- const std::string& name,
- const std::string& message,
- U8 offline,
- EInstantMessage dialog,
- const LLUUID& id,
- U32 parent_estate_id,
- const LLUUID& region_id,
- const LLVector3& position,
- U32 timestamp,
- const U8* binary_bucket,
- S32 binary_bucket_size)
-{
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, from_id);
- msg->addUUIDFast(_PREHASH_SessionID, session_id);
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, from_group);
- msg->addUUIDFast(_PREHASH_ToAgentID, to_id);
- msg->addU32Fast(_PREHASH_ParentEstateID, parent_estate_id);
- msg->addUUIDFast(_PREHASH_RegionID, region_id);
- msg->addVector3Fast(_PREHASH_Position, position);
- msg->addU8Fast(_PREHASH_Offline, offline);
- msg->addU8Fast(_PREHASH_Dialog, (U8) dialog);
- msg->addUUIDFast(_PREHASH_ID, id);
- msg->addU32Fast(_PREHASH_Timestamp, timestamp);
- msg->addStringFast(_PREHASH_FromAgentName, name);
- S32 bytes_left = MTUBYTES;
- if(!message.empty())
- {
- char buffer[MTUBYTES];
- int num_written = snprintf(buffer, MTUBYTES, "%s", message.c_str()); /* Flawfinder: ignore */
- // snprintf returns number of bytes that would have been written
- // had the output not being truncated. In that case, it will
- // return either -1 or value >= passed in size value . So a check needs to be added
- // to detect truncation, and if there is any, only account for the
- // actual number of bytes written..and not what could have been
- // written.
- if (num_written < 0 || num_written >= MTUBYTES)
- {
- num_written = MTUBYTES - 1;
- LL_WARNS() << "pack_instant_message_block: message truncated: " << message << LL_ENDL;
- }
-
- bytes_left -= num_written;
- bytes_left = llmax(0, bytes_left);
- msg->addStringFast(_PREHASH_Message, buffer);
- }
- else
- {
- msg->addStringFast(_PREHASH_Message, NULL);
- }
- const U8* bb;
- if(binary_bucket)
- {
- bb = binary_bucket;
- binary_bucket_size = llmin(bytes_left, binary_bucket_size);
- }
- else
- {
- bb = (const U8*)EMPTY_BINARY_BUCKET;
- binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE;
- }
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size);
-}
-
-
+/**
+ * @file llinstantmessage.cpp
+ * @author Phoenix
+ * @date 2005-08-29
+ * @brief Constants and functions used in IM.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lldbstrings.h"
+#include "llinstantmessage.h"
+#include "llhost.h"
+#include "lluuid.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+#include "llsdutil_math.h"
+#include "llpointer.h"
+#include "message.h"
+
+#include "message.h"
+
+const U8 IM_ONLINE = 0;
+const U8 IM_OFFLINE = 1;
+
+const char EMPTY_BINARY_BUCKET[] = "";
+const S32 EMPTY_BINARY_BUCKET_SIZE = 1;
+const U32 NO_TIMESTAMP = 0;
+const std::string SYSTEM_FROM("Second Life");
+const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B");
+const S32 IM_TTL = 1;
+
+
+void pack_instant_message(
+ LLMessageSystem* msg,
+ const LLUUID& from_id,
+ bool from_group,
+ const LLUUID& session_id,
+ const LLUUID& to_id,
+ const std::string& name,
+ const std::string& message,
+ U8 offline,
+ EInstantMessage dialog,
+ const LLUUID& id,
+ U32 parent_estate_id,
+ const LLUUID& region_id,
+ const LLVector3& position,
+ U32 timestamp,
+ const U8* binary_bucket,
+ S32 binary_bucket_size)
+{
+ LL_DEBUGS() << "pack_instant_message()" << LL_ENDL;
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ pack_instant_message_block(
+ msg,
+ from_id,
+ from_group,
+ session_id,
+ to_id,
+ name,
+ message,
+ offline,
+ dialog,
+ id,
+ parent_estate_id,
+ region_id,
+ position,
+ timestamp,
+ binary_bucket,
+ binary_bucket_size);
+}
+
+void pack_instant_message_block(
+ LLMessageSystem* msg,
+ const LLUUID& from_id,
+ bool from_group,
+ const LLUUID& session_id,
+ const LLUUID& to_id,
+ const std::string& name,
+ const std::string& message,
+ U8 offline,
+ EInstantMessage dialog,
+ const LLUUID& id,
+ U32 parent_estate_id,
+ const LLUUID& region_id,
+ const LLVector3& position,
+ U32 timestamp,
+ const U8* binary_bucket,
+ S32 binary_bucket_size)
+{
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, from_id);
+ msg->addUUIDFast(_PREHASH_SessionID, session_id);
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, from_group);
+ msg->addUUIDFast(_PREHASH_ToAgentID, to_id);
+ msg->addU32Fast(_PREHASH_ParentEstateID, parent_estate_id);
+ msg->addUUIDFast(_PREHASH_RegionID, region_id);
+ msg->addVector3Fast(_PREHASH_Position, position);
+ msg->addU8Fast(_PREHASH_Offline, offline);
+ msg->addU8Fast(_PREHASH_Dialog, (U8) dialog);
+ msg->addUUIDFast(_PREHASH_ID, id);
+ msg->addU32Fast(_PREHASH_Timestamp, timestamp);
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ S32 bytes_left = MTUBYTES;
+ if(!message.empty())
+ {
+ char buffer[MTUBYTES];
+ int num_written = snprintf(buffer, MTUBYTES, "%s", message.c_str()); /* Flawfinder: ignore */
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if (num_written < 0 || num_written >= MTUBYTES)
+ {
+ num_written = MTUBYTES - 1;
+ LL_WARNS() << "pack_instant_message_block: message truncated: " << message << LL_ENDL;
+ }
+
+ bytes_left -= num_written;
+ bytes_left = llmax(0, bytes_left);
+ msg->addStringFast(_PREHASH_Message, buffer);
+ }
+ else
+ {
+ msg->addStringFast(_PREHASH_Message, NULL);
+ }
+ const U8* bb;
+ if(binary_bucket)
+ {
+ bb = binary_bucket;
+ binary_bucket_size = llmin(bytes_left, binary_bucket_size);
+ }
+ else
+ {
+ bb = (const U8*)EMPTY_BINARY_BUCKET;
+ binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE;
+ }
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, bb, binary_bucket_size);
+}
+
+
diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h
index 383fe2591a..d1f5eef548 100644
--- a/indra/llmessage/llinstantmessage.h
+++ b/indra/llmessage/llinstantmessage.h
@@ -1,218 +1,218 @@
-/**
- * @file llinstantmessage.h
- * @brief Constants and declarations used by instant messages.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLINSTANTMESSAGE_H
-#define LL_LLINSTANTMESSAGE_H
-
-#include "llhost.h"
-#include "lluuid.h"
-#include "llsd.h"
-#include "llrefcount.h"
-#include "llpointer.h"
-#include "v3math.h"
-
-class LLMessageSystem;
-
-// The ImprovedInstantMessage only supports 8 bits in the "Dialog"
-// field, so don't go past the byte boundary
-enum EInstantMessage
-{
- // default. ID is meaningless, nothing in the binary bucket.
- IM_NOTHING_SPECIAL = 0,
-
- // pops a messagebox with a single OK button
- IM_MESSAGEBOX = 1,
-
- // pops a countdown messagebox with a single OK button
- // IM_MESSAGEBOX_COUNTDOWN = 2,
-
- // You've been invited to join a group.
- // ID is the group id.
-
- // The binary bucket contains a null terminated string
- // representation of the officer/member status and join cost for
- // the invitee. (bug # 7672) The format is 1 byte for
- // officer/member (O for officer, M for member), and as many bytes
- // as necessary for cost.
- IM_GROUP_INVITATION = 3,
-
- // Inventory offer.
- // ID is the transaction id
- // Binary bucket is a list of inventory uuid and type.
- IM_INVENTORY_OFFERED = 4,
- IM_INVENTORY_ACCEPTED = 5,
- IM_INVENTORY_DECLINED = 6,
-
- // Group vote
- // Name is name of person who called vote.
- // ID is vote ID used for internal tracking
- // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
- IM_GROUP_VOTE = 7,
-
- // Group message
- // This means that the message is meant for everyone in the
- // agent's group. This will result in a database query to find all
- // participants and start an im session.
- IM_GROUP_MESSAGE_DEPRECATED = 8,
-
- // Task inventory offer.
- // ID is the transaction id
- // Binary bucket is a (mostly) complete packed inventory item
- IM_TASK_INVENTORY_OFFERED = 9,
- IM_TASK_INVENTORY_ACCEPTED = 10,
- IM_TASK_INVENTORY_DECLINED = 11,
-
- // Copied as pending, type LL_NOTHING_SPECIAL, for new users
- // used by offline tools
- IM_NEW_USER_DEFAULT = 12,
-
- //
- // session based messaging - the way that people usually actually
- // communicate with each other.
- //
-
- // Invite users to a session.
- IM_SESSION_INVITE = 13,
-
- IM_SESSION_P2P_INVITE = 14,
-
- // start a session with your gruop
- IM_SESSION_GROUP_START = 15,
-
- // start a session without a calling card (finder or objects)
- IM_SESSION_CONFERENCE_START = 16,
-
- // send a message to a session.
- IM_SESSION_SEND = 17,
-
- // leave a session
- IM_SESSION_LEAVE = 18,
-
- // an instant message from an object - for differentiation on the
- // viewer, since you can't IM an object yet.
- IM_FROM_TASK = 19,
-
- // sent an IM to a do not disturb user, this is the auto response
- IM_DO_NOT_DISTURB_AUTO_RESPONSE = 20,
-
- // Shows the message in the console and chat history
- IM_CONSOLE_AND_CHAT_HISTORY = 21,
-
- // IM Types used for luring your friends
- IM_LURE_USER = 22,
- IM_LURE_ACCEPTED = 23,
- IM_LURE_DECLINED = 24,
- IM_GODLIKE_LURE_USER = 25,
- IM_TELEPORT_REQUEST = 26,
-
- // IM that notifie of a new group election.
- // Name is name of person who called vote.
- // ID is election ID used for internal tracking
- IM_GROUP_ELECTION_DEPRECATED = 27,
-
- // IM to tell the user to go to an URL. Put a text message in the
- // message field, and put the url with a trailing \0 in the binary
- // bucket.
- IM_GOTO_URL = 28,
-
- // a message generated by a script which we don't want to
- // be sent through e-mail. Similar to IM_FROM_TASK, but
- // it is shown as an alert on the viewer.
- IM_FROM_TASK_AS_ALERT = 31,
-
- // IM from group officer to all group members.
- IM_GROUP_NOTICE = 32,
- IM_GROUP_NOTICE_INVENTORY_ACCEPTED = 33,
- IM_GROUP_NOTICE_INVENTORY_DECLINED = 34,
-
- IM_GROUP_INVITATION_ACCEPT = 35,
- IM_GROUP_INVITATION_DECLINE = 36,
-
- IM_GROUP_NOTICE_REQUESTED = 37,
-
- IM_FRIENDSHIP_OFFERED = 38,
- IM_FRIENDSHIP_ACCEPTED = 39,
- IM_FRIENDSHIP_DECLINED_DEPRECATED = 40,
-
- IM_TYPING_START = 41,
- IM_TYPING_STOP = 42,
-
- IM_COUNT
-};
-
-
-extern const U8 IM_ONLINE;
-extern const U8 IM_OFFLINE;
-
-extern const char EMPTY_BINARY_BUCKET[];
-extern const S32 EMPTY_BINARY_BUCKET_SIZE;
-
-extern const U32 NO_TIMESTAMP;
-extern const std::string SYSTEM_FROM;
-extern const std::string INTERACTIVE_SYSTEM_FROM;
-
-// Number of retry attempts on sending the im.
-extern const S32 IM_TTL;
-
-void pack_instant_message(
- LLMessageSystem* msgsystem,
- const LLUUID& from_id,
- bool from_group,
- const LLUUID& session_id,
- const LLUUID& to_id,
- const std::string& name,
- const std::string& message,
- U8 offline = IM_ONLINE,
- EInstantMessage dialog = IM_NOTHING_SPECIAL,
- const LLUUID& id = LLUUID::null,
- U32 parent_estate_id = 0,
- const LLUUID& region_id = LLUUID::null,
- const LLVector3& position = LLVector3::zero,
- U32 timestamp = NO_TIMESTAMP,
- const U8* binary_bucket = (U8*)EMPTY_BINARY_BUCKET,
- S32 binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE);
-
-void pack_instant_message_block(
- LLMessageSystem* msgsystem,
- const LLUUID& from_id,
- bool from_group,
- const LLUUID& session_id,
- const LLUUID& to_id,
- const std::string& name,
- const std::string& message,
- U8 offline = IM_ONLINE,
- EInstantMessage dialog = IM_NOTHING_SPECIAL,
- const LLUUID& id = LLUUID::null,
- U32 parent_estate_id = 0,
- const LLUUID& region_id = LLUUID::null,
- const LLVector3& position = LLVector3::zero,
- U32 timestamp = NO_TIMESTAMP,
- const U8* binary_bucket = (U8*)EMPTY_BINARY_BUCKET,
- S32 binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE);
-
-
-#endif // LL_LLINSTANTMESSAGE_H
-
+/**
+ * @file llinstantmessage.h
+ * @brief Constants and declarations used by instant messages.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINSTANTMESSAGE_H
+#define LL_LLINSTANTMESSAGE_H
+
+#include "llhost.h"
+#include "lluuid.h"
+#include "llsd.h"
+#include "llrefcount.h"
+#include "llpointer.h"
+#include "v3math.h"
+
+class LLMessageSystem;
+
+// The ImprovedInstantMessage only supports 8 bits in the "Dialog"
+// field, so don't go past the byte boundary
+enum EInstantMessage
+{
+ // default. ID is meaningless, nothing in the binary bucket.
+ IM_NOTHING_SPECIAL = 0,
+
+ // pops a messagebox with a single OK button
+ IM_MESSAGEBOX = 1,
+
+ // pops a countdown messagebox with a single OK button
+ // IM_MESSAGEBOX_COUNTDOWN = 2,
+
+ // You've been invited to join a group.
+ // ID is the group id.
+
+ // The binary bucket contains a null terminated string
+ // representation of the officer/member status and join cost for
+ // the invitee. (bug # 7672) The format is 1 byte for
+ // officer/member (O for officer, M for member), and as many bytes
+ // as necessary for cost.
+ IM_GROUP_INVITATION = 3,
+
+ // Inventory offer.
+ // ID is the transaction id
+ // Binary bucket is a list of inventory uuid and type.
+ IM_INVENTORY_OFFERED = 4,
+ IM_INVENTORY_ACCEPTED = 5,
+ IM_INVENTORY_DECLINED = 6,
+
+ // Group vote
+ // Name is name of person who called vote.
+ // ID is vote ID used for internal tracking
+ // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856
+ IM_GROUP_VOTE = 7,
+
+ // Group message
+ // This means that the message is meant for everyone in the
+ // agent's group. This will result in a database query to find all
+ // participants and start an im session.
+ IM_GROUP_MESSAGE_DEPRECATED = 8,
+
+ // Task inventory offer.
+ // ID is the transaction id
+ // Binary bucket is a (mostly) complete packed inventory item
+ IM_TASK_INVENTORY_OFFERED = 9,
+ IM_TASK_INVENTORY_ACCEPTED = 10,
+ IM_TASK_INVENTORY_DECLINED = 11,
+
+ // Copied as pending, type LL_NOTHING_SPECIAL, for new users
+ // used by offline tools
+ IM_NEW_USER_DEFAULT = 12,
+
+ //
+ // session based messaging - the way that people usually actually
+ // communicate with each other.
+ //
+
+ // Invite users to a session.
+ IM_SESSION_INVITE = 13,
+
+ IM_SESSION_P2P_INVITE = 14,
+
+ // start a session with your gruop
+ IM_SESSION_GROUP_START = 15,
+
+ // start a session without a calling card (finder or objects)
+ IM_SESSION_CONFERENCE_START = 16,
+
+ // send a message to a session.
+ IM_SESSION_SEND = 17,
+
+ // leave a session
+ IM_SESSION_LEAVE = 18,
+
+ // an instant message from an object - for differentiation on the
+ // viewer, since you can't IM an object yet.
+ IM_FROM_TASK = 19,
+
+ // sent an IM to a do not disturb user, this is the auto response
+ IM_DO_NOT_DISTURB_AUTO_RESPONSE = 20,
+
+ // Shows the message in the console and chat history
+ IM_CONSOLE_AND_CHAT_HISTORY = 21,
+
+ // IM Types used for luring your friends
+ IM_LURE_USER = 22,
+ IM_LURE_ACCEPTED = 23,
+ IM_LURE_DECLINED = 24,
+ IM_GODLIKE_LURE_USER = 25,
+ IM_TELEPORT_REQUEST = 26,
+
+ // IM that notifie of a new group election.
+ // Name is name of person who called vote.
+ // ID is election ID used for internal tracking
+ IM_GROUP_ELECTION_DEPRECATED = 27,
+
+ // IM to tell the user to go to an URL. Put a text message in the
+ // message field, and put the url with a trailing \0 in the binary
+ // bucket.
+ IM_GOTO_URL = 28,
+
+ // a message generated by a script which we don't want to
+ // be sent through e-mail. Similar to IM_FROM_TASK, but
+ // it is shown as an alert on the viewer.
+ IM_FROM_TASK_AS_ALERT = 31,
+
+ // IM from group officer to all group members.
+ IM_GROUP_NOTICE = 32,
+ IM_GROUP_NOTICE_INVENTORY_ACCEPTED = 33,
+ IM_GROUP_NOTICE_INVENTORY_DECLINED = 34,
+
+ IM_GROUP_INVITATION_ACCEPT = 35,
+ IM_GROUP_INVITATION_DECLINE = 36,
+
+ IM_GROUP_NOTICE_REQUESTED = 37,
+
+ IM_FRIENDSHIP_OFFERED = 38,
+ IM_FRIENDSHIP_ACCEPTED = 39,
+ IM_FRIENDSHIP_DECLINED_DEPRECATED = 40,
+
+ IM_TYPING_START = 41,
+ IM_TYPING_STOP = 42,
+
+ IM_COUNT
+};
+
+
+extern const U8 IM_ONLINE;
+extern const U8 IM_OFFLINE;
+
+extern const char EMPTY_BINARY_BUCKET[];
+extern const S32 EMPTY_BINARY_BUCKET_SIZE;
+
+extern const U32 NO_TIMESTAMP;
+extern const std::string SYSTEM_FROM;
+extern const std::string INTERACTIVE_SYSTEM_FROM;
+
+// Number of retry attempts on sending the im.
+extern const S32 IM_TTL;
+
+void pack_instant_message(
+ LLMessageSystem* msgsystem,
+ const LLUUID& from_id,
+ bool from_group,
+ const LLUUID& session_id,
+ const LLUUID& to_id,
+ const std::string& name,
+ const std::string& message,
+ U8 offline = IM_ONLINE,
+ EInstantMessage dialog = IM_NOTHING_SPECIAL,
+ const LLUUID& id = LLUUID::null,
+ U32 parent_estate_id = 0,
+ const LLUUID& region_id = LLUUID::null,
+ const LLVector3& position = LLVector3::zero,
+ U32 timestamp = NO_TIMESTAMP,
+ const U8* binary_bucket = (U8*)EMPTY_BINARY_BUCKET,
+ S32 binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE);
+
+void pack_instant_message_block(
+ LLMessageSystem* msgsystem,
+ const LLUUID& from_id,
+ bool from_group,
+ const LLUUID& session_id,
+ const LLUUID& to_id,
+ const std::string& name,
+ const std::string& message,
+ U8 offline = IM_ONLINE,
+ EInstantMessage dialog = IM_NOTHING_SPECIAL,
+ const LLUUID& id = LLUUID::null,
+ U32 parent_estate_id = 0,
+ const LLUUID& region_id = LLUUID::null,
+ const LLVector3& position = LLVector3::zero,
+ U32 timestamp = NO_TIMESTAMP,
+ const U8* binary_bucket = (U8*)EMPTY_BINARY_BUCKET,
+ S32 binary_bucket_size = EMPTY_BINARY_BUCKET_SIZE);
+
+
+#endif // LL_LLINSTANTMESSAGE_H
+
diff --git a/indra/llmessage/llinvite.h b/indra/llmessage/llinvite.h
index e5d573c1e3..8655f79982 100644
--- a/indra/llmessage/llinvite.h
+++ b/indra/llmessage/llinvite.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llinvite.h
* @brief Constants used for inviting users to join groups.
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -27,7 +27,7 @@
#ifndef LL_LLINVITE_H
#define LL_LLINVITE_H
-const S32 INVITE_LIST_STR_LEN = 324; // Would be larger, but we don't have much room in the CreateGroupRequest msg.
-const S32 INVITE_LIST_BUF_SIZE = 325;
+const S32 INVITE_LIST_STR_LEN = 324; // Would be larger, but we don't have much room in the CreateGroupRequest msg.
+const S32 INVITE_LIST_BUF_SIZE = 325;
#endif // LL_LLINVITE_H
diff --git a/indra/llmessage/lliobuffer.cpp b/indra/llmessage/lliobuffer.cpp
index bbd7b8777d..4f5821b15f 100644
--- a/indra/llmessage/lliobuffer.cpp
+++ b/indra/llmessage/lliobuffer.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliobuffer.cpp
* @author Phoenix
* @date 2005-05-04
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,82 +33,82 @@
// LLIOBuffer
//
LLIOBuffer::LLIOBuffer() :
- mBuffer(NULL),
- mBufferSize(0L),
- mReadHead(NULL),
- mWriteHead(NULL)
+ mBuffer(NULL),
+ mBufferSize(0L),
+ mReadHead(NULL),
+ mWriteHead(NULL)
{
}
LLIOBuffer::~LLIOBuffer()
{
- if(mBuffer)
- {
- delete[] mBuffer;
- }
+ if(mBuffer)
+ {
+ delete[] mBuffer;
+ }
}
U8* LLIOBuffer::data() const
{
- return mBuffer;
+ return mBuffer;
}
S64 LLIOBuffer::size() const
{
- return mBufferSize;
+ return mBufferSize;
}
U8* LLIOBuffer::current() const
{
- return mReadHead;
+ return mReadHead;
}
S64 LLIOBuffer::bytesLeft() const
{
- return mWriteHead - mReadHead;
+ return mWriteHead - mReadHead;
}
void LLIOBuffer::clear()
{
- mReadHead = mBuffer;
- mWriteHead = mBuffer;
+ mReadHead = mBuffer;
+ mWriteHead = mBuffer;
}
LLIOPipe::EStatus LLIOBuffer::seek(LLIOBuffer::EHead head, S64 delta)
{
- LLIOPipe::EStatus status = STATUS_ERROR;
- switch(head)
- {
- case READ:
- if(((delta >= 0) && ((mReadHead + delta) <= mWriteHead))
- || ((delta < 0) && ((mReadHead + delta) >= mBuffer)))
- {
- mReadHead += delta;
- status = STATUS_OK;
- }
- break;
- case WRITE:
- if(((delta >= 0) && ((mWriteHead + delta) < (mBuffer + mBufferSize)))
- || ((delta < 0) && ((mWriteHead + delta) > mReadHead)))
- {
- mWriteHead += delta;
- status = STATUS_OK;
- }
- default:
- break;
- }
- return status;
+ LLIOPipe::EStatus status = STATUS_ERROR;
+ switch(head)
+ {
+ case READ:
+ if(((delta >= 0) && ((mReadHead + delta) <= mWriteHead))
+ || ((delta < 0) && ((mReadHead + delta) >= mBuffer)))
+ {
+ mReadHead += delta;
+ status = STATUS_OK;
+ }
+ break;
+ case WRITE:
+ if(((delta >= 0) && ((mWriteHead + delta) < (mBuffer + mBufferSize)))
+ || ((delta < 0) && ((mWriteHead + delta) > mReadHead)))
+ {
+ mWriteHead += delta;
+ status = STATUS_OK;
+ }
+ default:
+ break;
+ }
+ return status;
}
// virtual
LLIOPipe::EStatus LLIOBuffer::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
- // no-op (I think)
- LL_WARNS() << "You are using an LLIOBuffer which is deprecated." << LL_ENDL;
- return STATUS_OK;
+ // no-op (I think)
+ LL_WARNS() << "You are using an LLIOBuffer which is deprecated." << LL_ENDL;
+ return STATUS_OK;
}
diff --git a/indra/llmessage/lliobuffer.h b/indra/llmessage/lliobuffer.h
index 3349848947..4d4fab5fe4 100644
--- a/indra/llmessage/lliobuffer.h
+++ b/indra/llmessage/lliobuffer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliobuffer.h
* @author Phoenix
* @date 2005-05-04
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -31,7 +31,7 @@
#include "lliopipe.h"
-/**
+/**
* @class LLIOBuffer
* @brief This class is an io class that represents an automtically
* resizing io buffer.
@@ -46,90 +46,90 @@
class LLIOBuffer : public LLIOPipe
{
public:
- LLIOBuffer();
- virtual ~LLIOBuffer();
+ LLIOBuffer();
+ virtual ~LLIOBuffer();
- /**
- * @brief Return a raw pointer to the current data set.
- *
- * The pointer returned can be used for reading or even adjustment
- * if you are a bit crazy up to size() bytes into memory.
- * @return A potentially NULL pointer to the raw buffer data
- */
- U8* data() const;
+ /**
+ * @brief Return a raw pointer to the current data set.
+ *
+ * The pointer returned can be used for reading or even adjustment
+ * if you are a bit crazy up to size() bytes into memory.
+ * @return A potentially NULL pointer to the raw buffer data
+ */
+ U8* data() const;
- /**
- * @brief Return the size of the buffer
- */
- S64 size() const;
+ /**
+ * @brief Return the size of the buffer
+ */
+ S64 size() const;
- /**
- * @brief Return a raw pointer to the current read position in the data.
- *
- * The pointer returned can be used for reading or even adjustment
- * if you are a bit crazy up to bytesLeft() bytes into memory.
- * @return A potentially NULL pointer to the buffer data starting
- * at the read point
- */
- U8* current() const;
+ /**
+ * @brief Return a raw pointer to the current read position in the data.
+ *
+ * The pointer returned can be used for reading or even adjustment
+ * if you are a bit crazy up to bytesLeft() bytes into memory.
+ * @return A potentially NULL pointer to the buffer data starting
+ * at the read point
+ */
+ U8* current() const;
- /**
- * @brief Return the number of unprocessed bytes in buffer.
- */
- S64 bytesLeft() const;
+ /**
+ * @brief Return the number of unprocessed bytes in buffer.
+ */
+ S64 bytesLeft() const;
- /**
- * @brief Move the buffer offsets back to the beginning.
- *
- * This method effectively clears what has been stored here,
- * without mucking around with memory allocation.
- */
- void clear();
+ /**
+ * @brief Move the buffer offsets back to the beginning.
+ *
+ * This method effectively clears what has been stored here,
+ * without mucking around with memory allocation.
+ */
+ void clear();
- /**
- * @brief Enumeration passed into the seek function
- *
- * The READ head is used for where to start processing data for
- * the next link in the chain, while the WRITE head specifies
- * where new data processed from the previous link in the chain
- * will be written.
- */
- enum EHead
- {
- READ,
- WRITE
- };
+ /**
+ * @brief Enumeration passed into the seek function
+ *
+ * The READ head is used for where to start processing data for
+ * the next link in the chain, while the WRITE head specifies
+ * where new data processed from the previous link in the chain
+ * will be written.
+ */
+ enum EHead
+ {
+ READ,
+ WRITE
+ };
- /**
- * @brief Seek to a place in the buffer
- *
- * @param head The READ or WRITE head.
- * @param delta The offset from the current position to seek.
- * @return The status of the operation. status >= if head moved.
- */
- EStatus seek(EHead head, S64 delta);
+ /**
+ * @brief Seek to a place in the buffer
+ *
+ * @param head The READ or WRITE head.
+ * @param delta The offset from the current position to seek.
+ * @return The status of the operation. status >= if head moved.
+ */
+ EStatus seek(EHead head, S64 delta);
public:
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- U8* mBuffer;
- S64 mBufferSize;
- U8* mReadHead;
- U8* mWriteHead;
+ U8* mBuffer;
+ S64 mBufferSize;
+ U8* mReadHead;
+ U8* mWriteHead;
};
#endif // LL_LLIOBUFFER_H
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index e302dd2b5e..9791a20743 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliohttpserver.cpp
* @author Phoenix
* @date 2005-10-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -58,89 +58,89 @@ static void* sTimingCallbackData = NULL;
class LLHTTPPipe : public LLIOPipe
{
public:
- LLHTTPPipe(const LLHTTPNode& node)
- : mNode(node),
- mResponse(NULL),
- mState(STATE_INVOKE),
- mChainLock(0),
- mLockedPump(NULL),
- mStatusCode(0)
- { }
- virtual ~LLHTTPPipe()
- {
- if (mResponse.notNull())
- {
- mResponse->nullPipe();
- }
- }
+ LLHTTPPipe(const LLHTTPNode& node)
+ : mNode(node),
+ mResponse(NULL),
+ mState(STATE_INVOKE),
+ mChainLock(0),
+ mLockedPump(NULL),
+ mStatusCode(0)
+ { }
+ virtual ~LLHTTPPipe()
+ {
+ if (mResponse.notNull())
+ {
+ mResponse->nullPipe();
+ }
+ }
private:
- // LLIOPipe API implementation.
- virtual EStatus process_impl(
+ // LLIOPipe API implementation.
+ virtual EStatus process_impl(
const LLChannelDescriptors& channels,
LLIOPipe::buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump);
- const LLHTTPNode& mNode;
-
- class Response : public LLHTTPNode::Response
- {
- public:
-
- static LLPointer<Response> create(LLHTTPPipe* pipe);
- virtual ~Response();
-
- // from LLHTTPNode::Response
- virtual void result(const LLSD&);
- virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
- virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
- virtual void status(S32 code, const std::string& message);
-
- void nullPipe();
-
- private:
- Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
- LLHTTPPipe* mPipe;
- };
- friend class Response;
-
- LLPointer<Response> mResponse;
-
- enum State
- {
- STATE_INVOKE,
- STATE_DELAYED,
- STATE_LOCKED,
- STATE_GOOD_RESULT,
- STATE_STATUS_RESULT,
- STATE_EXTENDED_RESULT,
- STATE_EXTENDED_LLSD_RESULT
- };
- State mState;
-
- S32 mChainLock;
- LLPumpIO* mLockedPump;
-
- void lockChain(LLPumpIO*);
- void unlockChain();
-
- LLSD mResult;
- S32 mStatusCode;
- std::string mStatusMessage;
- LLSD mHeaders;
+ const LLHTTPNode& mNode;
+
+ class Response : public LLHTTPNode::Response
+ {
+ public:
+
+ static LLPointer<Response> create(LLHTTPPipe* pipe);
+ virtual ~Response();
+
+ // from LLHTTPNode::Response
+ virtual void result(const LLSD&);
+ virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers);
+ virtual void extendedResult(S32 code, const LLSD& body, const LLSD& headers);
+ virtual void status(S32 code, const std::string& message);
+
+ void nullPipe();
+
+ private:
+ Response() : mPipe(NULL) {} // Must be accessed through LLPointer.
+ LLHTTPPipe* mPipe;
+ };
+ friend class Response;
+
+ LLPointer<Response> mResponse;
+
+ enum State
+ {
+ STATE_INVOKE,
+ STATE_DELAYED,
+ STATE_LOCKED,
+ STATE_GOOD_RESULT,
+ STATE_STATUS_RESULT,
+ STATE_EXTENDED_RESULT,
+ STATE_EXTENDED_LLSD_RESULT
+ };
+ State mState;
+
+ S32 mChainLock;
+ LLPumpIO* mLockedPump;
+
+ void lockChain(LLPumpIO*);
+ void unlockChain();
+
+ LLSD mResult;
+ S32 mStatusCode;
+ std::string mStatusMessage;
+ LLSD mHeaders;
};
LLIOPipe::EStatus LLHTTPPipe::process_impl(
- const LLChannelDescriptors& channels,
+ const LLChannelDescriptors& channels,
buffer_ptr_t& buffer,
bool& eos,
LLSD& context,
LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
+ PUMP_DEBUG;
LL_DEBUGS() << "LLSDHTTPServer::process_impl" << LL_ENDL;
// Once we have all the data, We need to read the sd on
@@ -149,166 +149,166 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
if(!eos) return STATUS_BREAK;
if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
- PUMP_DEBUG;
- if (mState == STATE_INVOKE)
- {
- PUMP_DEBUG;
- mState = STATE_DELAYED;
- // assume deferred unless mResponse does otherwise
- mResponse = Response::create(this);
-
- // *TODO: Babbage: Parameterize parser?
- // *TODO: We should look at content-type and do the right
- // thing. Phoenix 2007-12-31
- LLBufferStream istr(channels, buffer.get());
-
- static LLTimer timer;
- timer.reset();
-
- std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
- if(verb == HTTP_VERB_GET)
- {
- mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_PUT)
- {
- LLSD input;
- if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
- {
- LLSDSerialize::fromXML(input, istr);
- }
- else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
- {
- std::ostringstream strstrm;
- strstrm << istr.rdbuf();
- input = strstrm.str();
- }
- mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_POST)
- {
- LLSD input;
- if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
- {
- LLSDSerialize::fromXML(input, istr);
- }
- else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
- {
- std::ostringstream strstrm;
- strstrm << istr.rdbuf();
- input = strstrm.str();
- }
- mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
- }
- else if(verb == HTTP_VERB_DELETE)
- {
- mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else if(verb == HTTP_VERB_OPTIONS)
- {
- mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
- }
- else
- {
- mResponse->methodNotAllowed();
- }
-
- F32 delta = timer.getElapsedTimeF32();
- if (sTimingCallback)
- {
- LLHTTPNode::Description desc;
- mNode.describe(desc);
- LLSD info = desc.getInfo();
- std::string timing_name = info["description"];
- timing_name += " ";
- timing_name += verb;
- sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
- }
-
- // Log all HTTP transactions.
- // TODO: Add a way to log these to their own file instead of indra.log
- // It is just too spammy to be in indra.log.
- LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
- << " " << mStatusCode << " " << mStatusMessage << " " << delta
- << "s" << LL_ENDL;
-
- // Log Internal Server Errors
- //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
- //{
- // LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error"
- // << LL_ENDL;
- //}
- }
-
- PUMP_DEBUG;
- switch (mState)
- {
- case STATE_DELAYED:
- lockChain(pump);
- mState = STATE_LOCKED;
- return STATUS_BREAK;
-
- case STATE_LOCKED:
- // should never ever happen!
- return STATUS_ERROR;
-
- case STATE_GOOD_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- LLBufferStream ostr(channels, buffer.get());
- LLSDSerialize::toXML(mResult, ostr);
-
- return STATUS_DONE;
- }
-
- case STATE_STATUS_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
- LLBufferStream ostr(channels, buffer.get());
- ostr << mStatusMessage;
-
- return STATUS_DONE;
- }
- case STATE_EXTENDED_RESULT:
- {
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- LLBufferStream ostr(channels, buffer.get());
- ostr << mStatusMessage;
-
- return STATUS_DONE;
- }
- case STATE_EXTENDED_LLSD_RESULT:
- {
- LLSD headers = mHeaders;
- headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
- context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
- context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
- LLBufferStream ostr(channels, buffer.get());
- LLSDSerialize::toXML(mResult, ostr);
-
- return STATUS_DONE;
- }
- default:
- LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
- << mState << LL_ENDL;
-
- return STATUS_BREAK;
- }
-// PUMP_DEBUG; // unreachable
+ PUMP_DEBUG;
+ if (mState == STATE_INVOKE)
+ {
+ PUMP_DEBUG;
+ mState = STATE_DELAYED;
+ // assume deferred unless mResponse does otherwise
+ mResponse = Response::create(this);
+
+ // *TODO: Babbage: Parameterize parser?
+ // *TODO: We should look at content-type and do the right
+ // thing. Phoenix 2007-12-31
+ LLBufferStream istr(channels, buffer.get());
+
+ static LLTimer timer;
+ timer.reset();
+
+ std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
+ if(verb == HTTP_VERB_GET)
+ {
+ mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_PUT)
+ {
+ LLSD input;
+ if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
+ {
+ LLSDSerialize::fromXML(input, istr);
+ }
+ else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
+ {
+ std::ostringstream strstrm;
+ strstrm << istr.rdbuf();
+ input = strstrm.str();
+ }
+ mNode.put(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_POST)
+ {
+ LLSD input;
+ if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
+ {
+ LLSDSerialize::fromXML(input, istr);
+ }
+ else if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_TEXT)
+ {
+ std::ostringstream strstrm;
+ strstrm << istr.rdbuf();
+ input = strstrm.str();
+ }
+ mNode.post(LLHTTPNode::ResponsePtr(mResponse), context, input);
+ }
+ else if(verb == HTTP_VERB_DELETE)
+ {
+ mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else if(verb == HTTP_VERB_OPTIONS)
+ {
+ mNode.options(LLHTTPNode::ResponsePtr(mResponse), context);
+ }
+ else
+ {
+ mResponse->methodNotAllowed();
+ }
+
+ F32 delta = timer.getElapsedTimeF32();
+ if (sTimingCallback)
+ {
+ LLHTTPNode::Description desc;
+ mNode.describe(desc);
+ LLSD info = desc.getInfo();
+ std::string timing_name = info["description"];
+ timing_name += " ";
+ timing_name += verb;
+ sTimingCallback(timing_name.c_str(), delta, sTimingCallbackData);
+ }
+
+ // Log all HTTP transactions.
+ // TODO: Add a way to log these to their own file instead of indra.log
+ // It is just too spammy to be in indra.log.
+ LL_DEBUGS() << verb << " " << context[CONTEXT_REQUEST][CONTEXT_PATH].asString()
+ << " " << mStatusCode << " " << mStatusMessage << " " << delta
+ << "s" << LL_ENDL;
+
+ // Log Internal Server Errors
+ //if(mStatusCode == HTTP_INTERNAL_SERVER_ERROR)
+ //{
+ // LL_WARNS() << "LLHTTPPipe::process_impl:500:Internal Server Error"
+ // << LL_ENDL;
+ //}
+ }
+
+ PUMP_DEBUG;
+ switch (mState)
+ {
+ case STATE_DELAYED:
+ lockChain(pump);
+ mState = STATE_LOCKED;
+ return STATUS_BREAK;
+
+ case STATE_LOCKED:
+ // should never ever happen!
+ return STATUS_ERROR;
+
+ case STATE_GOOD_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ LLBufferStream ostr(channels, buffer.get());
+ LLSDSerialize::toXML(mResult, ostr);
+
+ return STATUS_DONE;
+ }
+
+ case STATE_STATUS_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_TEXT_PLAIN;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ context[CONTEXT_RESPONSE]["statusMessage"] = mStatusMessage;
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << mStatusMessage;
+
+ return STATUS_DONE;
+ }
+ case STATE_EXTENDED_RESULT:
+ {
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = mHeaders;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ LLBufferStream ostr(channels, buffer.get());
+ ostr << mStatusMessage;
+
+ return STATUS_DONE;
+ }
+ case STATE_EXTENDED_LLSD_RESULT:
+ {
+ LLSD headers = mHeaders;
+ headers[HTTP_OUT_HEADER_CONTENT_TYPE] = HTTP_CONTENT_LLSD_XML;
+ context[CONTEXT_RESPONSE][CONTEXT_HEADERS] = headers;
+ context[CONTEXT_RESPONSE]["statusCode"] = mStatusCode;
+ LLBufferStream ostr(channels, buffer.get());
+ LLSDSerialize::toXML(mResult, ostr);
+
+ return STATUS_DONE;
+ }
+ default:
+ LL_WARNS() << "LLHTTPPipe::process_impl: unexpected state "
+ << mState << LL_ENDL;
+
+ return STATUS_BREAK;
+ }
+// PUMP_DEBUG; // unreachable
}
LLPointer<LLHTTPPipe::Response> LLHTTPPipe::Response::create(LLHTTPPipe* pipe)
{
- LLPointer<Response> result = new Response();
- result->mPipe = pipe;
- return result;
+ LLPointer<Response> result = new Response();
+ result->mPipe = pipe;
+ return result;
}
// virtual
@@ -318,93 +318,93 @@ LLHTTPPipe::Response::~Response()
void LLHTTPPipe::Response::nullPipe()
{
- mPipe = NULL;
+ mPipe = NULL;
}
// virtual
void LLHTTPPipe::Response::result(const LLSD& r)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::result: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = HTTP_OK;
- mPipe->mStatusMessage = "OK";
- mPipe->mResult = r;
- mPipe->mState = STATE_GOOD_RESULT;
- mPipe->mHeaders = mHeaders;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::result: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = HTTP_OK;
+ mPipe->mStatusMessage = "OK";
+ mPipe->mResult = r;
+ mPipe->mState = STATE_GOOD_RESULT;
+ mPipe->mHeaders = mHeaders;
+ mPipe->unlockChain();
}
void LLHTTPPipe::Response::extendedResult(S32 code, const LLSD& r, const LLSD& headers)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = "(LLSD)";
- mPipe->mResult = r;
- mPipe->mHeaders = headers;
- mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::extendedResult: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = "(LLSD)";
+ mPipe->mResult = r;
+ mPipe->mHeaders = headers;
+ mPipe->mState = STATE_EXTENDED_LLSD_RESULT;
+ mPipe->unlockChain();
}
void LLHTTPPipe::Response::extendedResult(S32 code, const std::string& body, const LLSD& headers)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = body;
- mPipe->mHeaders = headers;
- mPipe->mState = STATE_EXTENDED_RESULT;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = body;
+ mPipe->mHeaders = headers;
+ mPipe->mState = STATE_EXTENDED_RESULT;
+ mPipe->unlockChain();
}
// virtual
void LLHTTPPipe::Response::status(S32 code, const std::string& message)
{
- if(! mPipe)
- {
- LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
- return;
- }
-
- mPipe->mStatusCode = code;
- mPipe->mStatusMessage = message;
- mPipe->mState = STATE_STATUS_RESULT;
- mPipe->mHeaders = mHeaders;
- mPipe->unlockChain();
+ if(! mPipe)
+ {
+ LL_WARNS() << "LLHTTPPipe::Response::status: NULL pipe" << LL_ENDL;
+ return;
+ }
+
+ mPipe->mStatusCode = code;
+ mPipe->mStatusMessage = message;
+ mPipe->mState = STATE_STATUS_RESULT;
+ mPipe->mHeaders = mHeaders;
+ mPipe->unlockChain();
}
void LLHTTPPipe::lockChain(LLPumpIO* pump)
{
- if (mChainLock != 0) { return; }
+ if (mChainLock != 0) { return; }
- mLockedPump = pump;
- mChainLock = pump->setLock();
+ mLockedPump = pump;
+ mChainLock = pump->setLock();
}
void LLHTTPPipe::unlockChain()
{
- if (mChainLock == 0) { return; }
+ if (mChainLock == 0) { return; }
- mLockedPump->clearLock(mChainLock);
- mLockedPump = NULL;
- mChainLock = 0;
+ mLockedPump->clearLock(mChainLock);
+ mLockedPump = NULL;
+ mChainLock = 0;
}
-/**
+/**
* @class LLHTTPResponseHeader
* @brief Class which correctly builds HTTP headers on a pipe
* @see LLIOPipe
@@ -418,26 +418,26 @@ void LLHTTPPipe::unlockChain()
class LLHTTPResponseHeader : public LLIOPipe
{
public:
- LLHTTPResponseHeader() : mCode(0) {}
- virtual ~LLHTTPResponseHeader() {}
+ LLHTTPResponseHeader() : mCode(0) {}
+ virtual ~LLHTTPResponseHeader() {}
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- S32 mCode;
+ S32 mCode;
};
@@ -447,66 +447,66 @@ protected:
// virtual
LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(eos)
- {
- PUMP_DEBUG;
- //mGotEOS = true;
- std::ostringstream ostr;
- std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
-
- int code = context[CONTEXT_RESPONSE]["statusCode"];
- if (code < HTTP_OK)
- {
- code = HTTP_OK;
- message = "OK";
- }
-
- ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
-
- S32 content_length = buffer->countAfter(channels.in(), NULL);
- if(0 < content_length)
- {
- ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
- }
- // *NOTE: This guard can go away once the LLSD static map
- // iterator is available. Phoenix. 2008-05-09
- LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
- if(headers.isDefined())
- {
- LLSD::map_iterator iter = headers.beginMap();
- LLSD::map_iterator end = headers.endMap();
- for(; iter != end; ++iter)
- {
- ostr << (*iter).first << ": " << (*iter).second.asString()
- << "\r\n";
- }
- }
- ostr << "\r\n";
-
- LLChangeChannel change(channels.in(), channels.out());
- std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
- std::string header = ostr.str();
- buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
- PUMP_DEBUG;
- return STATUS_DONE;
- }
- PUMP_DEBUG;
- return STATUS_OK;
+ PUMP_DEBUG;
+ if(eos)
+ {
+ PUMP_DEBUG;
+ //mGotEOS = true;
+ std::ostringstream ostr;
+ std::string message = context[CONTEXT_RESPONSE]["statusMessage"];
+
+ int code = context[CONTEXT_RESPONSE]["statusCode"];
+ if (code < HTTP_OK)
+ {
+ code = HTTP_OK;
+ message = "OK";
+ }
+
+ ostr << HTTP_VERSION_STR << " " << code << " " << message << "\r\n";
+
+ S32 content_length = buffer->countAfter(channels.in(), NULL);
+ if(0 < content_length)
+ {
+ ostr << HTTP_OUT_HEADER_CONTENT_LENGTH << ": " << content_length << "\r\n";
+ }
+ // *NOTE: This guard can go away once the LLSD static map
+ // iterator is available. Phoenix. 2008-05-09
+ LLSD headers = context[CONTEXT_RESPONSE][CONTEXT_HEADERS];
+ if(headers.isDefined())
+ {
+ LLSD::map_iterator iter = headers.beginMap();
+ LLSD::map_iterator end = headers.endMap();
+ for(; iter != end; ++iter)
+ {
+ ostr << (*iter).first << ": " << (*iter).second.asString()
+ << "\r\n";
+ }
+ }
+ ostr << "\r\n";
+
+ LLChangeChannel change(channels.in(), channels.out());
+ std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
+ std::string header = ostr.str();
+ buffer->prepend(channels.out(), (U8*)header.c_str(), header.size());
+ PUMP_DEBUG;
+ return STATUS_DONE;
+ }
+ PUMP_DEBUG;
+ return STATUS_OK;
}
-/**
+/**
* @class LLHTTPResponder
- * @brief This class
+ * @brief This class
* @see LLIOPipe
*
* <b>NOTE:</b> You should not need to create or use one of these, the
@@ -515,464 +515,464 @@ LLIOPipe::EStatus LLHTTPResponseHeader::process_impl(
class LLHTTPResponder : public LLIOPipe
{
public:
- LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
- ~LLHTTPResponder();
+ LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx);
+ ~LLHTTPResponder();
protected:
- /**
- * @brief Read data off of CHANNEL_IN keeping track of last read position.
- *
- * This is a quick little hack to read headers. It is not IO
- * optimal, but it makes it easier for me to implement the header
- * parsing. Plus, there should never be more than a few headers.
- * This method will tend to read more than necessary, find the
- * newline, make the front part of dest look like a c string, and
- * move the read head back to where the newline was found. Thus,
- * the next read will pick up on the next line.
- * @param channel The channel to read in the buffer
- * @param buffer The heap array of processed data
- * @param dest Destination for the data to be read
- * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how
- * much was read. This value is not useful for determining where to
- * seek orfor string assignment.
- * @returns Returns true if a line was found.
- */
- bool readHeaderLine(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer,
- U8* dest,
- S32& len);
-
- /**
- * @brief Mark the request as bad, and handle appropriately
- *
- * @param channels The channels to use in the buffer.
- * @param buffer The heap array of processed data.
- */
- void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
+ /**
+ * @brief Read data off of CHANNEL_IN keeping track of last read position.
+ *
+ * This is a quick little hack to read headers. It is not IO
+ * optimal, but it makes it easier for me to implement the header
+ * parsing. Plus, there should never be more than a few headers.
+ * This method will tend to read more than necessary, find the
+ * newline, make the front part of dest look like a c string, and
+ * move the read head back to where the newline was found. Thus,
+ * the next read will pick up on the next line.
+ * @param channel The channel to read in the buffer
+ * @param buffer The heap array of processed data
+ * @param dest Destination for the data to be read
+ * @param[in,out] len <b>in</b> The size of the buffer. <b>out</b> how
+ * much was read. This value is not useful for determining where to
+ * seek orfor string assignment.
+ * @returns Returns true if a line was found.
+ */
+ bool readHeaderLine(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer,
+ U8* dest,
+ S32& len);
+
+ /**
+ * @brief Mark the request as bad, and handle appropriately
+ *
+ * @param channels The channels to use in the buffer.
+ * @param buffer The heap array of processed data.
+ */
+ void markBad(const LLChannelDescriptors& channels, buffer_ptr_t buffer);
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- enum EState
- {
- STATE_NOTHING,
- STATE_READING_HEADERS,
- STATE_LOOKING_FOR_EOS,
- STATE_DONE,
- STATE_SHORT_CIRCUIT
- };
-
- LLSD mBuildContext;
- EState mState;
- U8* mLastRead;
- std::string mVerb;
- std::string mAbsPathAndQuery;
- std::string mPath;
- std::string mQuery;
- std::string mVersion;
- S32 mContentLength;
- LLSD mHeaders;
-
- // handle the urls
- const LLHTTPNode& mRootNode;
+ enum EState
+ {
+ STATE_NOTHING,
+ STATE_READING_HEADERS,
+ STATE_LOOKING_FOR_EOS,
+ STATE_DONE,
+ STATE_SHORT_CIRCUIT
+ };
+
+ LLSD mBuildContext;
+ EState mState;
+ U8* mLastRead;
+ std::string mVerb;
+ std::string mAbsPathAndQuery;
+ std::string mPath;
+ std::string mQuery;
+ std::string mVersion;
+ S32 mContentLength;
+ LLSD mHeaders;
+
+ // handle the urls
+ const LLHTTPNode& mRootNode;
};
LLHTTPResponder::LLHTTPResponder(const LLHTTPNode& tree, const LLSD& ctx) :
- mBuildContext(ctx),
- mState(STATE_NOTHING),
- mLastRead(NULL),
- mContentLength(0),
- mRootNode(tree)
+ mBuildContext(ctx),
+ mState(STATE_NOTHING),
+ mLastRead(NULL),
+ mContentLength(0),
+ mRootNode(tree)
{
}
// virtual
LLHTTPResponder::~LLHTTPResponder()
{
- //LL_DEBUGS() << "destroying LLHTTPResponder" << LL_ENDL;
+ //LL_DEBUGS() << "destroying LLHTTPResponder" << LL_ENDL;
}
bool LLHTTPResponder::readHeaderLine(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer,
- U8* dest,
- S32& len)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer,
+ U8* dest,
+ S32& len)
{
- --len;
- U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
- dest[len] = '\0';
- U8* newline = (U8*)strchr((char*)dest, '\n');
- if(!newline)
- {
- if(len)
- {
- LL_DEBUGS() << "readLine failed - too long maybe?" << LL_ENDL;
- markBad(channels, buffer);
- }
- return false;
- }
- S32 offset = -((len - 1) - (newline - dest));
- ++newline;
- *newline = '\0';
- mLastRead = buffer->seek(channels.in(), last, offset);
- return true;
+ --len;
+ U8* last = buffer->readAfter(channels.in(), mLastRead, dest, len);
+ dest[len] = '\0';
+ U8* newline = (U8*)strchr((char*)dest, '\n');
+ if(!newline)
+ {
+ if(len)
+ {
+ LL_DEBUGS() << "readLine failed - too long maybe?" << LL_ENDL;
+ markBad(channels, buffer);
+ }
+ return false;
+ }
+ S32 offset = -((len - 1) - (newline - dest));
+ ++newline;
+ *newline = '\0';
+ mLastRead = buffer->seek(channels.in(), last, offset);
+ return true;
}
void LLHTTPResponder::markBad(
- const LLChannelDescriptors& channels,
- buffer_ptr_t buffer)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t buffer)
{
- mState = STATE_SHORT_CIRCUIT;
- LLBufferStream out(channels, buffer.get());
- out << HTTP_VERSION_STR << " 400 Bad Request\r\n\r\n<html>\n"
- << "<title>Bad Request</title>\n<body>\nBad Request.\n"
- << "</body>\n</html>\n";
+ mState = STATE_SHORT_CIRCUIT;
+ LLBufferStream out(channels, buffer.get());
+ out << HTTP_VERSION_STR << " 400 Bad Request\r\n\r\n<html>\n"
+ << "<title>Bad Request</title>\n<body>\nBad Request.\n"
+ << "</body>\n</html>\n";
}
// virtual
LLIOPipe::EStatus LLHTTPResponder::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- LLIOPipe::EStatus status = STATUS_OK;
-
- // parsing headers
- if((STATE_NOTHING == mState) || (STATE_READING_HEADERS == mState))
- {
- PUMP_DEBUG;
- status = STATUS_BREAK;
- mState = STATE_READING_HEADERS;
- const S32 HEADER_BUFFER_SIZE = 1024;
- char buf[HEADER_BUFFER_SIZE + 1]; /*Flawfinder: ignore*/
- S32 len = HEADER_BUFFER_SIZE;
+ PUMP_DEBUG;
+ LLIOPipe::EStatus status = STATUS_OK;
+
+ // parsing headers
+ if((STATE_NOTHING == mState) || (STATE_READING_HEADERS == mState))
+ {
+ PUMP_DEBUG;
+ status = STATUS_BREAK;
+ mState = STATE_READING_HEADERS;
+ const S32 HEADER_BUFFER_SIZE = 1024;
+ char buf[HEADER_BUFFER_SIZE + 1]; /*Flawfinder: ignore*/
+ S32 len = HEADER_BUFFER_SIZE;
#if 0
- if(true)
- {
- LLBufferArray::segment_iterator_t seg_iter = buffer->beginSegment();
- char buf[1024]; /*Flawfinder: ignore*/
- while(seg_iter != buffer->endSegment())
- {
- memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
- buf[(*seg_iter).size()] = '\0';
- LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
- << LL_ENDL;
- ++seg_iter;
- }
- }
+ if(true)
+ {
+ LLBufferArray::segment_iterator_t seg_iter = buffer->beginSegment();
+ char buf[1024]; /*Flawfinder: ignore*/
+ while(seg_iter != buffer->endSegment())
+ {
+ memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
+ buf[(*seg_iter).size()] = '\0';
+ LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
+ << LL_ENDL;
+ ++seg_iter;
+ }
+ }
#endif
-
- PUMP_DEBUG;
- if(readHeaderLine(channels, buffer, (U8*)buf, len))
- {
- bool read_next_line = false;
- bool parse_all = true;
- if(mVerb.empty())
- {
- read_next_line = true;
- LLMemoryStream header((U8*)buf, len);
- header >> mVerb;
-
- if((HTTP_VERB_GET == mVerb)
- || (HTTP_VERB_POST == mVerb)
- || (HTTP_VERB_PUT == mVerb)
- || (HTTP_VERB_DELETE == mVerb)
- || (HTTP_VERB_OPTIONS == mVerb))
- {
- header >> mAbsPathAndQuery;
- header >> mVersion;
-
- LL_DEBUGS() << "http request: "
- << mVerb
- << " " << mAbsPathAndQuery
- << " " << mVersion << LL_ENDL;
-
- std::string::size_type delimiter
- = mAbsPathAndQuery.find('?');
- if (delimiter == std::string::npos)
- {
- mPath = mAbsPathAndQuery;
- mQuery = "";
- }
- else
- {
- mPath = mAbsPathAndQuery.substr(0, delimiter);
- mQuery = mAbsPathAndQuery.substr(delimiter+1);
- }
-
- if(!mAbsPathAndQuery.empty())
- {
- if(mVersion.empty())
- {
- // simple request.
- parse_all = false;
- mState = STATE_DONE;
- mVersion.assign("HTTP/1.0");
- }
- }
- }
- else
- {
- read_next_line = false;
- parse_all = false;
- LL_DEBUGS() << "unknown http verb: " << mVerb << LL_ENDL;
- markBad(channels, buffer);
- }
- }
- if(parse_all)
- {
- bool keep_parsing = true;
- while(keep_parsing)
- {
- if(read_next_line)
- {
- len = HEADER_BUFFER_SIZE;
- if (!readHeaderLine(channels, buffer, (U8*)buf, len))
- {
- // Failed to read the header line, probably too long.
- // readHeaderLine already marked the channel/buffer as bad.
- keep_parsing = false;
- break;
- }
- }
- if(0 == len)
- {
- return status;
- }
- if(buf[0] == '\r' && buf[1] == '\n')
- {
- // end-o-headers
- keep_parsing = false;
- mState = STATE_LOOKING_FOR_EOS;
- break;
- }
- char* pos_colon = strchr(buf, ':');
- if(NULL == pos_colon)
- {
- keep_parsing = false;
- LL_DEBUGS() << "bad header: " << buf << LL_ENDL;
- markBad(channels, buffer);
- break;
- }
- // we've found a header
- read_next_line = true;
- std::string name(buf, pos_colon - buf);
- std::string value(pos_colon + 2);
- LLStringUtil::toLower(name);
- if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
- {
- LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
- mContentLength = atoi(value.c_str());
- }
- else
- {
- LLStringUtil::trimTail(value);
- mHeaders[name] = value;
- }
- }
- }
- }
- }
-
- PUMP_DEBUG;
- // look for the end of stream based on
- if(STATE_LOOKING_FOR_EOS == mState)
- {
- if(0 == mContentLength)
- {
- mState = STATE_DONE;
- }
- else if(buffer->countAfter(channels.in(), mLastRead) >= mContentLength)
- {
- mState = STATE_DONE;
- }
- // else more bytes should be coming.
- }
-
- PUMP_DEBUG;
- if(STATE_DONE == mState)
- {
- // hey, hey, we should have everything now, so we pass it to
- // a content handler.
- context[CONTEXT_REQUEST][CONTEXT_VERB] = mVerb;
- const LLHTTPNode* node = mRootNode.traverse(mPath, context);
- if(node)
- {
- //LL_INFOS() << "LLHTTPResponder::process_impl found node for "
- // << mAbsPathAndQuery << LL_ENDL;
-
- // Copy everything after mLast read to the out.
- LLBufferArray::segment_iterator_t seg_iter;
-
- buffer->lock();
- seg_iter = buffer->splitAfter(mLastRead);
- if(seg_iter != buffer->endSegment())
- {
- LLChangeChannel change(channels.in(), channels.out());
- ++seg_iter;
- std::for_each(seg_iter, buffer->endSegment(), change);
+
+ PUMP_DEBUG;
+ if(readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ bool read_next_line = false;
+ bool parse_all = true;
+ if(mVerb.empty())
+ {
+ read_next_line = true;
+ LLMemoryStream header((U8*)buf, len);
+ header >> mVerb;
+
+ if((HTTP_VERB_GET == mVerb)
+ || (HTTP_VERB_POST == mVerb)
+ || (HTTP_VERB_PUT == mVerb)
+ || (HTTP_VERB_DELETE == mVerb)
+ || (HTTP_VERB_OPTIONS == mVerb))
+ {
+ header >> mAbsPathAndQuery;
+ header >> mVersion;
+
+ LL_DEBUGS() << "http request: "
+ << mVerb
+ << " " << mAbsPathAndQuery
+ << " " << mVersion << LL_ENDL;
+
+ std::string::size_type delimiter
+ = mAbsPathAndQuery.find('?');
+ if (delimiter == std::string::npos)
+ {
+ mPath = mAbsPathAndQuery;
+ mQuery = "";
+ }
+ else
+ {
+ mPath = mAbsPathAndQuery.substr(0, delimiter);
+ mQuery = mAbsPathAndQuery.substr(delimiter+1);
+ }
+
+ if(!mAbsPathAndQuery.empty())
+ {
+ if(mVersion.empty())
+ {
+ // simple request.
+ parse_all = false;
+ mState = STATE_DONE;
+ mVersion.assign("HTTP/1.0");
+ }
+ }
+ }
+ else
+ {
+ read_next_line = false;
+ parse_all = false;
+ LL_DEBUGS() << "unknown http verb: " << mVerb << LL_ENDL;
+ markBad(channels, buffer);
+ }
+ }
+ if(parse_all)
+ {
+ bool keep_parsing = true;
+ while(keep_parsing)
+ {
+ if(read_next_line)
+ {
+ len = HEADER_BUFFER_SIZE;
+ if (!readHeaderLine(channels, buffer, (U8*)buf, len))
+ {
+ // Failed to read the header line, probably too long.
+ // readHeaderLine already marked the channel/buffer as bad.
+ keep_parsing = false;
+ break;
+ }
+ }
+ if(0 == len)
+ {
+ return status;
+ }
+ if(buf[0] == '\r' && buf[1] == '\n')
+ {
+ // end-o-headers
+ keep_parsing = false;
+ mState = STATE_LOOKING_FOR_EOS;
+ break;
+ }
+ char* pos_colon = strchr(buf, ':');
+ if(NULL == pos_colon)
+ {
+ keep_parsing = false;
+ LL_DEBUGS() << "bad header: " << buf << LL_ENDL;
+ markBad(channels, buffer);
+ break;
+ }
+ // we've found a header
+ read_next_line = true;
+ std::string name(buf, pos_colon - buf);
+ std::string value(pos_colon + 2);
+ LLStringUtil::toLower(name);
+ if(HTTP_IN_HEADER_CONTENT_LENGTH == name)
+ {
+ LL_DEBUGS() << "Content-Length: " << value << LL_ENDL;
+ mContentLength = atoi(value.c_str());
+ }
+ else
+ {
+ LLStringUtil::trimTail(value);
+ mHeaders[name] = value;
+ }
+ }
+ }
+ }
+ }
+
+ PUMP_DEBUG;
+ // look for the end of stream based on
+ if(STATE_LOOKING_FOR_EOS == mState)
+ {
+ if(0 == mContentLength)
+ {
+ mState = STATE_DONE;
+ }
+ else if(buffer->countAfter(channels.in(), mLastRead) >= mContentLength)
+ {
+ mState = STATE_DONE;
+ }
+ // else more bytes should be coming.
+ }
+
+ PUMP_DEBUG;
+ if(STATE_DONE == mState)
+ {
+ // hey, hey, we should have everything now, so we pass it to
+ // a content handler.
+ context[CONTEXT_REQUEST][CONTEXT_VERB] = mVerb;
+ const LLHTTPNode* node = mRootNode.traverse(mPath, context);
+ if(node)
+ {
+ //LL_INFOS() << "LLHTTPResponder::process_impl found node for "
+ // << mAbsPathAndQuery << LL_ENDL;
+
+ // Copy everything after mLast read to the out.
+ LLBufferArray::segment_iterator_t seg_iter;
+
+ buffer->lock();
+ seg_iter = buffer->splitAfter(mLastRead);
+ if(seg_iter != buffer->endSegment())
+ {
+ LLChangeChannel change(channels.in(), channels.out());
+ ++seg_iter;
+ std::for_each(seg_iter, buffer->endSegment(), change);
#if 0
- seg_iter = buffer->beginSegment();
- char buf[1024]; /*Flawfinder: ignore*/
- while(seg_iter != buffer->endSegment())
- {
- memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
- buf[(*seg_iter).size()] = '\0';
- LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
- << LL_ENDL;
- ++seg_iter;
- }
+ seg_iter = buffer->beginSegment();
+ char buf[1024]; /*Flawfinder: ignore*/
+ while(seg_iter != buffer->endSegment())
+ {
+ memcpy(buf, (*seg_iter).data(), (*seg_iter).size()); /*Flawfinder: ignore*/
+ buf[(*seg_iter).size()] = '\0';
+ LL_INFOS() << (*seg_iter).getChannel() << ": " << buf
+ << LL_ENDL;
+ ++seg_iter;
+ }
#endif
- }
- buffer->unlock();
- //
- // *FIX: get rid of extra bytes off the end
- //
-
- // Set up a chain which will prepend a content length and
- // HTTP headers.
- LLPumpIO::chain_t chain;
- chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
- context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
- context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
- context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
- = mBuildContext[CONTEXT_REMOTE_HOST];
- context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
- = mBuildContext[CONTEXT_REMOTE_PORT];
- context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
-
- const LLChainIOFactory* protocolHandler
- = node->getProtocolHandler();
- if (protocolHandler)
- {
- LL_DEBUGS() << "HTTP context: " << context << LL_ENDL;
- protocolHandler->build(chain, context);
- }
- else
- {
- // this is a simple LLHTTPNode, so use LLHTTPPipe
- chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
- }
-
- // Add the header - which needs to have the same
- // channel information as the link before it since it
- // is part of the response.
- LLIOPipe* header = new LLHTTPResponseHeader;
- chain.push_back(LLIOPipe::ptr_t(header));
-
- // We need to copy all of the pipes _after_ this so
- // that the response goes out correctly.
- LLPumpIO::links_t current_links;
- pump->copyCurrentLinkInfo(current_links);
- LLPumpIO::links_t::iterator link_iter = current_links.begin();
- LLPumpIO::links_t::iterator links_end = current_links.end();
- bool after_this = false;
- for(; link_iter < links_end; ++link_iter)
- {
- if(after_this)
- {
- chain.push_back((*link_iter).mPipe);
- }
- else if(this == (*link_iter).mPipe.get())
- {
- after_this = true;
- }
- }
-
- // Do the final build of the chain, and send it on
- // it's way.
- LLChannelDescriptors chnl = channels;
- LLPumpIO::LLLinkInfo link;
- LLPumpIO::links_t links;
- LLPumpIO::chain_t::iterator it = chain.begin();
- LLPumpIO::chain_t::iterator end = chain.end();
- while(it != end)
- {
- link.mPipe = *it;
- link.mChannels = chnl;
- links.push_back(link);
- chnl = LLBufferArray::makeChannelConsumer(chnl);
- ++it;
- }
- pump->addChain(
- links,
- buffer,
- context,
- DEFAULT_CHAIN_EXPIRY_SECS);
-
- status = STATUS_STOP;
- }
- else
- {
- LL_WARNS() << "LLHTTPResponder::process_impl didn't find a node for "
- << mAbsPathAndQuery << LL_ENDL;
- LLBufferStream str(channels, buffer.get());
- mState = STATE_SHORT_CIRCUIT;
- str << HTTP_VERSION_STR << " 404 Not Found\r\n\r\n<html>\n"
- << "<title>Not Found</title>\n<body>\nNode '" << mAbsPathAndQuery
- << "' not found.\n</body>\n</html>\n";
- }
- }
-
- if(STATE_SHORT_CIRCUIT == mState)
- {
- //status = mNext->process(buffer, true, pump, context);
- status = STATUS_DONE;
- }
- PUMP_DEBUG;
- return status;
+ }
+ buffer->unlock();
+ //
+ // *FIX: get rid of extra bytes off the end
+ //
+
+ // Set up a chain which will prepend a content length and
+ // HTTP headers.
+ LLPumpIO::chain_t chain;
+ chain.push_back(LLIOPipe::ptr_t(new LLIOFlush));
+ context[CONTEXT_REQUEST][CONTEXT_PATH] = mPath;
+ context[CONTEXT_REQUEST][CONTEXT_QUERY_STRING] = mQuery;
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST]
+ = mBuildContext[CONTEXT_REMOTE_HOST];
+ context[CONTEXT_REQUEST][CONTEXT_REMOTE_PORT]
+ = mBuildContext[CONTEXT_REMOTE_PORT];
+ context[CONTEXT_REQUEST][CONTEXT_HEADERS] = mHeaders;
+
+ const LLChainIOFactory* protocolHandler
+ = node->getProtocolHandler();
+ if (protocolHandler)
+ {
+ LL_DEBUGS() << "HTTP context: " << context << LL_ENDL;
+ protocolHandler->build(chain, context);
+ }
+ else
+ {
+ // this is a simple LLHTTPNode, so use LLHTTPPipe
+ chain.push_back(LLIOPipe::ptr_t(new LLHTTPPipe(*node)));
+ }
+
+ // Add the header - which needs to have the same
+ // channel information as the link before it since it
+ // is part of the response.
+ LLIOPipe* header = new LLHTTPResponseHeader;
+ chain.push_back(LLIOPipe::ptr_t(header));
+
+ // We need to copy all of the pipes _after_ this so
+ // that the response goes out correctly.
+ LLPumpIO::links_t current_links;
+ pump->copyCurrentLinkInfo(current_links);
+ LLPumpIO::links_t::iterator link_iter = current_links.begin();
+ LLPumpIO::links_t::iterator links_end = current_links.end();
+ bool after_this = false;
+ for(; link_iter < links_end; ++link_iter)
+ {
+ if(after_this)
+ {
+ chain.push_back((*link_iter).mPipe);
+ }
+ else if(this == (*link_iter).mPipe.get())
+ {
+ after_this = true;
+ }
+ }
+
+ // Do the final build of the chain, and send it on
+ // it's way.
+ LLChannelDescriptors chnl = channels;
+ LLPumpIO::LLLinkInfo link;
+ LLPumpIO::links_t links;
+ LLPumpIO::chain_t::iterator it = chain.begin();
+ LLPumpIO::chain_t::iterator end = chain.end();
+ while(it != end)
+ {
+ link.mPipe = *it;
+ link.mChannels = chnl;
+ links.push_back(link);
+ chnl = LLBufferArray::makeChannelConsumer(chnl);
+ ++it;
+ }
+ pump->addChain(
+ links,
+ buffer,
+ context,
+ DEFAULT_CHAIN_EXPIRY_SECS);
+
+ status = STATUS_STOP;
+ }
+ else
+ {
+ LL_WARNS() << "LLHTTPResponder::process_impl didn't find a node for "
+ << mAbsPathAndQuery << LL_ENDL;
+ LLBufferStream str(channels, buffer.get());
+ mState = STATE_SHORT_CIRCUIT;
+ str << HTTP_VERSION_STR << " 404 Not Found\r\n\r\n<html>\n"
+ << "<title>Not Found</title>\n<body>\nNode '" << mAbsPathAndQuery
+ << "' not found.\n</body>\n</html>\n";
+ }
+ }
+
+ if(STATE_SHORT_CIRCUIT == mState)
+ {
+ //status = mNext->process(buffer, true, pump, context);
+ status = STATUS_DONE;
+ }
+ PUMP_DEBUG;
+ return status;
}
-// static
-void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain,
+// static
+void LLIOHTTPServer::createPipe(LLPumpIO::chain_t& chain,
const LLHTTPNode& root, const LLSD& ctx)
{
- chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
+ chain.push_back(LLIOPipe::ptr_t(new LLHTTPResponder(root, ctx)));
}
class LLHTTPResponseFactory : public LLChainIOFactory
{
public:
- bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
- {
- LLIOHTTPServer::createPipe(chain, mTree, ctx);
- return true;
- }
+ bool build(LLPumpIO::chain_t& chain, LLSD ctx) const
+ {
+ LLIOHTTPServer::createPipe(chain, mTree, ctx);
+ return true;
+ }
- LLHTTPNode& getRootNode() { return mTree; }
+ LLHTTPNode& getRootNode() { return mTree; }
private:
- LLHTTPNode mTree;
+ LLHTTPNode mTree;
};
// static
LLHTTPNode& LLIOHTTPServer::create(
- apr_pool_t* pool, LLPumpIO& pump, U16 port)
+ apr_pool_t* pool, LLPumpIO& pump, U16 port)
{
- LLSocket::ptr_t socket = LLSocket::create(
+ LLSocket::ptr_t socket = LLSocket::create(
pool,
LLSocket::STREAM_TCP,
port);
@@ -982,21 +982,21 @@ LLHTTPNode& LLIOHTTPServer::create(
}
LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
- std::shared_ptr<LLChainIOFactory> factory_ptr(factory);
+ std::shared_ptr<LLChainIOFactory> factory_ptr(factory);
LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
- LLPumpIO::chain_t chain;
+ LLPumpIO::chain_t chain;
chain.push_back(LLIOPipe::ptr_t(server));
pump.addChain(chain, NEVER_CHAIN_EXPIRY_SECS);
- return factory->getRootNode();
+ return factory->getRootNode();
}
// static
void LLIOHTTPServer::setTimingCallback(timing_callback_t callback,
- void* data)
+ void* data)
{
- sTimingCallback = callback;
- sTimingCallbackData = data;
+ sTimingCallback = callback;
+ sTimingCallbackData = data;
}
diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h
index a23eafe58a..a1ae8736b7 100644
--- a/indra/llmessage/lliohttpserver.h
+++ b/indra/llmessage/lliohttpserver.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliohttpserver.h
* @brief Declaration of function for creating an HTTP wire server
* @see LLIOServerSocket, LLPumpIO
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,38 +36,38 @@ class LLPumpIO;
class LLIOHTTPServer
{
public:
- typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data);
-
- static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port);
- /**< Creates an HTTP wire server on the pump for the given TCP port.
- *
- * Returns the root node of the new server. Add LLHTTPNode instances
- * to this root.
- *
- * Nodes that return NULL for getProtocolHandler(), will use the
- * default handler that interprets HTTP on the wire and converts
- * it into calls to get(), put(), post(), del() with appropriate
- * LLSD arguments and results.
- *
- * To have nodes that implement some other wire protocol (XML-RPC
- * for example), use the helper templates below.
- */
-
- static void createPipe(LLPumpIO::chain_t& chain,
+ typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data);
+
+ static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port);
+ /**< Creates an HTTP wire server on the pump for the given TCP port.
+ *
+ * Returns the root node of the new server. Add LLHTTPNode instances
+ * to this root.
+ *
+ * Nodes that return NULL for getProtocolHandler(), will use the
+ * default handler that interprets HTTP on the wire and converts
+ * it into calls to get(), put(), post(), del() with appropriate
+ * LLSD arguments and results.
+ *
+ * To have nodes that implement some other wire protocol (XML-RPC
+ * for example), use the helper templates below.
+ */
+
+ static void createPipe(LLPumpIO::chain_t& chain,
const LLHTTPNode& root, const LLSD& ctx);
- /**< Create a pipe on the chain that handles HTTP requests.
- * The requests are served by the node tree given at root.
- *
- * This is primarily useful for unit testing.
- */
-
- static void setTimingCallback(timing_callback_t callback, void* data);
- /**< Register a callback function that will be called every time
- * a GET, PUT, POST, or DELETE is handled.
- *
- * This is used to time the LLHTTPNode handler code, which often hits
- * the database or does other, slow operations. JC
- */
+ /**< Create a pipe on the chain that handles HTTP requests.
+ * The requests are served by the node tree given at root.
+ *
+ * This is primarily useful for unit testing.
+ */
+
+ static void setTimingCallback(timing_callback_t callback, void* data);
+ /**< Register a callback function that will be called every time
+ * a GET, PUT, POST, or DELETE is handled.
+ *
+ * This is used to time the LLHTTPNode handler code, which often hits
+ * the database or does other, slow operations. JC
+ */
};
/* @name Helper Templates
@@ -80,14 +80,14 @@ public:
*
* The templates are:
*
- * LLChainIOFactoryForPipe
- * - a simple factory that builds instances of a pipe
+ * LLChainIOFactoryForPipe
+ * - a simple factory that builds instances of a pipe
*
- * LLHTTPNodeForFacotry
- * - a HTTP node that uses a factory as the protocol handler
+ * LLHTTPNodeForFacotry
+ * - a HTTP node that uses a factory as the protocol handler
*
- * LLHTTPNodeForPipe
- * - a HTTP node that uses a simple factory based on a pipe
+ * LLHTTPNodeForPipe
+ * - a HTTP node that uses a simple factory based on a pipe
*/
//@{
@@ -95,22 +95,22 @@ template<class Pipe>
class LLChainIOFactoryForPipe : public LLChainIOFactory
{
public:
- virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
- {
- chain.push_back(LLIOPipe::ptr_t(new Pipe));
- return true;
- }
+ virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
+ {
+ chain.push_back(LLIOPipe::ptr_t(new Pipe));
+ return true;
+ }
};
template<class Factory>
class LLHTTPNodeForFactory : public LLHTTPNode
{
public:
- const LLChainIOFactory* getProtocolHandler() const
- { return &mProtocolHandler; }
+ const LLChainIOFactory* getProtocolHandler() const
+ { return &mProtocolHandler; }
private:
- Factory mProtocolHandler;
+ Factory mProtocolHandler;
};
//@}
@@ -118,7 +118,7 @@ private:
template<class Pipe>
class LLHTTPNodeForPipe : public LLHTTPNodeForFactory<
- LLChainIOFactoryForPipe<Pipe> >
+ LLChainIOFactoryForPipe<Pipe> >
{
};
diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp
index 4676a9a8f0..75811bf3ce 100644
--- a/indra/llmessage/lliopipe.cpp
+++ b/indra/llmessage/lliopipe.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliopipe.cpp
* @author Phoenix
* @date 2004-11-19
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,32 +33,32 @@
static const std::string STATUS_SUCCESS_NAMES[LLIOPipe::STATUS_SUCCESS_COUNT] =
{
- std::string("STATUS_OK"),
- std::string("STATUS_STOP"),
- std::string("STATUS_DONE"),
- std::string("STATUS_BREAK"),
- std::string("STATUS_NEED_PROCESS"),
+ std::string("STATUS_OK"),
+ std::string("STATUS_STOP"),
+ std::string("STATUS_DONE"),
+ std::string("STATUS_BREAK"),
+ std::string("STATUS_NEED_PROCESS"),
};
static const std::string STATUS_ERROR_NAMES[LLIOPipe::STATUS_ERROR_COUNT] =
{
- std::string("STATUS_ERROR"),
- std::string("STATUS_NOT_IMPLEMENTED"),
- std::string("STATUS_PRECONDITION_NOT_MET"),
- std::string("STATUS_NO_CONNECTION"),
- std::string("STATUS_LOST_CONNECTION"),
- std::string("STATUS_EXPIRED"),
+ std::string("STATUS_ERROR"),
+ std::string("STATUS_NOT_IMPLEMENTED"),
+ std::string("STATUS_PRECONDITION_NOT_MET"),
+ std::string("STATUS_NO_CONNECTION"),
+ std::string("STATUS_LOST_CONNECTION"),
+ std::string("STATUS_EXPIRED"),
};
#ifdef LL_DEBUG_PUMPS
// Debugging schmutz for deadlock
-const char *gPumpFile = "";
-S32 gPumpLine = 0;
+const char *gPumpFile = "";
+S32 gPumpLine = 0;
void pump_debug(const char *file, S32 line)
{
- gPumpFile = file;
- gPumpLine = line;
+ gPumpFile = file;
+ gPumpLine = line;
}
#endif /* LL_DEBUG_PUMPS */
@@ -66,55 +66,55 @@ void pump_debug(const char *file, S32 line)
* LLIOPipe
*/
LLIOPipe::LLIOPipe() :
- mReferenceCount(0)
+ mReferenceCount(0)
{
}
LLIOPipe::~LLIOPipe()
{
- //LL_DEBUGS() << "destroying LLIOPipe" << LL_ENDL;
+ //LL_DEBUGS() << "destroying LLIOPipe" << LL_ENDL;
}
-//virtual
-bool LLIOPipe::isValid()
+//virtual
+bool LLIOPipe::isValid()
{
- return true ;
+ return true ;
}
// static
std::string LLIOPipe::lookupStatusString(EStatus status)
{
- if((status >= 0) && (status < STATUS_SUCCESS_COUNT))
- {
- return STATUS_SUCCESS_NAMES[status];
- }
- else
- {
- S32 error_code = ((S32)status * -1) - 1;
- if(error_code < STATUS_ERROR_COUNT)
- {
- return STATUS_ERROR_NAMES[error_code];
- }
- }
- std::string rv;
- return rv;
+ if((status >= 0) && (status < STATUS_SUCCESS_COUNT))
+ {
+ return STATUS_SUCCESS_NAMES[status];
+ }
+ else
+ {
+ S32 error_code = ((S32)status * -1) - 1;
+ if(error_code < STATUS_ERROR_COUNT)
+ {
+ return STATUS_ERROR_NAMES[error_code];
+ }
+ }
+ std::string rv;
+ return rv;
}
LLIOPipe::EStatus LLIOPipe::process(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
- return process_impl(channels, buffer, eos, context, pump);
+ return process_impl(channels, buffer, eos, context, pump);
}
// virtual
LLIOPipe::EStatus LLIOPipe::handleError(
- LLIOPipe::EStatus status,
- LLPumpIO* pump)
+ LLIOPipe::EStatus status,
+ LLPumpIO* pump)
{
- // by default, the error is not handled.
- return status;
+ // by default, the error is not handled.
+ return status;
}
diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h
index e6ac8ebfc2..a58ee045c2 100644
--- a/indra/llmessage/lliopipe.h
+++ b/indra/llmessage/lliopipe.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliopipe.h
* @author Phoenix
* @date 2004-11-18
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -59,7 +59,7 @@ void pump_debug(const char *file, S32 line);
void intrusive_ptr_add_ref(LLIOPipe* p);
void intrusive_ptr_release(LLIOPipe* p);
-/**
+/**
* @class LLIOPipe
* @brief This class is an abstract base class for data processing units
* @see LLPumpIO
@@ -78,191 +78,191 @@ void intrusive_ptr_release(LLIOPipe* p);
class LLIOPipe
{
public:
- /**
- * @brief I have decided that IO objects should have a reference
- * count. In general, you can pass bald LLIOPipe pointers around
- * as you need, but if you need to maintain a reference to one,
- * you need to hold a ptr_t.
- */
- typedef boost::intrusive_ptr<LLIOPipe> ptr_t;
-
- /**
- * @brief Scattered memory container.
- */
- typedef std::shared_ptr<LLBufferArray> buffer_ptr_t;
-
- /**
- * @brief Enumeration for IO return codes
- *
- * A status code a positive integer value is considered a success,
- * but may indicate special handling for future calls, for
- * example, issuing a STATUS_STOP to an LLIOSocketReader instance
- * will tell the instance to stop reading the socket. A status
- * code with a negative value means that a problem has been
- * encountered which will require further action on the caller or
- * a developer to correct. Some mechanisms, such as the LLPumpIO
- * may depend on this definition of success and failure.
- */
- enum EStatus
- {
- // Processing occurred normally, future calls will be accepted.
- STATUS_OK = 0,
-
- // Processing occured normally, but stop unsolicited calls to
- // process.
- STATUS_STOP = 1,
-
- // This pipe is done with the processing. Future calls to
- // process will be accepted as long as new data is available.
- STATUS_DONE = 2,
-
- // This pipe is requesting that it become the head in a process.
- STATUS_BREAK = 3,
-
- // This pipe is requesting that it become the head in a process.
- STATUS_NEED_PROCESS = 4,
-
- // Keep track of the highest number of success codes here.
- STATUS_SUCCESS_COUNT = 5,
-
- // A generic error code.
- STATUS_ERROR = -1,
-
- // This method has not yet been implemented. This usually
- // indicates the programmer working on the pipe is not yet
- // done.
- STATUS_NOT_IMPLEMENTED = -2,
-
- // This indicates that a pipe precondition was not met. For
- // example, many pipes require an element to appear after them
- // in a chain (ie, mNext is not null) and will return this in
- // response to method calls. To recover from this, it will
- // require the caller to adjust the pipe state or may require
- // a dev to adjust the code to satisfy the preconditions.
- STATUS_PRECONDITION_NOT_MET = -3,
-
- // This means we could not connect to a remote host.
- STATUS_NO_CONNECTION = -4,
-
- // The connection was lost.
- STATUS_LOST_CONNECTION = -5,
-
- // The totoal process time has exceeded the timeout.
- STATUS_EXPIRED = -6,
-
- // Keep track of the count of codes here.
- STATUS_ERROR_COUNT = 6,
- };
-
- /**
- * @brief Helper function to check status.
- *
- * When writing code to check status codes, if you do not
- * specifically check a particular value, use this method for
- * checking an error condition.
- * @param status The status to check.
- * @return Returns true if the code indicates an error occurred.
- */
- inline static bool isError(EStatus status)
- {
- return ((S32)status < 0);
- }
-
- /**
- * @brief Helper function to check status.
- *
- * When writing code to check status codes, if you do not
- * specifically check a particular value, use this method for
- * checking an error condition.
- * @param status The status to check.
- * @return Returns true if the code indicates no error was generated.
- */
- inline static bool isSuccess(EStatus status)
- {
- return ((S32)status >= 0);
- }
-
- /**
- * @brief Helper function to turn status into a string.
- *
- * @param status The status to check.
- * @return Returns the name of the status code or empty string on failure.
- */
- static std::string lookupStatusString(EStatus status);
-
- /**
- * @brief Process the data in buffer.
- *
- * @param data The data processed
- * @param eos True if this function call is the last because end of stream.
- * @param pump The pump which is calling process. May be NULL.
- * @param context Shared meta-data for the process.
- * @return Returns a status code from the operation.
- */
- EStatus process(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
-
- /**
- * @brief Give this pipe a chance to handle a generated error
- *
- * If this pipe is in a chain being processed by a pump, and one
- * of the pipes generates an error, the pump will rewind through
- * the chain to see if any of the links can handle the error. For
- * example, if a connection is refused in a socket connection, the
- * socket client can try to find a new destination host. Return an
- * error code if this pipe does not handle the error passed in.
- * @param status The status code for the error
- * @param pump The pump which was calling process before the error
- * was generated.
- * @return Returns a status code from the operation. Returns an
- * error code if the error passed in was not handled. Returns
- * STATUS_OK to indicate the error has been handled.
- */
- virtual EStatus handleError(EStatus status, LLPumpIO* pump);
-
- /**
- * @brief Base Destructor - do not call <code>delete</code> directly.
- */
- virtual ~LLIOPipe();
-
- virtual bool isValid() ;
+ /**
+ * @brief I have decided that IO objects should have a reference
+ * count. In general, you can pass bald LLIOPipe pointers around
+ * as you need, but if you need to maintain a reference to one,
+ * you need to hold a ptr_t.
+ */
+ typedef boost::intrusive_ptr<LLIOPipe> ptr_t;
+
+ /**
+ * @brief Scattered memory container.
+ */
+ typedef std::shared_ptr<LLBufferArray> buffer_ptr_t;
+
+ /**
+ * @brief Enumeration for IO return codes
+ *
+ * A status code a positive integer value is considered a success,
+ * but may indicate special handling for future calls, for
+ * example, issuing a STATUS_STOP to an LLIOSocketReader instance
+ * will tell the instance to stop reading the socket. A status
+ * code with a negative value means that a problem has been
+ * encountered which will require further action on the caller or
+ * a developer to correct. Some mechanisms, such as the LLPumpIO
+ * may depend on this definition of success and failure.
+ */
+ enum EStatus
+ {
+ // Processing occurred normally, future calls will be accepted.
+ STATUS_OK = 0,
+
+ // Processing occured normally, but stop unsolicited calls to
+ // process.
+ STATUS_STOP = 1,
+
+ // This pipe is done with the processing. Future calls to
+ // process will be accepted as long as new data is available.
+ STATUS_DONE = 2,
+
+ // This pipe is requesting that it become the head in a process.
+ STATUS_BREAK = 3,
+
+ // This pipe is requesting that it become the head in a process.
+ STATUS_NEED_PROCESS = 4,
+
+ // Keep track of the highest number of success codes here.
+ STATUS_SUCCESS_COUNT = 5,
+
+ // A generic error code.
+ STATUS_ERROR = -1,
+
+ // This method has not yet been implemented. This usually
+ // indicates the programmer working on the pipe is not yet
+ // done.
+ STATUS_NOT_IMPLEMENTED = -2,
+
+ // This indicates that a pipe precondition was not met. For
+ // example, many pipes require an element to appear after them
+ // in a chain (ie, mNext is not null) and will return this in
+ // response to method calls. To recover from this, it will
+ // require the caller to adjust the pipe state or may require
+ // a dev to adjust the code to satisfy the preconditions.
+ STATUS_PRECONDITION_NOT_MET = -3,
+
+ // This means we could not connect to a remote host.
+ STATUS_NO_CONNECTION = -4,
+
+ // The connection was lost.
+ STATUS_LOST_CONNECTION = -5,
+
+ // The totoal process time has exceeded the timeout.
+ STATUS_EXPIRED = -6,
+
+ // Keep track of the count of codes here.
+ STATUS_ERROR_COUNT = 6,
+ };
+
+ /**
+ * @brief Helper function to check status.
+ *
+ * When writing code to check status codes, if you do not
+ * specifically check a particular value, use this method for
+ * checking an error condition.
+ * @param status The status to check.
+ * @return Returns true if the code indicates an error occurred.
+ */
+ inline static bool isError(EStatus status)
+ {
+ return ((S32)status < 0);
+ }
+
+ /**
+ * @brief Helper function to check status.
+ *
+ * When writing code to check status codes, if you do not
+ * specifically check a particular value, use this method for
+ * checking an error condition.
+ * @param status The status to check.
+ * @return Returns true if the code indicates no error was generated.
+ */
+ inline static bool isSuccess(EStatus status)
+ {
+ return ((S32)status >= 0);
+ }
+
+ /**
+ * @brief Helper function to turn status into a string.
+ *
+ * @param status The status to check.
+ * @return Returns the name of the status code or empty string on failure.
+ */
+ static std::string lookupStatusString(EStatus status);
+
+ /**
+ * @brief Process the data in buffer.
+ *
+ * @param data The data processed
+ * @param eos True if this function call is the last because end of stream.
+ * @param pump The pump which is calling process. May be NULL.
+ * @param context Shared meta-data for the process.
+ * @return Returns a status code from the operation.
+ */
+ EStatus process(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+
+ /**
+ * @brief Give this pipe a chance to handle a generated error
+ *
+ * If this pipe is in a chain being processed by a pump, and one
+ * of the pipes generates an error, the pump will rewind through
+ * the chain to see if any of the links can handle the error. For
+ * example, if a connection is refused in a socket connection, the
+ * socket client can try to find a new destination host. Return an
+ * error code if this pipe does not handle the error passed in.
+ * @param status The status code for the error
+ * @param pump The pump which was calling process before the error
+ * was generated.
+ * @return Returns a status code from the operation. Returns an
+ * error code if the error passed in was not handled. Returns
+ * STATUS_OK to indicate the error has been handled.
+ */
+ virtual EStatus handleError(EStatus status, LLPumpIO* pump);
+
+ /**
+ * @brief Base Destructor - do not call <code>delete</code> directly.
+ */
+ virtual ~LLIOPipe();
+
+ virtual bool isValid() ;
protected:
- /**
- * @brief Base Constructor.
- */
- LLIOPipe();
-
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump) = 0;
+ /**
+ * @brief Base Constructor.
+ */
+ LLIOPipe();
+
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump) = 0;
private:
- friend void intrusive_ptr_add_ref(LLIOPipe* p);
- friend void intrusive_ptr_release(LLIOPipe* p);
- U32 mReferenceCount;
+ friend void intrusive_ptr_add_ref(LLIOPipe* p);
+ friend void intrusive_ptr_release(LLIOPipe* p);
+ U32 mReferenceCount;
};
inline void intrusive_ptr_add_ref(LLIOPipe* p)
{
- ++p->mReferenceCount;
+ ++p->mReferenceCount;
}
inline void intrusive_ptr_release(LLIOPipe* p)
{
- if(p && 0 == --p->mReferenceCount)
- {
- delete p;
- }
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
}
#endif // LL_LLIOPIPE_H
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index 321d7286eb..a14d10fe5f 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliosocket.cpp
* @author Phoenix
* @date 2005-07-31
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -50,15 +50,15 @@ static const S32 LL_RECV_BUFFER_SIZE = 40000;
//static const U16 LL_PORT_DISCOVERY_RANGE_MAX = 13050;
//
-// local methods
+// local methods
//
bool is_addr_in_use(apr_status_t status)
{
#if LL_WINDOWS
- return (WSAEADDRINUSE == APR_TO_OS_ERROR(status));
+ return (WSAEADDRINUSE == APR_TO_OS_ERROR(status));
#else
- return (EADDRINUSE == APR_TO_OS_ERROR(status));
+ return (EADDRINUSE == APR_TO_OS_ERROR(status));
#endif
}
@@ -71,28 +71,28 @@ bool is_addr_in_use(apr_status_t status)
#endif
-// Quick function
+// Quick function
void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
{
#if LL_DEBUG_SOCKET_FILE_DESCRIPTORS
- if(!apr_sock)
- {
- LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << ": no socket." << LL_ENDL;
- return;
- }
- // *TODO: Why doesn't this work?
- //apr_os_sock_t os_sock;
- int os_sock;
- if(APR_SUCCESS == apr_os_sock_get(&os_sock, apr_sock))
- {
- LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << " on fd " << os_sock
- << " at " << apr_sock << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << " no fd "
- << " at " << apr_sock << LL_ENDL;
- }
+ if(!apr_sock)
+ {
+ LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << ": no socket." << LL_ENDL;
+ return;
+ }
+ // *TODO: Why doesn't this work?
+ //apr_os_sock_t os_sock;
+ int os_sock;
+ if(APR_SUCCESS == apr_os_sock_get(&os_sock, apr_sock))
+ {
+ LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << " on fd " << os_sock
+ << " at " << apr_sock << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Socket") << "Socket -- " << (msg?msg:"") << " no fd "
+ << " at " << apr_sock << LL_ENDL;
+ }
#endif
}
@@ -103,162 +103,162 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
// static
LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port, const char *hostname)
{
- LLSocket::ptr_t rv;
- apr_socket_t* socket = NULL;
- apr_pool_t* new_pool = NULL;
- apr_status_t status = APR_EGENERAL;
-
- // create a pool for the socket
- status = apr_pool_create(&new_pool, pool);
- if(ll_apr_warn_status(status))
- {
- if(new_pool) apr_pool_destroy(new_pool);
- return rv;
- }
-
- if(STREAM_TCP == type)
- {
- status = apr_socket_create(
- &socket,
- APR_INET,
- SOCK_STREAM,
- APR_PROTO_TCP,
- new_pool);
- }
- else if(DATAGRAM_UDP == type)
- {
- status = apr_socket_create(
- &socket,
- APR_INET,
- SOCK_DGRAM,
- APR_PROTO_UDP,
- new_pool);
- }
- else
- {
- if(new_pool) apr_pool_destroy(new_pool);
- return rv;
- }
- if(ll_apr_warn_status(status))
- {
- if(new_pool) apr_pool_destroy(new_pool);
- return rv;
- }
- // At this point, the new LLSocket instance takes ownership of new_pool,
- // which is why no early return below this call explicitly destroys it: it
- // is instead cleaned up by ~LLSocket().
- rv = ptr_t(new LLSocket(socket, new_pool));
- if(port > 0)
- {
- apr_sockaddr_t* sa = NULL;
- status = apr_sockaddr_info_get(
- &sa,
- hostname,
- APR_UNSPEC,
- port,
- 0,
- new_pool);
- if(ll_apr_warn_status(status))
- {
- rv.reset();
- return rv;
- }
- // This allows us to reuse the address on quick down/up. This
- // is unlikely to create problems.
- ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
- status = apr_socket_bind(socket, sa);
- if(ll_apr_warn_status(status))
- {
- rv.reset();
- return rv;
- }
- LL_DEBUGS() << "Bound " << ((DATAGRAM_UDP == type) ? "udp" : "tcp")
- << " socket to port: " << sa->port << LL_ENDL;
- if(STREAM_TCP == type)
- {
- // If it's a stream based socket, we need to tell the OS
- // to keep a queue of incoming connections for ACCEPT.
- LL_DEBUGS() << "Setting listen state for socket." << LL_ENDL;
- status = apr_socket_listen(
- socket,
- LL_DEFAULT_LISTEN_BACKLOG);
- if(ll_apr_warn_status(status))
- {
- rv.reset();
- return rv;
- }
- }
- }
- else // port <= 0
- {
- // we need to indicate that we have an ephemeral port if the
- // previous calls were successful. It will
- port = PORT_EPHEMERAL;
- }
- rv->mPort = port;
- rv->setNonBlocking();
- return rv;
+ LLSocket::ptr_t rv;
+ apr_socket_t* socket = NULL;
+ apr_pool_t* new_pool = NULL;
+ apr_status_t status = APR_EGENERAL;
+
+ // create a pool for the socket
+ status = apr_pool_create(&new_pool, pool);
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool) apr_pool_destroy(new_pool);
+ return rv;
+ }
+
+ if(STREAM_TCP == type)
+ {
+ status = apr_socket_create(
+ &socket,
+ APR_INET,
+ SOCK_STREAM,
+ APR_PROTO_TCP,
+ new_pool);
+ }
+ else if(DATAGRAM_UDP == type)
+ {
+ status = apr_socket_create(
+ &socket,
+ APR_INET,
+ SOCK_DGRAM,
+ APR_PROTO_UDP,
+ new_pool);
+ }
+ else
+ {
+ if(new_pool) apr_pool_destroy(new_pool);
+ return rv;
+ }
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool) apr_pool_destroy(new_pool);
+ return rv;
+ }
+ // At this point, the new LLSocket instance takes ownership of new_pool,
+ // which is why no early return below this call explicitly destroys it: it
+ // is instead cleaned up by ~LLSocket().
+ rv = ptr_t(new LLSocket(socket, new_pool));
+ if(port > 0)
+ {
+ apr_sockaddr_t* sa = NULL;
+ status = apr_sockaddr_info_get(
+ &sa,
+ hostname,
+ APR_UNSPEC,
+ port,
+ 0,
+ new_pool);
+ if(ll_apr_warn_status(status))
+ {
+ rv.reset();
+ return rv;
+ }
+ // This allows us to reuse the address on quick down/up. This
+ // is unlikely to create problems.
+ ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
+ status = apr_socket_bind(socket, sa);
+ if(ll_apr_warn_status(status))
+ {
+ rv.reset();
+ return rv;
+ }
+ LL_DEBUGS() << "Bound " << ((DATAGRAM_UDP == type) ? "udp" : "tcp")
+ << " socket to port: " << sa->port << LL_ENDL;
+ if(STREAM_TCP == type)
+ {
+ // If it's a stream based socket, we need to tell the OS
+ // to keep a queue of incoming connections for ACCEPT.
+ LL_DEBUGS() << "Setting listen state for socket." << LL_ENDL;
+ status = apr_socket_listen(
+ socket,
+ LL_DEFAULT_LISTEN_BACKLOG);
+ if(ll_apr_warn_status(status))
+ {
+ rv.reset();
+ return rv;
+ }
+ }
+ }
+ else // port <= 0
+ {
+ // we need to indicate that we have an ephemeral port if the
+ // previous calls were successful. It will
+ port = PORT_EPHEMERAL;
+ }
+ rv->mPort = port;
+ rv->setNonBlocking();
+ return rv;
}
// static
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
{
- LLSocket::ptr_t rv;
- if(!socket)
- {
- return rv;
- }
- rv = ptr_t(new LLSocket(socket, pool));
- rv->mPort = PORT_EPHEMERAL;
- rv->setNonBlocking();
- return rv;
+ LLSocket::ptr_t rv;
+ if(!socket)
+ {
+ return rv;
+ }
+ rv = ptr_t(new LLSocket(socket, pool));
+ rv->mPort = PORT_EPHEMERAL;
+ rv->setNonBlocking();
+ return rv;
}
bool LLSocket::blockingConnect(const LLHost& host)
{
- if(!mSocket) return false;
- apr_sockaddr_t* sa = NULL;
- std::string ip_address;
- ip_address = host.getIPString();
- if(ll_apr_warn_status(apr_sockaddr_info_get(
- &sa,
- ip_address.c_str(),
- APR_UNSPEC,
- host.getPort(),
- 0,
- mPool)))
- {
- return false;
- }
- setBlocking(1000);
- ll_debug_socket("Blocking connect", mSocket);
- if(ll_apr_warn_status(apr_socket_connect(mSocket, sa))) return false;
- setNonBlocking();
- return true;
+ if(!mSocket) return false;
+ apr_sockaddr_t* sa = NULL;
+ std::string ip_address;
+ ip_address = host.getIPString();
+ if(ll_apr_warn_status(apr_sockaddr_info_get(
+ &sa,
+ ip_address.c_str(),
+ APR_UNSPEC,
+ host.getPort(),
+ 0,
+ mPool)))
+ {
+ return false;
+ }
+ setBlocking(1000);
+ ll_debug_socket("Blocking connect", mSocket);
+ if(ll_apr_warn_status(apr_socket_connect(mSocket, sa))) return false;
+ setNonBlocking();
+ return true;
}
LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) :
- mSocket(socket),
- mPool(pool),
- mPort(PORT_INVALID)
+ mSocket(socket),
+ mPool(pool),
+ mPort(PORT_INVALID)
{
- ll_debug_socket("Constructing wholely formed socket", mSocket);
+ ll_debug_socket("Constructing wholely formed socket", mSocket);
}
LLSocket::~LLSocket()
{
- // *FIX: clean up memory we are holding.
- if(mSocket)
- {
- ll_debug_socket("Destroying socket", mSocket);
- apr_socket_close(mSocket);
- mSocket = NULL;
- }
- if(mPool)
- {
- apr_pool_destroy(mPool);
- }
+ // *FIX: clean up memory we are holding.
+ if(mSocket)
+ {
+ ll_debug_socket("Destroying socket", mSocket);
+ apr_socket_close(mSocket);
+ mSocket = NULL;
+ }
+ if(mPool)
+ {
+ apr_pool_destroy(mPool);
+ }
}
// See http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-13.html#ss13.4
@@ -267,21 +267,21 @@ LLSocket::~LLSocket()
void LLSocket::setBlocking(S32 timeout)
{
- // set up the socket options
- ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout)); // Sets both receive and send timeout SO_RCVTIMEO, SO_SNDTIMEO
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
+ // set up the socket options
+ ll_apr_warn_status(apr_socket_timeout_set(mSocket, timeout)); // Sets both receive and send timeout SO_RCVTIMEO, SO_SNDTIMEO
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
}
void LLSocket::setNonBlocking()
{
- // set up the socket options
- ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 1));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
+ // set up the socket options
+ ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_NONBLOCK, 1));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
}
@@ -290,96 +290,96 @@ void LLSocket::setNonBlocking()
///
LLIOSocketReader::LLIOSocketReader(LLSocket::ptr_t socket) :
- mSource(socket),
- mInitialized(false)
+ mSource(socket),
+ mInitialized(false)
{
}
LLIOSocketReader::~LLIOSocketReader()
{
- //LL_DEBUGS() << "Destroying LLIOSocketReader" << LL_ENDL;
+ //LL_DEBUGS() << "Destroying LLIOSocketReader" << LL_ENDL;
}
// virtual
LLIOPipe::EStatus LLIOSocketReader::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!mSource) return STATUS_PRECONDITION_NOT_MET;
- if(!mInitialized)
- {
- PUMP_DEBUG;
- // Since the read will not block, it's ok to initialize and
- // attempt to read off the descriptor immediately.
- mInitialized = true;
- if(pump)
- {
- PUMP_DEBUG;
- LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketReader."
- << LL_ENDL;
- apr_pollfd_t poll_fd;
- poll_fd.p = NULL;
- poll_fd.desc_type = APR_POLL_SOCKET;
- poll_fd.reqevents = APR_POLLIN;
- poll_fd.rtnevents = 0x0;
- poll_fd.desc.s = mSource->getSocket();
- poll_fd.client_data = NULL;
- pump->setConditional(this, &poll_fd);
- }
- }
- //if(!buffer)
- //{
- // buffer = new LLBufferArray;
- //}
- PUMP_DEBUG;
- const apr_size_t READ_BUFFER_SIZE = 1024;
- char read_buf[READ_BUFFER_SIZE]; /*Flawfinder: ignore*/
- apr_size_t len;
- apr_status_t status = APR_SUCCESS;
- do
- {
- PUMP_DEBUG;
- len = READ_BUFFER_SIZE;
- status = apr_socket_recv(mSource->getSocket(), read_buf, &len);
- buffer->append(channels.out(), (U8*)read_buf, len);
- } while((APR_SUCCESS == status) && (READ_BUFFER_SIZE == len));
- LL_DEBUGS() << "socket read status: " << status << LL_ENDL;
- LLIOPipe::EStatus rv = STATUS_OK;
-
- PUMP_DEBUG;
- // *FIX: Also need to check for broken pipe
- if(APR_STATUS_IS_EOF(status))
- {
- // *FIX: Should we shut down the socket read?
- if(pump)
- {
- pump->setConditional(this, NULL);
- }
- rv = STATUS_DONE;
- eos = true;
- }
- else if(APR_STATUS_IS_EAGAIN(status))
- {
+ PUMP_DEBUG;
+ if(!mSource) return STATUS_PRECONDITION_NOT_MET;
+ if(!mInitialized)
+ {
+ PUMP_DEBUG;
+ // Since the read will not block, it's ok to initialize and
+ // attempt to read off the descriptor immediately.
+ mInitialized = true;
+ if(pump)
+ {
+ PUMP_DEBUG;
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketReader."
+ << LL_ENDL;
+ apr_pollfd_t poll_fd;
+ poll_fd.p = NULL;
+ poll_fd.desc_type = APR_POLL_SOCKET;
+ poll_fd.reqevents = APR_POLLIN;
+ poll_fd.rtnevents = 0x0;
+ poll_fd.desc.s = mSource->getSocket();
+ poll_fd.client_data = NULL;
+ pump->setConditional(this, &poll_fd);
+ }
+ }
+ //if(!buffer)
+ //{
+ // buffer = new LLBufferArray;
+ //}
+ PUMP_DEBUG;
+ const apr_size_t READ_BUFFER_SIZE = 1024;
+ char read_buf[READ_BUFFER_SIZE]; /*Flawfinder: ignore*/
+ apr_size_t len;
+ apr_status_t status = APR_SUCCESS;
+ do
+ {
+ PUMP_DEBUG;
+ len = READ_BUFFER_SIZE;
+ status = apr_socket_recv(mSource->getSocket(), read_buf, &len);
+ buffer->append(channels.out(), (U8*)read_buf, len);
+ } while((APR_SUCCESS == status) && (READ_BUFFER_SIZE == len));
+ LL_DEBUGS() << "socket read status: " << status << LL_ENDL;
+ LLIOPipe::EStatus rv = STATUS_OK;
+
+ PUMP_DEBUG;
+ // *FIX: Also need to check for broken pipe
+ if(APR_STATUS_IS_EOF(status))
+ {
+ // *FIX: Should we shut down the socket read?
+ if(pump)
+ {
+ pump->setConditional(this, NULL);
+ }
+ rv = STATUS_DONE;
+ eos = true;
+ }
+ else if(APR_STATUS_IS_EAGAIN(status))
+ {
/*Commented out by Aura 9-9-8 for DEV-19961.
- // everything is fine, but we can terminate this process pump.
-
- rv = STATUS_BREAK;
+ // everything is fine, but we can terminate this process pump.
+
+ rv = STATUS_BREAK;
*/
- }
- else
- {
- if(ll_apr_warn_status(status))
- {
- rv = STATUS_ERROR;
- }
- }
- PUMP_DEBUG;
- return rv;
+ }
+ else
+ {
+ if(ll_apr_warn_status(status))
+ {
+ rv = STATUS_ERROR;
+ }
+ }
+ PUMP_DEBUG;
+ return rv;
}
///
@@ -387,143 +387,143 @@ LLIOPipe::EStatus LLIOSocketReader::process_impl(
///
LLIOSocketWriter::LLIOSocketWriter(LLSocket::ptr_t socket) :
- mDestination(socket),
- mLastWritten(NULL),
- mInitialized(false)
+ mDestination(socket),
+ mLastWritten(NULL),
+ mInitialized(false)
{
}
LLIOSocketWriter::~LLIOSocketWriter()
{
- //LL_DEBUGS() << "Destroying LLIOSocketWriter" << LL_ENDL;
+ //LL_DEBUGS() << "Destroying LLIOSocketWriter" << LL_ENDL;
}
// virtual
LLIOPipe::EStatus LLIOSocketWriter::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
- if(!mInitialized)
- {
- PUMP_DEBUG;
- // Since the write will not block, it's ok to initialize and
- // attempt to write immediately.
- mInitialized = true;
- if(pump)
- {
- PUMP_DEBUG;
- LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketWriter."
- << LL_ENDL;
- apr_pollfd_t poll_fd;
- poll_fd.p = NULL;
- poll_fd.desc_type = APR_POLL_SOCKET;
- poll_fd.reqevents = APR_POLLOUT;
- poll_fd.rtnevents = 0x0;
- poll_fd.desc.s = mDestination->getSocket();
- poll_fd.client_data = NULL;
- pump->setConditional(this, &poll_fd);
- }
- }
-
- PUMP_DEBUG;
- // *FIX: Some sort of writev implementation would be much more
- // efficient - not only because writev() is better, but also
- // because we won't have to do as much work to find the start
- // address.
- buffer->lock();
- LLBufferArray::segment_iterator_t it;
- LLBufferArray::segment_iterator_t end = buffer->endSegment();
- LLSegment segment;
- it = buffer->constructSegmentAfter(mLastWritten, segment);
- /*
- if(NULL == mLastWritten)
- {
- it = buffer->beginSegment();
- segment = (*it);
- }
- else
- {
- it = buffer->getSegment(mLastWritten);
- segment = (*it);
- S32 size = segment.size();
- U8* data = segment.data();
- if((data + size) == mLastWritten)
- {
- ++it;
- segment = (*it);
- }
- else
- {
- // *FIX: check the math on this one
- segment = LLSegment(
- (*it).getChannelMask(),
- mLastWritten + 1,
- size - (mLastWritten - data));
- }
- }
- */
-
- PUMP_DEBUG;
- apr_size_t len;
- bool done = false;
- apr_status_t status = APR_SUCCESS;
- while(it != end)
- {
-
- PUMP_DEBUG;
- if((*it).isOnChannel(channels.in()))
- {
- PUMP_DEBUG;
- len = (apr_size_t)segment.size();
- status = apr_socket_send(
- mDestination->getSocket(),
- (const char*)segment.data(),
- &len);
- // We sometimes get a 'non-blocking socket operation could not be
- // completed immediately' error from apr_socket_send. In this
- // case we break and the data will be sent the next time the chain
- // is pumped.
- if(APR_STATUS_IS_EAGAIN(status))
- {
- ll_apr_warn_status(status);
- break;
- }
-
- mLastWritten = segment.data() + len - 1;
-
- PUMP_DEBUG;
- if((S32)len < segment.size())
- {
- break;
- }
-
- }
-
- ++it;
- if(it != end)
- {
- segment = (*it);
- }
- else
- {
- done = true;
- }
-
- }
- buffer->unlock();
-
- PUMP_DEBUG;
- if(done && eos)
- {
- return STATUS_DONE;
- }
- return STATUS_OK;
+ PUMP_DEBUG;
+ if(!mDestination) return STATUS_PRECONDITION_NOT_MET;
+ if(!mInitialized)
+ {
+ PUMP_DEBUG;
+ // Since the write will not block, it's ok to initialize and
+ // attempt to write immediately.
+ mInitialized = true;
+ if(pump)
+ {
+ PUMP_DEBUG;
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOSocketWriter."
+ << LL_ENDL;
+ apr_pollfd_t poll_fd;
+ poll_fd.p = NULL;
+ poll_fd.desc_type = APR_POLL_SOCKET;
+ poll_fd.reqevents = APR_POLLOUT;
+ poll_fd.rtnevents = 0x0;
+ poll_fd.desc.s = mDestination->getSocket();
+ poll_fd.client_data = NULL;
+ pump->setConditional(this, &poll_fd);
+ }
+ }
+
+ PUMP_DEBUG;
+ // *FIX: Some sort of writev implementation would be much more
+ // efficient - not only because writev() is better, but also
+ // because we won't have to do as much work to find the start
+ // address.
+ buffer->lock();
+ LLBufferArray::segment_iterator_t it;
+ LLBufferArray::segment_iterator_t end = buffer->endSegment();
+ LLSegment segment;
+ it = buffer->constructSegmentAfter(mLastWritten, segment);
+ /*
+ if(NULL == mLastWritten)
+ {
+ it = buffer->beginSegment();
+ segment = (*it);
+ }
+ else
+ {
+ it = buffer->getSegment(mLastWritten);
+ segment = (*it);
+ S32 size = segment.size();
+ U8* data = segment.data();
+ if((data + size) == mLastWritten)
+ {
+ ++it;
+ segment = (*it);
+ }
+ else
+ {
+ // *FIX: check the math on this one
+ segment = LLSegment(
+ (*it).getChannelMask(),
+ mLastWritten + 1,
+ size - (mLastWritten - data));
+ }
+ }
+ */
+
+ PUMP_DEBUG;
+ apr_size_t len;
+ bool done = false;
+ apr_status_t status = APR_SUCCESS;
+ while(it != end)
+ {
+
+ PUMP_DEBUG;
+ if((*it).isOnChannel(channels.in()))
+ {
+ PUMP_DEBUG;
+ len = (apr_size_t)segment.size();
+ status = apr_socket_send(
+ mDestination->getSocket(),
+ (const char*)segment.data(),
+ &len);
+ // We sometimes get a 'non-blocking socket operation could not be
+ // completed immediately' error from apr_socket_send. In this
+ // case we break and the data will be sent the next time the chain
+ // is pumped.
+ if(APR_STATUS_IS_EAGAIN(status))
+ {
+ ll_apr_warn_status(status);
+ break;
+ }
+
+ mLastWritten = segment.data() + len - 1;
+
+ PUMP_DEBUG;
+ if((S32)len < segment.size())
+ {
+ break;
+ }
+
+ }
+
+ ++it;
+ if(it != end)
+ {
+ segment = (*it);
+ }
+ else
+ {
+ done = true;
+ }
+
+ }
+ buffer->unlock();
+
+ PUMP_DEBUG;
+ if(done && eos)
+ {
+ return STATUS_DONE;
+ }
+ return STATUS_OK;
}
@@ -532,166 +532,166 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
///
LLIOServerSocket::LLIOServerSocket(
- apr_pool_t* pool,
- LLIOServerSocket::socket_t listener,
- factory_t factory) :
- mPool(pool),
- mListenSocket(listener),
- mReactor(factory),
- mInitialized(false),
- mResponseTimeout(DEFAULT_CHAIN_EXPIRY_SECS)
+ apr_pool_t* pool,
+ LLIOServerSocket::socket_t listener,
+ factory_t factory) :
+ mPool(pool),
+ mListenSocket(listener),
+ mReactor(factory),
+ mInitialized(false),
+ mResponseTimeout(DEFAULT_CHAIN_EXPIRY_SECS)
{
}
LLIOServerSocket::~LLIOServerSocket()
{
- //LL_DEBUGS() << "Destroying LLIOServerSocket" << LL_ENDL;
+ //LL_DEBUGS() << "Destroying LLIOServerSocket" << LL_ENDL;
}
void LLIOServerSocket::setResponseTimeout(F32 timeout_secs)
{
- mResponseTimeout = timeout_secs;
+ mResponseTimeout = timeout_secs;
}
// virtual
LLIOPipe::EStatus LLIOServerSocket::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!pump)
- {
- LL_WARNS() << "Need a pump for server socket." << LL_ENDL;
- return STATUS_ERROR;
- }
- if(!mInitialized)
- {
- PUMP_DEBUG;
- // This segment sets up the pump so that we do not call
- // process again until we have an incoming read, aka connect()
- // from a remote host.
- LL_DEBUGS() << "Initializing poll descriptor for LLIOServerSocket."
- << LL_ENDL;
- apr_pollfd_t poll_fd;
- poll_fd.p = NULL;
- poll_fd.desc_type = APR_POLL_SOCKET;
- poll_fd.reqevents = APR_POLLIN;
- poll_fd.rtnevents = 0x0;
- poll_fd.desc.s = mListenSocket->getSocket();
- poll_fd.client_data = NULL;
- pump->setConditional(this, &poll_fd);
- mInitialized = true;
- return STATUS_OK;
- }
-
- // we are initialized, and told to process, so we must have a
- // socket waiting for a connection.
- LL_DEBUGS() << "accepting socket" << LL_ENDL;
-
- PUMP_DEBUG;
- apr_pool_t* new_pool = NULL;
- apr_status_t status = apr_pool_create(&new_pool, mPool);
- if(ll_apr_warn_status(status))
- {
- if(new_pool)
- {
- apr_pool_destroy(new_pool);
- }
- return STATUS_ERROR;
- }
-
- apr_socket_t* socket = NULL;
- status = apr_socket_accept(
- &socket,
- mListenSocket->getSocket(),
- new_pool);
- LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool));
- //EStatus rv = STATUS_ERROR;
- if(llsocket)
- {
- PUMP_DEBUG;
-
- apr_sockaddr_t* remote_addr;
- apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
-
- char* remote_host_string;
- apr_sockaddr_ip_get(&remote_host_string, remote_addr);
-
- LLSD context;
- context[CONTEXT_REMOTE_HOST] = remote_host_string;
- context[CONTEXT_REMOTE_PORT] = remote_addr->port;
-
- LLPumpIO::chain_t chain;
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
- if(mReactor->build(chain, context))
- {
- chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
- pump->addChain(chain, mResponseTimeout);
- status = STATUS_OK;
- }
- else
- {
- LL_WARNS() << "Unable to build reactor to socket." << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS() << "Unable to create linden socket." << LL_ENDL;
- }
-
- PUMP_DEBUG;
- // This needs to always return success, lest it get removed from
- // the pump.
- return STATUS_OK;
+ PUMP_DEBUG;
+ if(!pump)
+ {
+ LL_WARNS() << "Need a pump for server socket." << LL_ENDL;
+ return STATUS_ERROR;
+ }
+ if(!mInitialized)
+ {
+ PUMP_DEBUG;
+ // This segment sets up the pump so that we do not call
+ // process again until we have an incoming read, aka connect()
+ // from a remote host.
+ LL_DEBUGS() << "Initializing poll descriptor for LLIOServerSocket."
+ << LL_ENDL;
+ apr_pollfd_t poll_fd;
+ poll_fd.p = NULL;
+ poll_fd.desc_type = APR_POLL_SOCKET;
+ poll_fd.reqevents = APR_POLLIN;
+ poll_fd.rtnevents = 0x0;
+ poll_fd.desc.s = mListenSocket->getSocket();
+ poll_fd.client_data = NULL;
+ pump->setConditional(this, &poll_fd);
+ mInitialized = true;
+ return STATUS_OK;
+ }
+
+ // we are initialized, and told to process, so we must have a
+ // socket waiting for a connection.
+ LL_DEBUGS() << "accepting socket" << LL_ENDL;
+
+ PUMP_DEBUG;
+ apr_pool_t* new_pool = NULL;
+ apr_status_t status = apr_pool_create(&new_pool, mPool);
+ if(ll_apr_warn_status(status))
+ {
+ if(new_pool)
+ {
+ apr_pool_destroy(new_pool);
+ }
+ return STATUS_ERROR;
+ }
+
+ apr_socket_t* socket = NULL;
+ status = apr_socket_accept(
+ &socket,
+ mListenSocket->getSocket(),
+ new_pool);
+ LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool));
+ //EStatus rv = STATUS_ERROR;
+ if(llsocket)
+ {
+ PUMP_DEBUG;
+
+ apr_sockaddr_t* remote_addr;
+ apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
+
+ char* remote_host_string;
+ apr_sockaddr_ip_get(&remote_host_string, remote_addr);
+
+ LLSD context;
+ context[CONTEXT_REMOTE_HOST] = remote_host_string;
+ context[CONTEXT_REMOTE_PORT] = remote_addr->port;
+
+ LLPumpIO::chain_t chain;
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketReader(llsocket)));
+ if(mReactor->build(chain, context))
+ {
+ chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
+ pump->addChain(chain, mResponseTimeout);
+ status = STATUS_OK;
+ }
+ else
+ {
+ LL_WARNS() << "Unable to build reactor to socket." << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Unable to create linden socket." << LL_ENDL;
+ }
+
+ PUMP_DEBUG;
+ // This needs to always return success, lest it get removed from
+ // the pump.
+ return STATUS_OK;
}
#if 0
LLIODataSocket::LLIODataSocket(
- U16 suggested_port,
- U16 start_discovery_port,
- apr_pool_t* pool) :
- mSocket(NULL)
+ U16 suggested_port,
+ U16 start_discovery_port,
+ apr_pool_t* pool) :
+ mSocket(NULL)
{
- if(!pool || (PORT_INVALID == suggested_port)) return;
- if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return;
- apr_sockaddr_t* sa = NULL;
- if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return;
- apr_status_t status = apr_socket_bind(mSocket, sa);
- if((start_discovery_port > 0) && is_addr_in_use(status))
- {
- const U16 MAX_ATTEMPT_PORTS = 50;
- for(U16 attempt_port = start_discovery_port;
- attempt_port < (start_discovery_port + MAX_ATTEMPT_PORTS);
- ++attempt_port)
- {
- sa->port = attempt_port;
- sa->sa.sin.sin_port = htons(attempt_port);
- status = apr_socket_bind(mSocket, sa);
- if(APR_SUCCESS == status) break;
- if(is_addr_in_use(status)) continue;
- (void)ll_apr_warn_status(status);
- }
- }
- if(ll_apr_warn_status(status)) return;
- if(sa->port)
- {
- LL_DEBUGS() << "Bound datagram socket to port: " << sa->port << LL_ENDL;
- mPort = sa->port;
- }
- else
- {
- mPort = LLIOSocket::PORT_EPHEMERAL;
- }
-
- // set up the socket options options
- ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
- ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
+ if(!pool || (PORT_INVALID == suggested_port)) return;
+ if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return;
+ apr_sockaddr_t* sa = NULL;
+ if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return;
+ apr_status_t status = apr_socket_bind(mSocket, sa);
+ if((start_discovery_port > 0) && is_addr_in_use(status))
+ {
+ const U16 MAX_ATTEMPT_PORTS = 50;
+ for(U16 attempt_port = start_discovery_port;
+ attempt_port < (start_discovery_port + MAX_ATTEMPT_PORTS);
+ ++attempt_port)
+ {
+ sa->port = attempt_port;
+ sa->sa.sin.sin_port = htons(attempt_port);
+ status = apr_socket_bind(mSocket, sa);
+ if(APR_SUCCESS == status) break;
+ if(is_addr_in_use(status)) continue;
+ (void)ll_apr_warn_status(status);
+ }
+ }
+ if(ll_apr_warn_status(status)) return;
+ if(sa->port)
+ {
+ LL_DEBUGS() << "Bound datagram socket to port: " << sa->port << LL_ENDL;
+ mPort = sa->port;
+ }
+ else
+ {
+ mPort = LLIOSocket::PORT_EPHEMERAL;
+ }
+
+ // set up the socket options options
+ ll_apr_warn_status(apr_socket_timeout_set(mSocket, 0));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_SNDBUF, LL_SEND_BUFFER_SIZE));
+ ll_apr_warn_status(apr_socket_opt_set(mSocket, APR_SO_RCVBUF, LL_RECV_BUFFER_SIZE));
}
LLIODataSocket::~LLIODataSocket()
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index a62b3c0204..0a3f2617e6 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lliosocket.h
* @author Phoenix
* @date 2005-07-31
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,7 +29,7 @@
#ifndef LL_LLIOSOCKET_H
#define LL_LLIOSOCKET_H
-/**
+/**
* The socket interface provided here is a simple wraper around apr
* sockets, with a pipe source and sink to read and write off of the
* socket. Every socket only performs non-blocking operations except
@@ -48,7 +48,7 @@ extern const std::string CONTEXT_REMOTE_PORT;
class LLHost;
-/**
+/**
* @class LLSocket
* @brief Implementation of a wrapper around a socket.
*
@@ -62,134 +62,134 @@ class LLHost;
class LLSocket
{
public:
- /**
- * @brief Reference counted shared pointers to sockets.
- */
- typedef std::shared_ptr<LLSocket> ptr_t;
-
- /**
- * @brief Type of socket to create.
- */
- enum EType
- {
- STREAM_TCP,
- DATAGRAM_UDP,
- };
-
- /**
- * @brief Anonymous enumeration to help identify ports
- */
- enum
- {
- PORT_INVALID = (U16)-1,
- PORT_EPHEMERAL = 0,
- };
-
- /**
- * @brief Create a socket.
- *
- * This is the call you would use if you intend to create a listen
- * socket. If you intend the socket to be known to external
- * clients without prior port notification, do not use
- * PORT_EPHEMERAL.
- * @param pool The apr pool to use. A child pool will be created
- * and associated with the socket.
- * @param type The type of socket to create
- * @param port The port for the socket
- * @param hostname e.g. APR_ANYADDR to listen openly, or "127.0.0.1"
- * @return A valid socket shared pointer if the call worked.
- */
- static ptr_t create(
- apr_pool_t* pool,
- EType type,
- U16 port = PORT_EPHEMERAL,
- const char *hostname = APR_ANYADDR);
-
- /**
- * @brief Create a LLSocket when you already have an apr socket.
- *
- * This method assumes an ephemeral port. This is typically used
- * by calls which spawn a socket such as a call to
- * <code>accept()</code> as in the server socket. This call should
- * not fail if you have a valid apr socket.
- * Because of the nature of how accept() works, you are expected
- * to create a new pool for the socket, use that pool for the
- * accept, and pass it in here where it will be bound with the
- * socket and destroyed at the same time.
- * @param socket The apr socket to use
- * @param pool The pool used to create the socket. *NOTE: The pool
- * passed in will be DESTROYED.
- * @return A valid socket shared pointer if the call worked.
- */
- static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
-
- /**
- * @brief Perform a blocking connect to a host. Do not use in production.
- *
- * @param host The host to connect this socket to.
- * @return Returns true if the connect was successful.
- */
- bool blockingConnect(const LLHost& host);
-
- /**
- * @brief Get the type of socket
- */
- //EType getType() const { return mType; }
-
- /**
- * @brief Get the port.
- *
- * This will return PORT_EPHEMERAL if bind was never called.
- * @return Returns the port associated with this socket.
- */
- U16 getPort() const { return mPort; }
-
- /**
- * @brief Get the apr socket implementation.
- *
- * @return Returns the raw apr socket.
- */
- apr_socket_t* getSocket() const { return mSocket; }
-
- /**
- * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
- * @param timeout Number of microseconds to wait on this socket. Any
- * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE.
- */
- void setBlocking(S32 timeout);
-
- /**
- * @brief Set default socket options, with SO_NONBLOCK = 1 and timeout = 0.
- */
- void setNonBlocking();
+ /**
+ * @brief Reference counted shared pointers to sockets.
+ */
+ typedef std::shared_ptr<LLSocket> ptr_t;
+
+ /**
+ * @brief Type of socket to create.
+ */
+ enum EType
+ {
+ STREAM_TCP,
+ DATAGRAM_UDP,
+ };
+
+ /**
+ * @brief Anonymous enumeration to help identify ports
+ */
+ enum
+ {
+ PORT_INVALID = (U16)-1,
+ PORT_EPHEMERAL = 0,
+ };
+
+ /**
+ * @brief Create a socket.
+ *
+ * This is the call you would use if you intend to create a listen
+ * socket. If you intend the socket to be known to external
+ * clients without prior port notification, do not use
+ * PORT_EPHEMERAL.
+ * @param pool The apr pool to use. A child pool will be created
+ * and associated with the socket.
+ * @param type The type of socket to create
+ * @param port The port for the socket
+ * @param hostname e.g. APR_ANYADDR to listen openly, or "127.0.0.1"
+ * @return A valid socket shared pointer if the call worked.
+ */
+ static ptr_t create(
+ apr_pool_t* pool,
+ EType type,
+ U16 port = PORT_EPHEMERAL,
+ const char *hostname = APR_ANYADDR);
+
+ /**
+ * @brief Create a LLSocket when you already have an apr socket.
+ *
+ * This method assumes an ephemeral port. This is typically used
+ * by calls which spawn a socket such as a call to
+ * <code>accept()</code> as in the server socket. This call should
+ * not fail if you have a valid apr socket.
+ * Because of the nature of how accept() works, you are expected
+ * to create a new pool for the socket, use that pool for the
+ * accept, and pass it in here where it will be bound with the
+ * socket and destroyed at the same time.
+ * @param socket The apr socket to use
+ * @param pool The pool used to create the socket. *NOTE: The pool
+ * passed in will be DESTROYED.
+ * @return A valid socket shared pointer if the call worked.
+ */
+ static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
+
+ /**
+ * @brief Perform a blocking connect to a host. Do not use in production.
+ *
+ * @param host The host to connect this socket to.
+ * @return Returns true if the connect was successful.
+ */
+ bool blockingConnect(const LLHost& host);
+
+ /**
+ * @brief Get the type of socket
+ */
+ //EType getType() const { return mType; }
+
+ /**
+ * @brief Get the port.
+ *
+ * This will return PORT_EPHEMERAL if bind was never called.
+ * @return Returns the port associated with this socket.
+ */
+ U16 getPort() const { return mPort; }
+
+ /**
+ * @brief Get the apr socket implementation.
+ *
+ * @return Returns the raw apr socket.
+ */
+ apr_socket_t* getSocket() const { return mSocket; }
+
+ /**
+ * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
+ * @param timeout Number of microseconds to wait on this socket. Any
+ * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE.
+ */
+ void setBlocking(S32 timeout);
+
+ /**
+ * @brief Set default socket options, with SO_NONBLOCK = 1 and timeout = 0.
+ */
+ void setNonBlocking();
protected:
- /**
- * @brief Protected constructor since should only make sockets
- * with one of the two <code>create()</code> calls.
- */
- LLSocket(apr_socket_t* socket, apr_pool_t* pool);
+ /**
+ * @brief Protected constructor since should only make sockets
+ * with one of the two <code>create()</code> calls.
+ */
+ LLSocket(apr_socket_t* socket, apr_pool_t* pool);
public:
- /**
- * @brief Do not call this directly.
- */
- ~LLSocket();
+ /**
+ * @brief Do not call this directly.
+ */
+ ~LLSocket();
protected:
- // The apr socket.
- apr_socket_t* mSocket;
+ // The apr socket.
+ apr_socket_t* mSocket;
- // our memory pool
- apr_pool_t* mPool;
+ // our memory pool
+ apr_pool_t* mPool;
- // The port if we know it.
- U16 mPort;
+ // The port if we know it.
+ U16 mPort;
- //EType mType;
+ //EType mType;
};
-/**
+/**
* @class LLIOSocketReader
* @brief An LLIOPipe implementation which reads from a socket.
* @see LLIOPipe
@@ -201,44 +201,44 @@ protected:
class LLIOSocketReader : public LLIOPipe
{
public:
- LLIOSocketReader(LLSocket::ptr_t socket);
- ~LLIOSocketReader();
+ LLIOSocketReader(LLSocket::ptr_t socket);
+ ~LLIOSocketReader();
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data coming in the socket.
- *
- * Since the socket and next pipe must exist for process to make
- * any sense, this method will return STATUS_PRECONDITION_NOT_MET
- * unless if they are not known.
- * If a STATUS_STOP returned by the next link in the chain, this
- * reader will turn of the socket polling.
- * @param buffer Pointer to a buffer which needs processing. Probably NULL.
- * @param bytes Number of bytes to in buffer to process. Probably 0.
- * @param eos True if this function is the last. Almost always false.
- * @param read Number of bytes actually processed.
- * @param pump The pump which is calling process. May be NULL.
- * @param context A data structure to pass structured data
- * @return STATUS_OK unless the preconditions are not met.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data coming in the socket.
+ *
+ * Since the socket and next pipe must exist for process to make
+ * any sense, this method will return STATUS_PRECONDITION_NOT_MET
+ * unless if they are not known.
+ * If a STATUS_STOP returned by the next link in the chain, this
+ * reader will turn of the socket polling.
+ * @param buffer Pointer to a buffer which needs processing. Probably NULL.
+ * @param bytes Number of bytes to in buffer to process. Probably 0.
+ * @param eos True if this function is the last. Almost always false.
+ * @param read Number of bytes actually processed.
+ * @param pump The pump which is calling process. May be NULL.
+ * @param context A data structure to pass structured data
+ * @return STATUS_OK unless the preconditions are not met.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- LLSocket::ptr_t mSource;
- std::vector<U8> mBuffer;
- bool mInitialized;
+ LLSocket::ptr_t mSource;
+ std::vector<U8> mBuffer;
+ bool mInitialized;
};
-/**
+/**
* @class LLIOSocketWriter
* @brief An LLIOPipe implementation which writes to a socket
* @see LLIOPipe
@@ -249,42 +249,42 @@ protected:
class LLIOSocketWriter : public LLIOPipe
{
public:
- LLIOSocketWriter(LLSocket::ptr_t socket);
- ~LLIOSocketWriter();
+ LLIOSocketWriter(LLSocket::ptr_t socket);
+ ~LLIOSocketWriter();
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Write the data in buffer to the socket.
- *
- * Since the socket pipe must exist for process to make any sense,
- * this method will return STATUS_PRECONDITION_NOT_MET if it is
- * not known.
- * @param buffer Pointer to a buffer which needs processing.
- * @param bytes Number of bytes to in buffer to process.
- * @param eos True if this function is the last.
- * @param read Number of bytes actually processed.
- * @param pump The pump which is calling process. May be NULL.
- * @param context A data structure to pass structured data
- * @return A return code for the write.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Write the data in buffer to the socket.
+ *
+ * Since the socket pipe must exist for process to make any sense,
+ * this method will return STATUS_PRECONDITION_NOT_MET if it is
+ * not known.
+ * @param buffer Pointer to a buffer which needs processing.
+ * @param bytes Number of bytes to in buffer to process.
+ * @param eos True if this function is the last.
+ * @param read Number of bytes actually processed.
+ * @param pump The pump which is calling process. May be NULL.
+ * @param context A data structure to pass structured data
+ * @return A return code for the write.
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- LLSocket::ptr_t mDestination;
- U8* mLastWritten;
- bool mInitialized;
+ LLSocket::ptr_t mDestination;
+ U8* mLastWritten;
+ bool mInitialized;
};
-/**
+/**
* @class LLIOServerSocket
* @brief An IOPipe implementation which listens and spawns connected
* sockets.
@@ -304,49 +304,49 @@ protected:
class LLIOServerSocket : public LLIOPipe
{
public:
- typedef LLSocket::ptr_t socket_t;
- typedef std::shared_ptr<LLChainIOFactory> factory_t;
- LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
- virtual ~LLIOServerSocket();
-
- /**
- * @brief Set the timeout for the generated chains.
- *
- * This value is passed directly to the LLPumpIO::addChain()
- * method. The default on construction is set to
- * DEFAULT_CHAIN_EXPIRY_SECS which is a reasonable value for most
- * applications based on this library. Avoid passing in
- * NEVER_CHAIN_EXPIRY_SECS unless you have another method of
- * harvesting chains.
- * @param timeout_secs The seconds before timeout for the response chain.
- */
- void setResponseTimeout(F32 timeout_secs);
-
- /* @name LLIOPipe virtual implementations
- */
- //@{
+ typedef LLSocket::ptr_t socket_t;
+ typedef std::shared_ptr<LLChainIOFactory> factory_t;
+ LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
+ virtual ~LLIOServerSocket();
+
+ /**
+ * @brief Set the timeout for the generated chains.
+ *
+ * This value is passed directly to the LLPumpIO::addChain()
+ * method. The default on construction is set to
+ * DEFAULT_CHAIN_EXPIRY_SECS which is a reasonable value for most
+ * applications based on this library. Avoid passing in
+ * NEVER_CHAIN_EXPIRY_SECS unless you have another method of
+ * harvesting chains.
+ * @param timeout_secs The seconds before timeout for the response chain.
+ */
+ void setResponseTimeout(F32 timeout_secs);
+
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
protected:
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- apr_pool_t* mPool;
- socket_t mListenSocket;
- factory_t mReactor;
- bool mInitialized;
- F32 mResponseTimeout;
+ apr_pool_t* mPool;
+ socket_t mListenSocket;
+ factory_t mReactor;
+ bool mInitialized;
+ F32 mResponseTimeout;
};
#if 0
-/**
+/**
* @class LLIODataSocket
* @brief BRIEF_DESC
*
@@ -355,31 +355,31 @@ protected:
class LLIODataSocket : public LLIOSocket
{
public:
- /**
- * @brief Construct a datagram socket.
- *
- * If you pass in LLIOSocket::PORT_EPHEMERAL as the suggested
- * port, The socket will not be in a 'listen' mode, but can still
- * read data sent back to it's port. When suggested_port is not
- * ephemeral or invalid and bind fails, the port discovery
- * algorithm will search through a limited set of ports to
- * try to find an open port. If that process fails, getPort() will
- * return LLIOSocket::PORT_INVALID
- * @param suggested_port The port you would like to bind. Use
- * LLIOSocket::PORT_EPHEMERAL for an unspecified port.
- * @param start_discovery_port The start range for
- * @param pool The pool to use for allocation.
- */
- LLIODataSocket(
- U16 suggested_port,
- U16 start_discovery_port,
- apr_pool_t* pool);
- virtual ~LLIODataSocket();
+ /**
+ * @brief Construct a datagram socket.
+ *
+ * If you pass in LLIOSocket::PORT_EPHEMERAL as the suggested
+ * port, The socket will not be in a 'listen' mode, but can still
+ * read data sent back to it's port. When suggested_port is not
+ * ephemeral or invalid and bind fails, the port discovery
+ * algorithm will search through a limited set of ports to
+ * try to find an open port. If that process fails, getPort() will
+ * return LLIOSocket::PORT_INVALID
+ * @param suggested_port The port you would like to bind. Use
+ * LLIOSocket::PORT_EPHEMERAL for an unspecified port.
+ * @param start_discovery_port The start range for
+ * @param pool The pool to use for allocation.
+ */
+ LLIODataSocket(
+ U16 suggested_port,
+ U16 start_discovery_port,
+ apr_pool_t* pool);
+ virtual ~LLIODataSocket();
protected:
private:
- apr_socket_t* mSocket;
+ apr_socket_t* mSocket;
};
#endif
diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp
index 850bc2a616..a1bf6332b4 100644
--- a/indra/llmessage/llioutil.cpp
+++ b/indra/llmessage/llioutil.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llioutil.cpp
* @author Phoenix
* @date 2005-10-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,65 +34,65 @@
* LLIOFlush
*/
LLIOPipe::EStatus LLIOFlush::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
- eos = true;
- return STATUS_OK;
+ eos = true;
+ return STATUS_OK;
}
-/**
+/**
* @class LLIOSleep
*/
LLIOPipe::EStatus LLIOSleep::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- if(mSeconds > 0.0)
- {
- if(pump) pump->sleepChain(mSeconds);
- mSeconds = 0.0;
- return STATUS_BREAK;
- }
- return STATUS_DONE;
+ if(mSeconds > 0.0)
+ {
+ if(pump) pump->sleepChain(mSeconds);
+ mSeconds = 0.0;
+ return STATUS_BREAK;
+ }
+ return STATUS_DONE;
}
-/**
+/**
* @class LLIOAddChain
*/
LLIOPipe::EStatus LLIOAddChain::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump)
{
LL_PROFILE_ZONE_SCOPED;
- pump->addChain(mChain, mTimeout);
- return STATUS_DONE;
+ pump->addChain(mChain, mTimeout);
+ return STATUS_DONE;
}
/**
* LLChangeChannel
*/
LLChangeChannel::LLChangeChannel(S32 is, S32 becomes) :
- mIs(is),
- mBecomes(becomes)
+ mIs(is),
+ mBecomes(becomes)
{
}
void LLChangeChannel::operator()(LLSegment& segment)
{
- if(segment.isOnChannel(mIs))
- {
- segment.setChannel(mBecomes);
- }
+ if(segment.isOnChannel(mIs))
+ {
+ segment.setChannel(mBecomes);
+ }
}
diff --git a/indra/llmessage/llioutil.h b/indra/llmessage/llioutil.h
index c404a98bed..b6a4a9242f 100644
--- a/indra/llmessage/llioutil.h
+++ b/indra/llmessage/llioutil.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llioutil.h
* @author Phoenix
* @date 2005-10-05
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,7 +33,7 @@
#include "lliopipe.h"
#include "llpumpio.h"
-/**
+/**
* @class LLIOFlush
* @brief This class is used as a mini chain head which drains the buffer.
* @see LLIOPipe
@@ -44,27 +44,27 @@
class LLIOFlush : public LLIOPipe
{
public:
- LLIOFlush() {}
- virtual ~LLIOFlush() {}
+ LLIOFlush() {}
+ virtual ~LLIOFlush() {}
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
};
-/**
+/**
* @class LLIOSleep
* @brief This is a simple helper class which will hold a chain and
* process it later using pump mechanisms
@@ -73,28 +73,28 @@ protected:
class LLIOSleep : public LLIOPipe
{
public:
- LLIOSleep(F64 sleep_seconds) : mSeconds(sleep_seconds) {}
- virtual ~LLIOSleep() {}
+ LLIOSleep(F64 sleep_seconds) : mSeconds(sleep_seconds) {}
+ virtual ~LLIOSleep() {}
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- F64 mSeconds;
+ F64 mSeconds;
};
-/**
+/**
* @class LLIOAddChain
* @brief Simple pipe that just adds a chain to a pump.
* @see LLIOPipe
@@ -102,33 +102,33 @@ protected:
class LLIOAddChain : public LLIOPipe
{
public:
- LLIOAddChain(const LLPumpIO::chain_t& chain, F32 timeout) :
- mChain(chain),
- mTimeout(timeout)
- {}
- virtual ~LLIOAddChain() {}
+ LLIOAddChain(const LLPumpIO::chain_t& chain, F32 timeout) :
+ mChain(chain),
+ mTimeout(timeout)
+ {}
+ virtual ~LLIOAddChain() {}
protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
protected:
- LLPumpIO::chain_t mChain;
- F32 mTimeout;
+ LLPumpIO::chain_t mChain;
+ F32 mTimeout;
};
-/**
+/**
* @class LLChangeChannel
* @brief This class changes the channel of segments in the buffer
* @see LLBufferArray
@@ -150,22 +150,22 @@ protected:
class LLChangeChannel
{
public:
- /**
- * @brief Constructor for iterating over a segment range to change channel.
- *
- * @param is The channel to match when looking at a segment.
- * @param becomes The channel to set the segment when a match is found.
- */
- LLChangeChannel(S32 is, S32 becomes);
+ /**
+ * @brief Constructor for iterating over a segment range to change channel.
+ *
+ * @param is The channel to match when looking at a segment.
+ * @param becomes The channel to set the segment when a match is found.
+ */
+ LLChangeChannel(S32 is, S32 becomes);
- /**
- * @brief Do the work of changing the channel
- */
- void operator()(LLSegment& segment);
+ /**
+ * @brief Do the work of changing the channel
+ */
+ void operator()(LLSegment& segment);
protected:
- S32 mIs;
- S32 mBecomes;
+ S32 mIs;
+ S32 mBecomes;
};
diff --git a/indra/llmessage/llloginflags.h b/indra/llmessage/llloginflags.h
index 45833fc914..a4d709888c 100644
--- a/indra/llmessage/llloginflags.h
+++ b/indra/llmessage/llloginflags.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llloginflags.h
* @brief Login flag constants.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,20 +28,20 @@
#define LL_LLLOGINFLAGS_H
// Is this your first login to Second Life?
-const U32 LOGIN_FLAG_FIRST_LOGIN = (1 << 0);
+const U32 LOGIN_FLAG_FIRST_LOGIN = (1 << 0);
// Is this a trial account?
-const U32 LOGIN_FLAG_TRIAL = (1 << 1);
+const U32 LOGIN_FLAG_TRIAL = (1 << 1);
// Stipend paid since last login?
-const U32 LOGIN_FLAG_STIPEND_SINCE_LOGIN = (1 << 2);
+const U32 LOGIN_FLAG_STIPEND_SINCE_LOGIN = (1 << 2);
// Is your account enabled?
-const U32 LOGIN_FLAG_ENABLED = (1 << 3);
+const U32 LOGIN_FLAG_ENABLED = (1 << 3);
// Is the Pacific Time zone (aka the server time zone)
// currently observing daylight savings time?
-const U32 LOGIN_FLAG_PACIFIC_DAYLIGHT_TIME = (1 << 4);
+const U32 LOGIN_FLAG_PACIFIC_DAYLIGHT_TIME = (1 << 4);
// Does the avatar have wearables or not
const U32 LOGIN_FLAG_GENDERED = (1 << 5);
diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp
index 6414c2c016..fe01f2d4a4 100644
--- a/indra/llmessage/llmail.cpp
+++ b/indra/llmessage/llmail.cpp
@@ -1,396 +1,396 @@
-/**
- * @file llmail.cpp
- * @brief smtp helper functions.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llmail.h"
-
-// APR on Windows needs full windows headers
-#include "llwin32headers.h"
-#include <string>
-#include <sstream>
-
-#include "apr_pools.h"
-#include "apr_network_io.h"
-
-#include "llapr.h"
-#include "llbase32.h" // IM-to-email address
-#include "llblowfishcipher.h"
-#include "llerror.h"
-#include "llhost.h"
-#include "llsd.h"
-#include "llstring.h"
-#include "lluuid.h"
-#include "net.h"
-
-//
-// constants
-//
-const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
-
-static bool gMailEnabled = true;
-static apr_pool_t* gMailPool;
-static apr_sockaddr_t* gSockAddr;
-static apr_socket_t* gMailSocket;
-
-bool connect_smtp();
-void disconnect_smtp();
-
-//#if LL_WINDOWS
-//SOCKADDR_IN gMailDstAddr, gMailSrcAddr, gMailLclAddr;
-//#else
-//struct sockaddr_in gMailDstAddr, gMailSrcAddr, gMailLclAddr;
-//#endif
-
-// Define this for a super-spammy mail mode.
-//#define LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND 1
-
-bool connect_smtp()
-{
- // Prepare an soket to talk smtp
- apr_status_t status;
- status = apr_socket_create(
- &gMailSocket,
- gSockAddr->sa.sin.sin_family,
- SOCK_STREAM,
- APR_PROTO_TCP,
- gMailPool);
- if(ll_apr_warn_status(status)) return false;
- status = apr_socket_connect(gMailSocket, gSockAddr);
- if(ll_apr_warn_status(status))
- {
- status = apr_socket_close(gMailSocket);
- ll_apr_warn_status(status);
- return false;
- }
- return true;
-}
-
-void disconnect_smtp()
-{
- if(gMailSocket)
- {
- apr_status_t status = apr_socket_close(gMailSocket);
- ll_apr_warn_status(status);
- gMailSocket = NULL;
- }
-}
-
-// Returns true on success.
-// message should NOT be SMTP escaped.
-// static
-bool LLMail::send(
- const char* from_name,
- const char* from_address,
- const char* to_name,
- const char* to_address,
- const char* subject,
- const char* message,
- const LLSD& headers)
-{
- std::string header = buildSMTPTransaction(
- from_name,
- from_address,
- to_name,
- to_address,
- subject,
- headers);
- if(header.empty())
- {
- return false;
- }
-
- std::string message_str;
- if(message)
- {
- message_str = message;
- }
- bool rv = send(header, message_str, to_address, from_address);
- if(rv) return true;
- return false;
-}
-
-// static
-void LLMail::init(const std::string& hostname, apr_pool_t* pool)
-{
- gMailSocket = NULL;
- if(hostname.empty() || !pool)
- {
- gMailPool = NULL;
- gSockAddr = NULL;
- }
- else
- {
- gMailPool = pool;
-
- // collect all the information into a socaddr sturcture. the
- // documentation is a bit unclear, but I either have to
- // specify APR_UNSPEC or not specify any flags. I am not sure
- // which option is better.
- apr_status_t status = apr_sockaddr_info_get(
- &gSockAddr,
- hostname.c_str(),
- APR_UNSPEC,
- 25,
- APR_IPV4_ADDR_OK,
- gMailPool);
- ll_apr_warn_status(status);
- }
-}
-
-// static
-void LLMail::enable(bool mail_enabled)
-{
- gMailEnabled = mail_enabled;
-}
-
-// Test a subject line for RFC2822 compliance.
-static bool valid_subject_chars(const char *subject)
-{
- for (; *subject != '\0'; subject++)
- {
- unsigned char c = *subject;
-
- if (c == '\xa' || c == '\xd' || c > '\x7f')
- {
- return false;
- }
- }
-
- return true;
-}
-
-// static
-std::string LLMail::buildSMTPTransaction(
- const char* from_name,
- const char* from_address,
- const char* to_name,
- const char* to_address,
- const char* subject,
- const LLSD& headers)
-{
- if(!from_address || !to_address)
- {
- LL_INFOS() << "send_mail build_smtp_transaction reject: missing to and/or"
- << " from address." << LL_ENDL;
- return std::string();
- }
- if(!valid_subject_chars(subject))
- {
- LL_INFOS() << "send_mail build_smtp_transaction reject: bad subject header: "
- << "to=<" << to_address
- << ">, from=<" << from_address << ">"
- << LL_ENDL;
- return std::string();
- }
- std::ostringstream from_fmt;
- if(from_name && from_name[0])
- {
- // "My Name" <myaddress@example.com>
- from_fmt << "\"" << from_name << "\" <" << from_address << ">";
- }
- else
- {
- // <myaddress@example.com>
- from_fmt << "<" << from_address << ">";
- }
- std::ostringstream to_fmt;
- if(to_name && to_name[0])
- {
- to_fmt << "\"" << to_name << "\" <" << to_address << ">";
- }
- else
- {
- to_fmt << "<" << to_address << ">";
- }
- std::ostringstream header;
- header
- << "HELO lindenlab.com\r\n"
- << "MAIL FROM:<" << from_address << ">\r\n"
- << "RCPT TO:<" << to_address << ">\r\n"
- << "DATA\r\n"
- << "From: " << from_fmt.str() << "\r\n"
- << "To: " << to_fmt.str() << "\r\n"
- << "Subject: " << subject << "\r\n";
-
- if(headers.isMap())
- {
- LLSD::map_const_iterator iter = headers.beginMap();
- LLSD::map_const_iterator end = headers.endMap();
- for(; iter != end; ++iter)
- {
- header << (*iter).first << ": " << ((*iter).second).asString()
- << "\r\n";
- }
- }
-
- header << "\r\n";
- return header.str();
-}
-
-// static
-bool LLMail::send(
- const std::string& header,
- const std::string& raw_message,
- const char* from_address,
- const char* to_address)
-{
- if(!from_address || !to_address)
- {
- LL_INFOS() << "send_mail reject: missing to and/or from address."
- << LL_ENDL;
- return false;
- }
-
- // remove any "." SMTP commands to prevent injection (DEV-35777)
- // we don't need to worry about "\r\n.\r\n" because of the
- // "\n" --> "\n\n" conversion going into rfc2822_msg below
- std::string message = raw_message;
- std::string bad_string = "\n.\n";
- std::string good_string = "\n..\n";
- while (1)
- {
- int index = message.find(bad_string);
- if (index == std::string::npos) break;
- message.replace(index, bad_string.size(), good_string);
- }
-
- // convert all "\n" into "\r\n"
- std::ostringstream rfc2822_msg;
- for(U32 i = 0; i < message.size(); ++i)
- {
- switch(message[i])
- {
- case '\0':
- break;
- case '\n':
- // *NOTE: this is kinda busted if we're fed \r\n
- rfc2822_msg << "\r\n";
- break;
- default:
- rfc2822_msg << message[i];
- break;
- }
- }
-
- if(!gMailEnabled)
- {
- LL_INFOS() << "send_mail reject: mail system is disabled: to=<"
- << to_address << ">, from=<" << from_address
- << ">" << LL_ENDL;
- // Any future interface to SMTP should return this as an
- // error. --mark
- return true;
- }
- if(!gSockAddr)
- {
- LL_WARNS() << "send_mail reject: mail system not initialized: to=<"
- << to_address << ">, from=<" << from_address
- << ">" << LL_ENDL;
- return false;
- }
-
- if(!connect_smtp())
- {
- LL_WARNS() << "send_mail reject: SMTP connect failure: to=<"
- << to_address << ">, from=<" << from_address
- << ">" << LL_ENDL;
- return false;
- }
-
- std::ostringstream smtp_fmt;
- smtp_fmt << header << rfc2822_msg.str() << "\r\n" << ".\r\n" << "QUIT\r\n";
- std::string smtp_transaction = smtp_fmt.str();
- size_t original_size = smtp_transaction.size();
- apr_size_t send_size = original_size;
- apr_status_t status = apr_socket_send(
- gMailSocket,
- smtp_transaction.c_str(),
- (apr_size_t*)&send_size);
- disconnect_smtp();
- if(ll_apr_warn_status(status))
- {
- LL_WARNS() << "send_mail socket failure: unable to write "
- << "to=<" << to_address
- << ">, from=<" << from_address << ">"
- << ", bytes=" << original_size
- << ", sent=" << send_size << LL_ENDL;
- return false;
- }
- if(send_size >= LL_MAX_KNOWN_GOOD_MAIL_SIZE)
- {
- LL_WARNS() << "send_mail message has been shown to fail in testing "
- << "when sending messages larger than " << LL_MAX_KNOWN_GOOD_MAIL_SIZE
- << " bytes. The next log about success is potentially a lie." << LL_ENDL;
- }
- LL_DEBUGS() << "send_mail success: "
- << "to=<" << to_address
- << ">, from=<" << from_address << ">"
- << ", bytes=" << original_size
- << ", sent=" << send_size << LL_ENDL;
-
-#if LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND
- LL_INFOS() << rfc2822_msg.str() << LL_ENDL;
-#endif
- return true;
-}
-
-
-// static
-std::string LLMail::encryptIMEmailAddress(const LLUUID& from_agent_id,
- const LLUUID& to_agent_id,
- U32 time,
- const U8* secret,
- size_t secret_size)
-{
-#if LL_WINDOWS
- return "blowfish-not-supported-on-windows";
-#else
- size_t data_size = 4 + UUID_BYTES + UUID_BYTES;
- // Convert input data into a binary blob
- std::vector<U8> data;
- data.resize(data_size);
- // *NOTE: This may suffer from endian issues. Could be htolememcpy.
- memcpy(&data[0], &time, 4);
- memcpy(&data[4], &from_agent_id.mData[0], UUID_BYTES);
- memcpy(&data[4 + UUID_BYTES], &to_agent_id.mData[0], UUID_BYTES);
-
- // Encrypt the blob
- LLBlowfishCipher cipher(secret, secret_size);
- size_t encrypted_size = cipher.requiredEncryptionSpace(data.size());
- U8* encrypted = new U8[encrypted_size];
- cipher.encrypt(&data[0], data_size, encrypted, encrypted_size);
-
- std::string address = LLBase32::encode(encrypted, encrypted_size);
-
- // Make it more pretty for humans.
- LLStringUtil::toLower(address);
-
- delete [] encrypted;
-
- return address;
-#endif
-}
+/**
+ * @file llmail.cpp
+ * @brief smtp helper functions.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmail.h"
+
+// APR on Windows needs full windows headers
+#include "llwin32headers.h"
+#include <string>
+#include <sstream>
+
+#include "apr_pools.h"
+#include "apr_network_io.h"
+
+#include "llapr.h"
+#include "llbase32.h" // IM-to-email address
+#include "llblowfishcipher.h"
+#include "llerror.h"
+#include "llhost.h"
+#include "llsd.h"
+#include "llstring.h"
+#include "lluuid.h"
+#include "net.h"
+
+//
+// constants
+//
+const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
+
+static bool gMailEnabled = true;
+static apr_pool_t* gMailPool;
+static apr_sockaddr_t* gSockAddr;
+static apr_socket_t* gMailSocket;
+
+bool connect_smtp();
+void disconnect_smtp();
+
+//#if LL_WINDOWS
+//SOCKADDR_IN gMailDstAddr, gMailSrcAddr, gMailLclAddr;
+//#else
+//struct sockaddr_in gMailDstAddr, gMailSrcAddr, gMailLclAddr;
+//#endif
+
+// Define this for a super-spammy mail mode.
+//#define LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND 1
+
+bool connect_smtp()
+{
+ // Prepare an soket to talk smtp
+ apr_status_t status;
+ status = apr_socket_create(
+ &gMailSocket,
+ gSockAddr->sa.sin.sin_family,
+ SOCK_STREAM,
+ APR_PROTO_TCP,
+ gMailPool);
+ if(ll_apr_warn_status(status)) return false;
+ status = apr_socket_connect(gMailSocket, gSockAddr);
+ if(ll_apr_warn_status(status))
+ {
+ status = apr_socket_close(gMailSocket);
+ ll_apr_warn_status(status);
+ return false;
+ }
+ return true;
+}
+
+void disconnect_smtp()
+{
+ if(gMailSocket)
+ {
+ apr_status_t status = apr_socket_close(gMailSocket);
+ ll_apr_warn_status(status);
+ gMailSocket = NULL;
+ }
+}
+
+// Returns true on success.
+// message should NOT be SMTP escaped.
+// static
+bool LLMail::send(
+ const char* from_name,
+ const char* from_address,
+ const char* to_name,
+ const char* to_address,
+ const char* subject,
+ const char* message,
+ const LLSD& headers)
+{
+ std::string header = buildSMTPTransaction(
+ from_name,
+ from_address,
+ to_name,
+ to_address,
+ subject,
+ headers);
+ if(header.empty())
+ {
+ return false;
+ }
+
+ std::string message_str;
+ if(message)
+ {
+ message_str = message;
+ }
+ bool rv = send(header, message_str, to_address, from_address);
+ if(rv) return true;
+ return false;
+}
+
+// static
+void LLMail::init(const std::string& hostname, apr_pool_t* pool)
+{
+ gMailSocket = NULL;
+ if(hostname.empty() || !pool)
+ {
+ gMailPool = NULL;
+ gSockAddr = NULL;
+ }
+ else
+ {
+ gMailPool = pool;
+
+ // collect all the information into a socaddr sturcture. the
+ // documentation is a bit unclear, but I either have to
+ // specify APR_UNSPEC or not specify any flags. I am not sure
+ // which option is better.
+ apr_status_t status = apr_sockaddr_info_get(
+ &gSockAddr,
+ hostname.c_str(),
+ APR_UNSPEC,
+ 25,
+ APR_IPV4_ADDR_OK,
+ gMailPool);
+ ll_apr_warn_status(status);
+ }
+}
+
+// static
+void LLMail::enable(bool mail_enabled)
+{
+ gMailEnabled = mail_enabled;
+}
+
+// Test a subject line for RFC2822 compliance.
+static bool valid_subject_chars(const char *subject)
+{
+ for (; *subject != '\0'; subject++)
+ {
+ unsigned char c = *subject;
+
+ if (c == '\xa' || c == '\xd' || c > '\x7f')
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// static
+std::string LLMail::buildSMTPTransaction(
+ const char* from_name,
+ const char* from_address,
+ const char* to_name,
+ const char* to_address,
+ const char* subject,
+ const LLSD& headers)
+{
+ if(!from_address || !to_address)
+ {
+ LL_INFOS() << "send_mail build_smtp_transaction reject: missing to and/or"
+ << " from address." << LL_ENDL;
+ return std::string();
+ }
+ if(!valid_subject_chars(subject))
+ {
+ LL_INFOS() << "send_mail build_smtp_transaction reject: bad subject header: "
+ << "to=<" << to_address
+ << ">, from=<" << from_address << ">"
+ << LL_ENDL;
+ return std::string();
+ }
+ std::ostringstream from_fmt;
+ if(from_name && from_name[0])
+ {
+ // "My Name" <myaddress@example.com>
+ from_fmt << "\"" << from_name << "\" <" << from_address << ">";
+ }
+ else
+ {
+ // <myaddress@example.com>
+ from_fmt << "<" << from_address << ">";
+ }
+ std::ostringstream to_fmt;
+ if(to_name && to_name[0])
+ {
+ to_fmt << "\"" << to_name << "\" <" << to_address << ">";
+ }
+ else
+ {
+ to_fmt << "<" << to_address << ">";
+ }
+ std::ostringstream header;
+ header
+ << "HELO lindenlab.com\r\n"
+ << "MAIL FROM:<" << from_address << ">\r\n"
+ << "RCPT TO:<" << to_address << ">\r\n"
+ << "DATA\r\n"
+ << "From: " << from_fmt.str() << "\r\n"
+ << "To: " << to_fmt.str() << "\r\n"
+ << "Subject: " << subject << "\r\n";
+
+ if(headers.isMap())
+ {
+ LLSD::map_const_iterator iter = headers.beginMap();
+ LLSD::map_const_iterator end = headers.endMap();
+ for(; iter != end; ++iter)
+ {
+ header << (*iter).first << ": " << ((*iter).second).asString()
+ << "\r\n";
+ }
+ }
+
+ header << "\r\n";
+ return header.str();
+}
+
+// static
+bool LLMail::send(
+ const std::string& header,
+ const std::string& raw_message,
+ const char* from_address,
+ const char* to_address)
+{
+ if(!from_address || !to_address)
+ {
+ LL_INFOS() << "send_mail reject: missing to and/or from address."
+ << LL_ENDL;
+ return false;
+ }
+
+ // remove any "." SMTP commands to prevent injection (DEV-35777)
+ // we don't need to worry about "\r\n.\r\n" because of the
+ // "\n" --> "\n\n" conversion going into rfc2822_msg below
+ std::string message = raw_message;
+ std::string bad_string = "\n.\n";
+ std::string good_string = "\n..\n";
+ while (1)
+ {
+ int index = message.find(bad_string);
+ if (index == std::string::npos) break;
+ message.replace(index, bad_string.size(), good_string);
+ }
+
+ // convert all "\n" into "\r\n"
+ std::ostringstream rfc2822_msg;
+ for(U32 i = 0; i < message.size(); ++i)
+ {
+ switch(message[i])
+ {
+ case '\0':
+ break;
+ case '\n':
+ // *NOTE: this is kinda busted if we're fed \r\n
+ rfc2822_msg << "\r\n";
+ break;
+ default:
+ rfc2822_msg << message[i];
+ break;
+ }
+ }
+
+ if(!gMailEnabled)
+ {
+ LL_INFOS() << "send_mail reject: mail system is disabled: to=<"
+ << to_address << ">, from=<" << from_address
+ << ">" << LL_ENDL;
+ // Any future interface to SMTP should return this as an
+ // error. --mark
+ return true;
+ }
+ if(!gSockAddr)
+ {
+ LL_WARNS() << "send_mail reject: mail system not initialized: to=<"
+ << to_address << ">, from=<" << from_address
+ << ">" << LL_ENDL;
+ return false;
+ }
+
+ if(!connect_smtp())
+ {
+ LL_WARNS() << "send_mail reject: SMTP connect failure: to=<"
+ << to_address << ">, from=<" << from_address
+ << ">" << LL_ENDL;
+ return false;
+ }
+
+ std::ostringstream smtp_fmt;
+ smtp_fmt << header << rfc2822_msg.str() << "\r\n" << ".\r\n" << "QUIT\r\n";
+ std::string smtp_transaction = smtp_fmt.str();
+ size_t original_size = smtp_transaction.size();
+ apr_size_t send_size = original_size;
+ apr_status_t status = apr_socket_send(
+ gMailSocket,
+ smtp_transaction.c_str(),
+ (apr_size_t*)&send_size);
+ disconnect_smtp();
+ if(ll_apr_warn_status(status))
+ {
+ LL_WARNS() << "send_mail socket failure: unable to write "
+ << "to=<" << to_address
+ << ">, from=<" << from_address << ">"
+ << ", bytes=" << original_size
+ << ", sent=" << send_size << LL_ENDL;
+ return false;
+ }
+ if(send_size >= LL_MAX_KNOWN_GOOD_MAIL_SIZE)
+ {
+ LL_WARNS() << "send_mail message has been shown to fail in testing "
+ << "when sending messages larger than " << LL_MAX_KNOWN_GOOD_MAIL_SIZE
+ << " bytes. The next log about success is potentially a lie." << LL_ENDL;
+ }
+ LL_DEBUGS() << "send_mail success: "
+ << "to=<" << to_address
+ << ">, from=<" << from_address << ">"
+ << ", bytes=" << original_size
+ << ", sent=" << send_size << LL_ENDL;
+
+#if LL_LOG_ENTIRE_MAIL_MESSAGE_ON_SEND
+ LL_INFOS() << rfc2822_msg.str() << LL_ENDL;
+#endif
+ return true;
+}
+
+
+// static
+std::string LLMail::encryptIMEmailAddress(const LLUUID& from_agent_id,
+ const LLUUID& to_agent_id,
+ U32 time,
+ const U8* secret,
+ size_t secret_size)
+{
+#if LL_WINDOWS
+ return "blowfish-not-supported-on-windows";
+#else
+ size_t data_size = 4 + UUID_BYTES + UUID_BYTES;
+ // Convert input data into a binary blob
+ std::vector<U8> data;
+ data.resize(data_size);
+ // *NOTE: This may suffer from endian issues. Could be htolememcpy.
+ memcpy(&data[0], &time, 4);
+ memcpy(&data[4], &from_agent_id.mData[0], UUID_BYTES);
+ memcpy(&data[4 + UUID_BYTES], &to_agent_id.mData[0], UUID_BYTES);
+
+ // Encrypt the blob
+ LLBlowfishCipher cipher(secret, secret_size);
+ size_t encrypted_size = cipher.requiredEncryptionSpace(data.size());
+ U8* encrypted = new U8[encrypted_size];
+ cipher.encrypt(&data[0], data_size, encrypted, encrypted_size);
+
+ std::string address = LLBase32::encode(encrypted, encrypted_size);
+
+ // Make it more pretty for humans.
+ LLStringUtil::toLower(address);
+
+ delete [] encrypted;
+
+ return address;
+#endif
+}
diff --git a/indra/llmessage/llmail.h b/indra/llmessage/llmail.h
index f97a443c47..1523e7b5c6 100644
--- a/indra/llmessage/llmail.h
+++ b/indra/llmessage/llmail.h
@@ -1,130 +1,130 @@
-/**
- * @file llmail.h
- * @brief smtp helper functions.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMAIL_H
-#define LL_LLMAIL_H
-
-typedef struct apr_pool_t apr_pool_t;
-
-#include "llsd.h"
-
-class LLMail
-{
-public:
- // if hostname is NULL, then the host is resolved as 'mail'
- static void init(const std::string& hostname, apr_pool_t* pool);
-
- // Allow all email transmission to be disabled/enabled.
- static void enable(bool mail_enabled);
-
- /**
- * @brief send an email
- * @param from_name The name of the email sender
- * @param from_address The email address for the sender
- * @param to_name The name of the email recipient
- * @param to_address The email recipient address
- * @param subject The subject of the email
- * @param headers optional X-Foo headers in an llsd map.
- * @return Returns true if the call succeeds, false otherwise.
- *
- * Results in:
- * From: "from_name" <from_address>
- * To: "to_name" <to_address>
- * Subject: subject
- *
- * message
- */
- static bool send(
- const char* from_name,
- const char* from_address,
- const char* to_name,
- const char* to_address,
- const char* subject,
- const char* message,
- const LLSD& headers = LLSD());
-
- /**
- * @brief build the complete smtp transaction & header for use in an
- * mail.
- *
- * @param from_name The name of the email sender
- * @param from_address The email address for the sender
- * @param to_name The name of the email recipient
- * @param to_address The email recipient address
- * @param subject The subject of the email
- * @param headers optional X-Foo headers in an llsd map.
- * @return Returns the complete SMTP transaction mail header.
- */
- static std::string buildSMTPTransaction(
- const char* from_name,
- const char* from_address,
- const char* to_name,
- const char* to_address,
- const char* subject,
- const LLSD& headers = LLSD());
-
- /**
- * @brief send an email with header and body.
- *
- * @param header The email header. Use build_mail_header().
- * @param message The unescaped email message.
- * @param from_address Used for debugging
- * @param to_address Used for debugging
- * @return Returns true if the message could be sent.
- */
- static bool send(
- const std::string& header,
- const std::string& message,
- const char* from_address,
- const char* to_address);
-
- // IM-to-email sessions use a "session id" based on an encrypted
- // combination of from agent_id, to agent_id, and timestamp. When
- // a user replies to an email we use the from_id to determine the
- // sender's name and the to_id to route the message. The address
- // is encrypted to prevent users from building addresses to spoof
- // IMs from other users. The timestamps allow the "sessions" to
- // expire, in case one of the sessions is stolen/hijacked.
- //
- // indra/tools/mailglue is responsible for parsing the inbound mail.
- //
- // secret: binary blob passed to blowfish, max length 56 bytes
- // secret_size: length of blob, in bytes
- //
- // Returns: "base64" encoded email local-part, with _ and - as the
- // non-alphanumeric characters. This allows better compatibility
- // with email systems than the default / and + extra chars. JC
- static std::string encryptIMEmailAddress(
- const LLUUID& from_agent_id,
- const LLUUID& to_agent_id,
- U32 time,
- const U8* secret,
- size_t secret_size);
-};
-
-extern const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE;
-
-#endif
+/**
+ * @file llmail.h
+ * @brief smtp helper functions.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMAIL_H
+#define LL_LLMAIL_H
+
+typedef struct apr_pool_t apr_pool_t;
+
+#include "llsd.h"
+
+class LLMail
+{
+public:
+ // if hostname is NULL, then the host is resolved as 'mail'
+ static void init(const std::string& hostname, apr_pool_t* pool);
+
+ // Allow all email transmission to be disabled/enabled.
+ static void enable(bool mail_enabled);
+
+ /**
+ * @brief send an email
+ * @param from_name The name of the email sender
+ * @param from_address The email address for the sender
+ * @param to_name The name of the email recipient
+ * @param to_address The email recipient address
+ * @param subject The subject of the email
+ * @param headers optional X-Foo headers in an llsd map.
+ * @return Returns true if the call succeeds, false otherwise.
+ *
+ * Results in:
+ * From: "from_name" <from_address>
+ * To: "to_name" <to_address>
+ * Subject: subject
+ *
+ * message
+ */
+ static bool send(
+ const char* from_name,
+ const char* from_address,
+ const char* to_name,
+ const char* to_address,
+ const char* subject,
+ const char* message,
+ const LLSD& headers = LLSD());
+
+ /**
+ * @brief build the complete smtp transaction & header for use in an
+ * mail.
+ *
+ * @param from_name The name of the email sender
+ * @param from_address The email address for the sender
+ * @param to_name The name of the email recipient
+ * @param to_address The email recipient address
+ * @param subject The subject of the email
+ * @param headers optional X-Foo headers in an llsd map.
+ * @return Returns the complete SMTP transaction mail header.
+ */
+ static std::string buildSMTPTransaction(
+ const char* from_name,
+ const char* from_address,
+ const char* to_name,
+ const char* to_address,
+ const char* subject,
+ const LLSD& headers = LLSD());
+
+ /**
+ * @brief send an email with header and body.
+ *
+ * @param header The email header. Use build_mail_header().
+ * @param message The unescaped email message.
+ * @param from_address Used for debugging
+ * @param to_address Used for debugging
+ * @return Returns true if the message could be sent.
+ */
+ static bool send(
+ const std::string& header,
+ const std::string& message,
+ const char* from_address,
+ const char* to_address);
+
+ // IM-to-email sessions use a "session id" based on an encrypted
+ // combination of from agent_id, to agent_id, and timestamp. When
+ // a user replies to an email we use the from_id to determine the
+ // sender's name and the to_id to route the message. The address
+ // is encrypted to prevent users from building addresses to spoof
+ // IMs from other users. The timestamps allow the "sessions" to
+ // expire, in case one of the sessions is stolen/hijacked.
+ //
+ // indra/tools/mailglue is responsible for parsing the inbound mail.
+ //
+ // secret: binary blob passed to blowfish, max length 56 bytes
+ // secret_size: length of blob, in bytes
+ //
+ // Returns: "base64" encoded email local-part, with _ and - as the
+ // non-alphanumeric characters. This allows better compatibility
+ // with email systems than the default / and + extra chars. JC
+ static std::string encryptIMEmailAddress(
+ const LLUUID& from_agent_id,
+ const LLUUID& to_agent_id,
+ U32 time,
+ const U8* secret,
+ size_t secret_size);
+};
+
+extern const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE;
+
+#endif
diff --git a/indra/llmessage/llmessagebuilder.cpp b/indra/llmessage/llmessagebuilder.cpp
index e2ed968a57..2bac3bffee 100644
--- a/indra/llmessage/llmessagebuilder.cpp
+++ b/indra/llmessage/llmessagebuilder.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessagebuilder.cpp
* @brief LLMessageBuilder class implementation
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -31,6 +31,6 @@
//virtual
LLMessageBuilder::~LLMessageBuilder()
{
- // even abstract base classes need a concrete destructor
+ // even abstract base classes need a concrete destructor
}
diff --git a/indra/llmessage/llmessagebuilder.h b/indra/llmessage/llmessagebuilder.h
index 75bd5f5cc7..2acb47c238 100644
--- a/indra/llmessage/llmessagebuilder.h
+++ b/indra/llmessage/llmessagebuilder.h
@@ -1,101 +1,101 @@
-/**
- * @file llmessagebuilder.h
- * @brief Declaration of LLMessageBuilder class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMESSAGEBUILDER_H
-#define LL_LLMESSAGEBUILDER_H
-
-#include <string>
-
-#include "stdtypes.h"
-
-class LLMsgData;
-class LLQuaternion;
-class LLSD;
-class LLUUID;
-class LLVector3;
-class LLVector3d;
-class LLVector4;
-
-class LLMessageBuilder
-{
-public:
-
- //CLASS_LOG_TYPE(LLMessageBuilder);
-
- virtual ~LLMessageBuilder();
- virtual void newMessage(const char* name) = 0;
-
- virtual void nextBlock(const char* blockname) = 0;
- virtual bool removeLastBlock() = 0; // TODO: babbage: remove this horror
-
- /** All add* methods expect pointers to canonical strings. */
- virtual void addBinaryData(
- const char* varname,
- const void* data,
- S32 size) = 0;
- virtual void addBOOL(const char* varname, bool b) = 0;
- virtual void addS8(const char* varname, S8 s) = 0;
- virtual void addU8(const char* varname, U8 u) = 0;
- virtual void addS16(const char* varname, S16 i) = 0;
- virtual void addU16(const char* varname, U16 i) = 0;
- virtual void addF32(const char* varname, F32 f) = 0;
- virtual void addS32(const char* varname, S32 s) = 0;
- virtual void addU32(const char* varname, U32 u) = 0;
- virtual void addU64(const char* varname, U64 lu) = 0;
- virtual void addF64(const char* varname, F64 d) = 0;
- virtual void addVector3(const char* varname, const LLVector3& vec) = 0;
- virtual void addVector4(const char* varname, const LLVector4& vec) = 0;
- virtual void addVector3d(const char* varname, const LLVector3d& vec) = 0;
- virtual void addQuat(const char* varname, const LLQuaternion& quat) = 0;
- virtual void addUUID(const char* varname, const LLUUID& uuid) = 0;
- virtual void addIPAddr(const char* varname, const U32 ip) = 0;
- virtual void addIPPort(const char* varname, const U16 port) = 0;
- virtual void addString(const char* varname, const char* s) = 0;
- virtual void addString(const char* varname, const std::string& s) = 0;
-
- virtual bool isMessageFull(const char* blockname) const = 0;
- virtual void compressMessage(U8*& buf_ptr, U32& buffer_length) = 0;
- virtual S32 getMessageSize() = 0;
-
- virtual bool isBuilt() const = 0;
- virtual bool isClear() const = 0;
- virtual U32 buildMessage(
- U8* buffer,
- U32 buffer_size,
- U8 offset_to_data) = 0;
- /**< Return built message size */
- virtual void clearMessage() = 0;
-
- // TODO: babbage: remove this horror
- virtual void setBuilt(bool b) = 0;
-
- virtual const char* getMessageName() const = 0;
-
- virtual void copyFromMessageData(const LLMsgData& data) = 0;
- virtual void copyFromLLSD(const LLSD& data) = 0;
-};
-
-#endif // LL_LLMESSAGEBUILDER_H
+/**
+ * @file llmessagebuilder.h
+ * @brief Declaration of LLMessageBuilder class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMESSAGEBUILDER_H
+#define LL_LLMESSAGEBUILDER_H
+
+#include <string>
+
+#include "stdtypes.h"
+
+class LLMsgData;
+class LLQuaternion;
+class LLSD;
+class LLUUID;
+class LLVector3;
+class LLVector3d;
+class LLVector4;
+
+class LLMessageBuilder
+{
+public:
+
+ //CLASS_LOG_TYPE(LLMessageBuilder);
+
+ virtual ~LLMessageBuilder();
+ virtual void newMessage(const char* name) = 0;
+
+ virtual void nextBlock(const char* blockname) = 0;
+ virtual bool removeLastBlock() = 0; // TODO: babbage: remove this horror
+
+ /** All add* methods expect pointers to canonical strings. */
+ virtual void addBinaryData(
+ const char* varname,
+ const void* data,
+ S32 size) = 0;
+ virtual void addBOOL(const char* varname, bool b) = 0;
+ virtual void addS8(const char* varname, S8 s) = 0;
+ virtual void addU8(const char* varname, U8 u) = 0;
+ virtual void addS16(const char* varname, S16 i) = 0;
+ virtual void addU16(const char* varname, U16 i) = 0;
+ virtual void addF32(const char* varname, F32 f) = 0;
+ virtual void addS32(const char* varname, S32 s) = 0;
+ virtual void addU32(const char* varname, U32 u) = 0;
+ virtual void addU64(const char* varname, U64 lu) = 0;
+ virtual void addF64(const char* varname, F64 d) = 0;
+ virtual void addVector3(const char* varname, const LLVector3& vec) = 0;
+ virtual void addVector4(const char* varname, const LLVector4& vec) = 0;
+ virtual void addVector3d(const char* varname, const LLVector3d& vec) = 0;
+ virtual void addQuat(const char* varname, const LLQuaternion& quat) = 0;
+ virtual void addUUID(const char* varname, const LLUUID& uuid) = 0;
+ virtual void addIPAddr(const char* varname, const U32 ip) = 0;
+ virtual void addIPPort(const char* varname, const U16 port) = 0;
+ virtual void addString(const char* varname, const char* s) = 0;
+ virtual void addString(const char* varname, const std::string& s) = 0;
+
+ virtual bool isMessageFull(const char* blockname) const = 0;
+ virtual void compressMessage(U8*& buf_ptr, U32& buffer_length) = 0;
+ virtual S32 getMessageSize() = 0;
+
+ virtual bool isBuilt() const = 0;
+ virtual bool isClear() const = 0;
+ virtual U32 buildMessage(
+ U8* buffer,
+ U32 buffer_size,
+ U8 offset_to_data) = 0;
+ /**< Return built message size */
+ virtual void clearMessage() = 0;
+
+ // TODO: babbage: remove this horror
+ virtual void setBuilt(bool b) = 0;
+
+ virtual const char* getMessageName() const = 0;
+
+ virtual void copyFromMessageData(const LLMsgData& data) = 0;
+ virtual void copyFromLLSD(const LLSD& data) = 0;
+};
+
+#endif // LL_LLMESSAGEBUILDER_H
diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp
index 64e79d6767..e611688155 100644
--- a/indra/llmessage/llmessageconfig.cpp
+++ b/indra/llmessage/llmessageconfig.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessageconfig.cpp
* @brief Live file handling for messaging
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,107 +47,107 @@ static LLSD sMessages;
class LLMessageConfigFile : public LLLiveFile
{
public:
- LLMessageConfigFile() :
- LLLiveFile(filename(), messageConfigRefreshRate),
- mMaxQueuedEvents(0)
+ LLMessageConfigFile() :
+ LLLiveFile(filename(), messageConfigRefreshRate),
+ mMaxQueuedEvents(0)
{ }
- static std::string filename();
+ static std::string filename();
+
+ LLSD mMessages;
+ std::string mServerDefault;
- LLSD mMessages;
- std::string mServerDefault;
-
- static LLMessageConfigFile& instance();
- // return the singleton configuration file
+ static LLMessageConfigFile& instance();
+ // return the singleton configuration file
- /* virtual */ bool loadFile();
- void loadServerDefaults(const LLSD& data);
- void loadMaxQueuedEvents(const LLSD& data);
- void loadMessages(const LLSD& data);
- void loadCapBans(const LLSD& blacklist);
- void loadMessageBans(const LLSD& blacklist);
- bool isCapBanned(const std::string& cap_name) const;
+ /* virtual */ bool loadFile();
+ void loadServerDefaults(const LLSD& data);
+ void loadMaxQueuedEvents(const LLSD& data);
+ void loadMessages(const LLSD& data);
+ void loadCapBans(const LLSD& blacklist);
+ void loadMessageBans(const LLSD& blacklist);
+ bool isCapBanned(const std::string& cap_name) const;
public:
- LLSD mCapBans;
- S32 mMaxQueuedEvents;
+ LLSD mCapBans;
+ S32 mMaxQueuedEvents;
private:
- static const S32 DEFAULT_MAX_QUEUED_EVENTS = 100;
+ static const S32 DEFAULT_MAX_QUEUED_EVENTS = 100;
};
std::string LLMessageConfigFile::filename()
{
std::ostringstream ostr;
- ostr << sConfigDir//gAppSimp->getOption("configdir").asString()
- << "/" << messageConfigFileName;
- return ostr.str();
+ ostr << sConfigDir//gAppSimp->getOption("configdir").asString()
+ << "/" << messageConfigFileName;
+ return ostr.str();
}
LLMessageConfigFile& LLMessageConfigFile::instance()
{
- static LLMessageConfigFile the_file;
- the_file.checkAndReload();
- return the_file;
+ static LLMessageConfigFile the_file;
+ the_file.checkAndReload();
+ return the_file;
}
// virtual
bool LLMessageConfigFile::loadFile()
{
- LLSD data;
+ LLSD data;
{
llifstream file(filename().c_str());
-
+
if (file.is_open())
{
- LL_DEBUGS("AppInit") << "Loading message.xml file at " << filename() << LL_ENDL;
+ LL_DEBUGS("AppInit") << "Loading message.xml file at " << filename() << LL_ENDL;
LLSDSerialize::fromXML(data, file);
}
if (data.isUndefined())
{
LL_INFOS("AppInit") << "LLMessageConfigFile::loadFile: file missing,"
- " ill-formed, or simply undefined; not changing the"
- " file" << LL_ENDL;
+ " ill-formed, or simply undefined; not changing the"
+ " file" << LL_ENDL;
return false;
}
}
- loadServerDefaults(data);
- loadMaxQueuedEvents(data);
- loadMessages(data);
- loadCapBans(data);
- loadMessageBans(data);
- return true;
+ loadServerDefaults(data);
+ loadMaxQueuedEvents(data);
+ loadMessages(data);
+ loadCapBans(data);
+ loadMessageBans(data);
+ return true;
}
void LLMessageConfigFile::loadServerDefaults(const LLSD& data)
{
- mServerDefault = data["serverDefaults"][sServerName].asString();
+ mServerDefault = data["serverDefaults"][sServerName].asString();
}
void LLMessageConfigFile::loadMaxQueuedEvents(const LLSD& data)
{
- if (data.has("maxQueuedEvents"))
- {
- mMaxQueuedEvents = data["maxQueuedEvents"].asInteger();
- }
- else
- {
- mMaxQueuedEvents = DEFAULT_MAX_QUEUED_EVENTS;
- }
+ if (data.has("maxQueuedEvents"))
+ {
+ mMaxQueuedEvents = data["maxQueuedEvents"].asInteger();
+ }
+ else
+ {
+ mMaxQueuedEvents = DEFAULT_MAX_QUEUED_EVENTS;
+ }
}
void LLMessageConfigFile::loadMessages(const LLSD& data)
{
- mMessages = data["messages"];
+ mMessages = data["messages"];
#ifdef DEBUG
- std::ostringstream out;
- LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
- formatter->format(mMessages, out);
- LL_INFOS() << "loading ... " << out.str()
- << " LLMessageConfigFile::loadMessages loaded "
- << mMessages.size() << " messages" << LL_ENDL;
+ std::ostringstream out;
+ LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
+ formatter->format(mMessages, out);
+ LL_INFOS() << "loading ... " << out.str()
+ << " LLMessageConfigFile::loadMessages loaded "
+ << mMessages.size() << " messages" << LL_ENDL;
#endif
}
@@ -160,9 +160,9 @@ void LLMessageConfigFile::loadCapBans(const LLSD& data)
<< LL_ENDL;
return;
}
-
- mCapBans = bans;
-
+
+ mCapBans = bans;
+
LL_DEBUGS("AppInit") << "LLMessageConfigFile::loadCapBans: "
<< bans.size() << " ban tests" << LL_ENDL;
}
@@ -176,13 +176,13 @@ void LLMessageConfigFile::loadMessageBans(const LLSD& data)
<< LL_ENDL;
return;
}
-
- gMessageSystem->setMessageBans(bans["trusted"], bans["untrusted"]);
+
+ gMessageSystem->setMessageBans(bans["trusted"], bans["untrusted"]);
}
bool LLMessageConfigFile::isCapBanned(const std::string& cap_name) const
{
- LL_DEBUGS() << "mCapBans is " << LLSDNotationStreamer(mCapBans) << LL_ENDL;
+ LL_DEBUGS() << "mCapBans is " << LLSDNotationStreamer(mCapBans) << LL_ENDL;
return mCapBans[cap_name];
}
@@ -192,99 +192,99 @@ bool LLMessageConfigFile::isCapBanned(const std::string& cap_name) const
//static
void LLMessageConfig::initClass(const std::string& server_name,
- const std::string& config_dir)
+ const std::string& config_dir)
{
- sServerName = server_name;
- sConfigDir = config_dir;
- (void) LLMessageConfigFile::instance();
- LL_DEBUGS("AppInit") << "LLMessageConfig::initClass config file "
- << config_dir << "/" << messageConfigFileName << LL_ENDL;
+ sServerName = server_name;
+ sConfigDir = config_dir;
+ (void) LLMessageConfigFile::instance();
+ LL_DEBUGS("AppInit") << "LLMessageConfig::initClass config file "
+ << config_dir << "/" << messageConfigFileName << LL_ENDL;
}
//static
void LLMessageConfig::useConfig(const LLSD& config)
{
- LLMessageConfigFile &the_file = LLMessageConfigFile::instance();
- the_file.loadServerDefaults(config);
- the_file.loadMaxQueuedEvents(config);
- the_file.loadMessages(config);
- the_file.loadCapBans(config);
- the_file.loadMessageBans(config);
+ LLMessageConfigFile &the_file = LLMessageConfigFile::instance();
+ the_file.loadServerDefaults(config);
+ the_file.loadMaxQueuedEvents(config);
+ the_file.loadMessages(config);
+ the_file.loadCapBans(config);
+ the_file.loadMessageBans(config);
}
//static
LLMessageConfig::Flavor LLMessageConfig::getServerDefaultFlavor()
{
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- if (file.mServerDefault == "llsd")
- {
- return LLSD_FLAVOR;
- }
- if (file.mServerDefault == "template")
- {
- return TEMPLATE_FLAVOR;
- }
- return NO_FLAVOR;
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ if (file.mServerDefault == "llsd")
+ {
+ return LLSD_FLAVOR;
+ }
+ if (file.mServerDefault == "template")
+ {
+ return TEMPLATE_FLAVOR;
+ }
+ return NO_FLAVOR;
}
//static
S32 LLMessageConfig::getMaxQueuedEvents()
{
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- return file.mMaxQueuedEvents;
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ return file.mMaxQueuedEvents;
}
//static
LLMessageConfig::Flavor LLMessageConfig::getMessageFlavor(const std::string& msg_name)
{
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- LLSD config = file.mMessages[msg_name];
- if (config["flavor"].asString() == "llsd")
- {
- return LLSD_FLAVOR;
- }
- if (config["flavor"].asString() == "template")
- {
- return TEMPLATE_FLAVOR;
- }
- return NO_FLAVOR;
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ LLSD config = file.mMessages[msg_name];
+ if (config["flavor"].asString() == "llsd")
+ {
+ return LLSD_FLAVOR;
+ }
+ if (config["flavor"].asString() == "template")
+ {
+ return TEMPLATE_FLAVOR;
+ }
+ return NO_FLAVOR;
}
//static
LLMessageConfig::SenderTrust LLMessageConfig::getSenderTrustedness(
- const std::string& msg_name)
+ const std::string& msg_name)
{
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- LLSD config = file.mMessages[msg_name];
- if (config.has("trusted-sender"))
- {
- return config["trusted-sender"].asBoolean() ? TRUSTED : UNTRUSTED;
- }
- return NOT_SET;
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ LLSD config = file.mMessages[msg_name];
+ if (config.has("trusted-sender"))
+ {
+ return config["trusted-sender"].asBoolean() ? TRUSTED : UNTRUSTED;
+ }
+ return NOT_SET;
}
//static
bool LLMessageConfig::isValidMessage(const std::string& msg_name)
{
- if (sServerName.empty())
- {
- LL_ERRS() << "LLMessageConfig::initClass() not called" << LL_ENDL;
- }
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- return file.mMessages.has(msg_name);
+ if (sServerName.empty())
+ {
+ LL_ERRS() << "LLMessageConfig::initClass() not called" << LL_ENDL;
+ }
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ return file.mMessages.has(msg_name);
}
//static
bool LLMessageConfig::onlySendLatest(const std::string& msg_name)
{
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- LLSD config = file.mMessages[msg_name];
- return config["only-send-latest"].asBoolean();
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ LLSD config = file.mMessages[msg_name];
+ return config["only-send-latest"].asBoolean();
}
bool LLMessageConfig::isCapBanned(const std::string& cap_name)
{
- return LLMessageConfigFile::instance().isCapBanned(cap_name);
+ return LLMessageConfigFile::instance().isCapBanned(cap_name);
}
// return the web-service path to use for a given
@@ -292,13 +292,13 @@ bool LLMessageConfig::isCapBanned(const std::string& cap_name)
// in simulator.xml!
LLSD LLMessageConfig::getConfigForMessage(const std::string& msg_name)
{
- if (sServerName.empty())
- {
- LL_ERRS() << "LLMessageConfig::isMessageTrusted(name) before"
- << " LLMessageConfig::initClass()" << LL_ENDL;
- }
- LLMessageConfigFile& file = LLMessageConfigFile::instance();
- // LLSD for the CamelCase message name
- LLSD config = file.mMessages[msg_name];
- return config;
+ if (sServerName.empty())
+ {
+ LL_ERRS() << "LLMessageConfig::isMessageTrusted(name) before"
+ << " LLMessageConfig::initClass()" << LL_ENDL;
+ }
+ LLMessageConfigFile& file = LLMessageConfigFile::instance();
+ // LLSD for the CamelCase message name
+ LLSD config = file.mMessages[msg_name];
+ return config;
}
diff --git a/indra/llmessage/llmessageconfig.h b/indra/llmessage/llmessageconfig.h
index 1b39c386ca..ce308faa1b 100644
--- a/indra/llmessage/llmessageconfig.h
+++ b/indra/llmessage/llmessageconfig.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessageconfig.h
* @brief Live file handling for messaging
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,22 +35,22 @@ class LLSD;
class LLMessageConfig
{
public:
- enum Flavor { NO_FLAVOR=0, LLSD_FLAVOR=1, TEMPLATE_FLAVOR=2 };
- enum SenderTrust { NOT_SET=0, UNTRUSTED=1, TRUSTED=2 };
-
- static void initClass(const std::string& server_name,
- const std::string& config_dir);
- static void useConfig(const LLSD& config);
+ enum Flavor { NO_FLAVOR=0, LLSD_FLAVOR=1, TEMPLATE_FLAVOR=2 };
+ enum SenderTrust { NOT_SET=0, UNTRUSTED=1, TRUSTED=2 };
+
+ static void initClass(const std::string& server_name,
+ const std::string& config_dir);
+ static void useConfig(const LLSD& config);
- static Flavor getServerDefaultFlavor();
- static S32 getMaxQueuedEvents();
+ static Flavor getServerDefaultFlavor();
+ static S32 getMaxQueuedEvents();
- // For individual messages
- static Flavor getMessageFlavor(const std::string& msg_name);
- static SenderTrust getSenderTrustedness(const std::string& msg_name);
- static bool isValidMessage(const std::string& msg_name);
- static bool onlySendLatest(const std::string& msg_name);
- static bool isCapBanned(const std::string& cap_name);
- static LLSD getConfigForMessage(const std::string& msg_name);
+ // For individual messages
+ static Flavor getMessageFlavor(const std::string& msg_name);
+ static SenderTrust getSenderTrustedness(const std::string& msg_name);
+ static bool isValidMessage(const std::string& msg_name);
+ static bool onlySendLatest(const std::string& msg_name);
+ static bool isCapBanned(const std::string& cap_name);
+ static LLSD getConfigForMessage(const std::string& msg_name);
};
#endif // LL_MESSAGECONFIG_H
diff --git a/indra/llmessage/llmessagereader.cpp b/indra/llmessage/llmessagereader.cpp
index 4a6f5145b3..80c4379549 100644
--- a/indra/llmessage/llmessagereader.cpp
+++ b/indra/llmessage/llmessagereader.cpp
@@ -1,62 +1,62 @@
-/**
- * @file llmessagereader.cpp
- * @brief LLMessageReader class implementation
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llmessagereader.h"
-
-static bool sTimeDecodes = false;
-
-static F32 sTimeDecodesSpamThreshold = 0.05f;
-
-//virtual
-LLMessageReader::~LLMessageReader()
-{
- // even abstract base classes need a concrete destructor
-}
-
-//static
-void LLMessageReader::setTimeDecodes(bool b)
-{
- sTimeDecodes = b;
-}
-
-//static
-void LLMessageReader::setTimeDecodesSpamThreshold(F32 seconds)
-{
- sTimeDecodesSpamThreshold = seconds;
-}
-
-//static
-bool LLMessageReader::getTimeDecodes()
-{
- return sTimeDecodes;
-}
-
-//static
-F32 LLMessageReader::getTimeDecodesSpamThreshold()
-{
- return sTimeDecodesSpamThreshold;
-}
+/**
+ * @file llmessagereader.cpp
+ * @brief LLMessageReader class implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llmessagereader.h"
+
+static bool sTimeDecodes = false;
+
+static F32 sTimeDecodesSpamThreshold = 0.05f;
+
+//virtual
+LLMessageReader::~LLMessageReader()
+{
+ // even abstract base classes need a concrete destructor
+}
+
+//static
+void LLMessageReader::setTimeDecodes(bool b)
+{
+ sTimeDecodes = b;
+}
+
+//static
+void LLMessageReader::setTimeDecodesSpamThreshold(F32 seconds)
+{
+ sTimeDecodesSpamThreshold = seconds;
+}
+
+//static
+bool LLMessageReader::getTimeDecodes()
+{
+ return sTimeDecodes;
+}
+
+//static
+F32 LLMessageReader::getTimeDecodesSpamThreshold()
+{
+ return sTimeDecodesSpamThreshold;
+}
diff --git a/indra/llmessage/llmessagereader.h b/indra/llmessage/llmessagereader.h
index 2f64371f63..42d8906e16 100644
--- a/indra/llmessage/llmessagereader.h
+++ b/indra/llmessage/llmessagereader.h
@@ -1,94 +1,94 @@
-/**
- * @file llmessagereader.h
- * @brief Declaration of LLMessageReader class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMESSAGEREADER_H
-#define LL_LLMESSAGEREADER_H
-
-#include "stdtypes.h"
-
-class LLHost;
-class LLMessageBuilder;
-class LLMsgData;
-class LLQuaternion;
-class LLUUID;
-class LLVector3;
-class LLVector3d;
-class LLVector4;
-
-// Error return values for getSize() functions
-const S32 LL_BLOCK_NOT_IN_MESSAGE = -1;
-const S32 LL_VARIABLE_NOT_IN_BLOCK = -2;
-const S32 LL_MESSAGE_ERROR = -3;
-
-
-class LLMessageReader
-{
- public:
-
- virtual ~LLMessageReader();
-
- /** All get* methods expect pointers to canonical strings. */
- virtual void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) = 0;
- virtual void getBOOL(const char *block, const char *var, bool &data, S32 blocknum = 0) = 0;
- virtual void getS8(const char *block, const char *var, S8 &data, S32 blocknum = 0) = 0;
- virtual void getU8(const char *block, const char *var, U8 &data, S32 blocknum = 0) = 0;
- virtual void getS16(const char *block, const char *var, S16 &data, S32 blocknum = 0) = 0;
- virtual void getU16(const char *block, const char *var, U16 &data, S32 blocknum = 0) = 0;
- virtual void getS32(const char *block, const char *var, S32 &data, S32 blocknum = 0) = 0;
- virtual void getF32(const char *block, const char *var, F32 &data, S32 blocknum = 0) = 0;
- virtual void getU32(const char *block, const char *var, U32 &data, S32 blocknum = 0) = 0;
- virtual void getU64(const char *block, const char *var, U64 &data, S32 blocknum = 0) = 0;
- virtual void getF64(const char *block, const char *var, F64 &data, S32 blocknum = 0) = 0;
- virtual void getVector3(const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0) = 0;
- virtual void getVector4(const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0) = 0;
- virtual void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0) = 0;
- virtual void getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0) = 0;
- virtual void getUUID(const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0) = 0;
- virtual void getIPAddr(const char *block, const char *var, U32 &ip, S32 blocknum = 0) = 0;
- virtual void getIPPort(const char *block, const char *var, U16 &port, S32 blocknum = 0) = 0;
- virtual void getString(const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0) = 0;
- virtual void getString(const char *block, const char *var, std::string& outstr, S32 blocknum = 0) = 0;
-
- virtual S32 getNumberOfBlocks(const char *blockname) = 0;
- virtual S32 getSize(const char *blockname, const char *varname) = 0;
- virtual S32 getSize(const char *blockname, S32 blocknum, const char *varname) = 0;
-
- virtual void clearMessage() = 0;
-
- /** Returns pointer to canonical (prehashed) string. */
- virtual const char* getMessageName() const = 0;
- virtual S32 getMessageSize() const = 0;
-
- virtual void copyToBuilder(LLMessageBuilder&) const = 0;
-
-
- static void setTimeDecodes(bool b);
- static bool getTimeDecodes();
- static void setTimeDecodesSpamThreshold(F32 seconds);
- static F32 getTimeDecodesSpamThreshold();
-};
-
-#endif // LL_LLMESSAGEREADER_H
+/**
+ * @file llmessagereader.h
+ * @brief Declaration of LLMessageReader class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMESSAGEREADER_H
+#define LL_LLMESSAGEREADER_H
+
+#include "stdtypes.h"
+
+class LLHost;
+class LLMessageBuilder;
+class LLMsgData;
+class LLQuaternion;
+class LLUUID;
+class LLVector3;
+class LLVector3d;
+class LLVector4;
+
+// Error return values for getSize() functions
+const S32 LL_BLOCK_NOT_IN_MESSAGE = -1;
+const S32 LL_VARIABLE_NOT_IN_BLOCK = -2;
+const S32 LL_MESSAGE_ERROR = -3;
+
+
+class LLMessageReader
+{
+ public:
+
+ virtual ~LLMessageReader();
+
+ /** All get* methods expect pointers to canonical strings. */
+ virtual void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX) = 0;
+ virtual void getBOOL(const char *block, const char *var, bool &data, S32 blocknum = 0) = 0;
+ virtual void getS8(const char *block, const char *var, S8 &data, S32 blocknum = 0) = 0;
+ virtual void getU8(const char *block, const char *var, U8 &data, S32 blocknum = 0) = 0;
+ virtual void getS16(const char *block, const char *var, S16 &data, S32 blocknum = 0) = 0;
+ virtual void getU16(const char *block, const char *var, U16 &data, S32 blocknum = 0) = 0;
+ virtual void getS32(const char *block, const char *var, S32 &data, S32 blocknum = 0) = 0;
+ virtual void getF32(const char *block, const char *var, F32 &data, S32 blocknum = 0) = 0;
+ virtual void getU32(const char *block, const char *var, U32 &data, S32 blocknum = 0) = 0;
+ virtual void getU64(const char *block, const char *var, U64 &data, S32 blocknum = 0) = 0;
+ virtual void getF64(const char *block, const char *var, F64 &data, S32 blocknum = 0) = 0;
+ virtual void getVector3(const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0) = 0;
+ virtual void getVector4(const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0) = 0;
+ virtual void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0) = 0;
+ virtual void getQuat(const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0) = 0;
+ virtual void getUUID(const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0) = 0;
+ virtual void getIPAddr(const char *block, const char *var, U32 &ip, S32 blocknum = 0) = 0;
+ virtual void getIPPort(const char *block, const char *var, U16 &port, S32 blocknum = 0) = 0;
+ virtual void getString(const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0) = 0;
+ virtual void getString(const char *block, const char *var, std::string& outstr, S32 blocknum = 0) = 0;
+
+ virtual S32 getNumberOfBlocks(const char *blockname) = 0;
+ virtual S32 getSize(const char *blockname, const char *varname) = 0;
+ virtual S32 getSize(const char *blockname, S32 blocknum, const char *varname) = 0;
+
+ virtual void clearMessage() = 0;
+
+ /** Returns pointer to canonical (prehashed) string. */
+ virtual const char* getMessageName() const = 0;
+ virtual S32 getMessageSize() const = 0;
+
+ virtual void copyToBuilder(LLMessageBuilder&) const = 0;
+
+
+ static void setTimeDecodes(bool b);
+ static bool getTimeDecodes();
+ static void setTimeDecodesSpamThreshold(F32 seconds);
+ static F32 getTimeDecodesSpamThreshold();
+};
+
+#endif // LL_LLMESSAGEREADER_H
diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h
index ac0f9f7edb..51f03841c3 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessagesenderinterface.h
- * @brief
+ * @brief
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,8 +35,8 @@ class LLSD;
class LLMessageSenderInterface
{
public:
- virtual ~LLMessageSenderInterface() {}
- virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message) = 0;
+ virtual ~LLMessageSenderInterface() {}
+ virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message) = 0;
};
diff --git a/indra/llmessage/llmessagetemplate.cpp b/indra/llmessage/llmessagetemplate.cpp
index e70e259436..8d2c1bf87a 100644
--- a/indra/llmessage/llmessagetemplate.cpp
+++ b/indra/llmessage/llmessagetemplate.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessagetemplate.cpp
* @brief Implementation of message template classes.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,161 +32,161 @@
void LLMsgVarData::addData(const void *data, S32 size, EMsgVariableType type, S32 data_size)
{
- mSize = size;
- mDataSize = data_size;
- if ( (type != MVT_VARIABLE) && (type != MVT_FIXED)
- && (mType != MVT_VARIABLE) && (mType != MVT_FIXED))
- {
- if (mType != type)
- {
- LL_WARNS() << "Type mismatch in LLMsgVarData::addData for " << mName
- << LL_ENDL;
- }
- }
- if(size)
- {
- delete[] mData; // Delete it if it already exists
- mData = new U8[size];
- htolememcpy(mData, data, mType, size);
- }
+ mSize = size;
+ mDataSize = data_size;
+ if ( (type != MVT_VARIABLE) && (type != MVT_FIXED)
+ && (mType != MVT_VARIABLE) && (mType != MVT_FIXED))
+ {
+ if (mType != type)
+ {
+ LL_WARNS() << "Type mismatch in LLMsgVarData::addData for " << mName
+ << LL_ENDL;
+ }
+ }
+ if(size)
+ {
+ delete[] mData; // Delete it if it already exists
+ mData = new U8[size];
+ htolememcpy(mData, data, mType, size);
+ }
}
void LLMsgData::addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size)
{
- // remember that if the blocknumber is > 0 then the number is appended to the name
- char *namep = (char *)blockname;
- LLMsgBlkData* block_data = mMemberBlocks[namep];
- if (block_data->mBlockNumber)
- {
- namep += block_data->mBlockNumber;
- block_data->addData(varname, data, size, type, data_size);
- }
- else
- {
- block_data->addData(varname, data, size, type, data_size);
- }
+ // remember that if the blocknumber is > 0 then the number is appended to the name
+ char *namep = (char *)blockname;
+ LLMsgBlkData* block_data = mMemberBlocks[namep];
+ if (block_data->mBlockNumber)
+ {
+ namep += block_data->mBlockNumber;
+ block_data->addData(varname, data, size, type, data_size);
+ }
+ else
+ {
+ block_data->addData(varname, data, size, type, data_size);
+ }
}
// LLMessageVariable functions and friends
std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg)
{
- s << "\t\t" << msg.mName << " (";
- switch (msg.mType)
- {
- case MVT_FIXED:
- s << "Fixed, " << msg.mSize << " bytes total)\n";
- break;
- case MVT_VARIABLE:
- s << "Variable, " << msg.mSize << " bytes of size info)\n";
- break;
- default:
- s << "Unknown\n";
- break;
- }
- return s;
+ s << "\t\t" << msg.mName << " (";
+ switch (msg.mType)
+ {
+ case MVT_FIXED:
+ s << "Fixed, " << msg.mSize << " bytes total)\n";
+ break;
+ case MVT_VARIABLE:
+ s << "Variable, " << msg.mSize << " bytes of size info)\n";
+ break;
+ default:
+ s << "Unknown\n";
+ break;
+ }
+ return s;
}
// LLMessageBlock functions and friends
std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg)
{
- s << "\t" << msg.mName << " (";
- switch (msg.mType)
- {
- case MBT_SINGLE:
- s << "Fixed";
- break;
- case MBT_MULTIPLE:
- s << "Multiple - " << msg.mNumber << " copies";
- break;
- case MBT_VARIABLE:
- s << "Variable";
- break;
- default:
- s << "Unknown";
- break;
- }
- if (msg.mTotalSize != -1)
- {
- s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n";
- }
- else
- {
- s << ")\n";
- }
-
-
- for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin();
- iter != msg.mMemberVariables.end(); iter++)
- {
- LLMessageVariable& ci = *(*iter);
- s << ci;
- }
-
- return s;
+ s << "\t" << msg.mName << " (";
+ switch (msg.mType)
+ {
+ case MBT_SINGLE:
+ s << "Fixed";
+ break;
+ case MBT_MULTIPLE:
+ s << "Multiple - " << msg.mNumber << " copies";
+ break;
+ case MBT_VARIABLE:
+ s << "Variable";
+ break;
+ default:
+ s << "Unknown";
+ break;
+ }
+ if (msg.mTotalSize != -1)
+ {
+ s << ", " << msg.mTotalSize << " bytes each, " << msg.mNumber*msg.mTotalSize << " bytes total)\n";
+ }
+ else
+ {
+ s << ")\n";
+ }
+
+
+ for (LLMessageBlock::message_variable_map_t::iterator iter = msg.mMemberVariables.begin();
+ iter != msg.mMemberVariables.end(); iter++)
+ {
+ LLMessageVariable& ci = *(*iter);
+ s << ci;
+ }
+
+ return s;
}
// LLMessageTemplate functions and friends
std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg)
{
- switch (msg.mFrequency)
- {
- case MFT_HIGH:
- s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " (";
- s << "High";
- break;
- case MFT_MEDIUM:
- s << "========================================\n" << "Message #";
- s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " (";
- s << "Medium";
- break;
- case MFT_LOW:
- s << "========================================\n" << "Message #";
- s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " (";
- s << "Low";
- break;
- default:
- s << "Unknown";
- break;
- }
-
- if (msg.mTotalSize != -1)
- {
- s << ", " << msg.mTotalSize << " bytes total)\n";
- }
- else
- {
- s << ")\n";
- }
-
- for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin();
- iter != msg.mMemberBlocks.end(); iter++)
- {
- LLMessageBlock* ci = *iter;
- s << *ci;
- }
-
- return s;
+ switch (msg.mFrequency)
+ {
+ case MFT_HIGH:
+ s << "========================================\n" << "Message #" << msg.mMessageNumber << "\n" << msg.mName << " (";
+ s << "High";
+ break;
+ case MFT_MEDIUM:
+ s << "========================================\n" << "Message #";
+ s << (msg.mMessageNumber & 0xFF) << "\n" << msg.mName << " (";
+ s << "Medium";
+ break;
+ case MFT_LOW:
+ s << "========================================\n" << "Message #";
+ s << (msg.mMessageNumber & 0xFFFF) << "\n" << msg.mName << " (";
+ s << "Low";
+ break;
+ default:
+ s << "Unknown";
+ break;
+ }
+
+ if (msg.mTotalSize != -1)
+ {
+ s << ", " << msg.mTotalSize << " bytes total)\n";
+ }
+ else
+ {
+ s << ")\n";
+ }
+
+ for (LLMessageTemplate::message_block_map_t::iterator iter = msg.mMemberBlocks.begin();
+ iter != msg.mMemberBlocks.end(); iter++)
+ {
+ LLMessageBlock* ci = *iter;
+ s << *ci;
+ }
+
+ return s;
}
void LLMessageTemplate::banUdp()
{
- static const char* deprecation[] = {
- "NotDeprecated",
- "Deprecated",
- "UDPDeprecated",
- "UDPBlackListed"
- };
- if (mDeprecation != MD_DEPRECATED)
- {
- LL_INFOS() << "Setting " << mName << " to UDPBlackListed was " << deprecation[mDeprecation] << LL_ENDL;
- mDeprecation = MD_UDPBLACKLISTED;
- }
- else
- {
- LL_INFOS() << mName << " is already more deprecated than UDPBlackListed" << LL_ENDL;
- }
+ static const char* deprecation[] = {
+ "NotDeprecated",
+ "Deprecated",
+ "UDPDeprecated",
+ "UDPBlackListed"
+ };
+ if (mDeprecation != MD_DEPRECATED)
+ {
+ LL_INFOS() << "Setting " << mName << " to UDPBlackListed was " << deprecation[mDeprecation] << LL_ENDL;
+ mDeprecation = MD_UDPBLACKLISTED;
+ }
+ else
+ {
+ LL_INFOS() << mName << " is already more deprecated than UDPBlackListed" << LL_ENDL;
+ }
}
diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h
index 41aca4ab91..454bae7238 100644
--- a/indra/llmessage/llmessagetemplate.h
+++ b/indra/llmessage/llmessagetemplate.h
@@ -1,421 +1,421 @@
-/**
- * @file llmessagetemplate.h
- * @brief Declaration of the message template classes.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMESSAGETEMPLATE_H
-#define LL_LLMESSAGETEMPLATE_H
-
-#include "message.h" // TODO: babbage: Remove...
-#include "llstl.h"
-#include "llindexedvector.h"
-
-class LLMsgVarData
-{
-public:
- LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8)
- {
- }
-
- LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type)
- {
- mName = (char *)name;
- }
-
- ~LLMsgVarData()
- {
- // copy constructor just copies the mData pointer, so only delete mData explicitly
- }
-
- void deleteData()
- {
- delete[] mData;
- mData = NULL;
- }
-
- void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1);
-
- char *getName() const { return mName; }
- S32 getSize() const { return mSize; }
- void *getData() { return (void*)mData; }
- const void *getData() const { return (const void*)mData; }
- S32 getDataSize() const { return mDataSize; }
- EMsgVariableType getType() const { return mType; }
-
-protected:
- char *mName;
- S32 mSize;
- S32 mDataSize;
-
- U8 *mData;
- EMsgVariableType mType;
-};
-
-class LLMsgBlkData
-{
-public:
- LLMsgBlkData(const char *name, S32 blocknum) : mBlockNumber(blocknum), mTotalSize(-1)
- {
- mName = (char *)name;
- }
-
- ~LLMsgBlkData()
- {
- for (msg_var_data_map_t::iterator iter = mMemberVarData.begin();
- iter != mMemberVarData.end(); iter++)
- {
- iter->deleteData();
- }
- }
-
- void addVariable(const char *name, EMsgVariableType type)
- {
- LLMsgVarData tmp(name,type);
- mMemberVarData[name] = tmp;
- }
-
- void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1)
- {
- LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist
- temp->addData(data, size, type, data_size);
- }
-
- S32 mBlockNumber;
- typedef LLIndexedVector<LLMsgVarData, const char *, 8> msg_var_data_map_t;
- msg_var_data_map_t mMemberVarData;
- char *mName;
- S32 mTotalSize;
-};
-
-class LLMsgData
-{
-public:
- LLMsgData(const char *name) : mTotalSize(-1)
- {
- mName = (char *)name;
- }
- ~LLMsgData()
- {
- for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
- mMemberBlocks.clear();
- }
-
- void addBlock(LLMsgBlkData *blockp)
- {
- mMemberBlocks[blockp->mName] = blockp;
- }
-
- void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1);
-
-public:
- typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t;
- msg_blk_data_map_t mMemberBlocks;
- char *mName;
- S32 mTotalSize;
-};
-
-// LLMessage* classes store the template of messages
-class LLMessageVariable
-{
-public:
- LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1)
- {
- }
-
- LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1)
- {
- mName = name;
- }
-
- LLMessageVariable(const char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size)
- {
- mName = LLMessageStringTable::getInstance()->getString(name);
- }
-
- ~LLMessageVariable() {}
-
- friend std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg);
-
- EMsgVariableType getType() const { return mType; }
- S32 getSize() const { return mSize; }
- char *getName() const { return mName; }
-protected:
- char *mName;
- EMsgVariableType mType;
- S32 mSize;
-};
-
-
-typedef enum e_message_block_type
-{
- MBT_NULL,
- MBT_SINGLE,
- MBT_MULTIPLE,
- MBT_VARIABLE,
- MBT_EOF
-} EMsgBlockType;
-
-class LLMessageBlock
-{
-public:
- LLMessageBlock(const char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0)
- {
- mName = LLMessageStringTable::getInstance()->getString(name);
- }
-
- ~LLMessageBlock()
- {
- for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePointer());
- }
-
- void addVariable(char *name, const EMsgVariableType type, const S32 size)
- {
- LLMessageVariable** varp = &mMemberVariables[name];
- if (*varp != NULL)
- {
- LL_ERRS() << name << " has already been used as a variable name!" << LL_ENDL;
- }
- *varp = new LLMessageVariable(name, type, size);
- if (((*varp)->getType() != MVT_VARIABLE)
- &&(mTotalSize != -1))
- {
- mTotalSize += (*varp)->getSize();
- }
- else
- {
- mTotalSize = -1;
- }
- }
-
- EMsgVariableType getVariableType(char *name)
- {
- return (mMemberVariables[name])->getType();
- }
-
- S32 getVariableSize(char *name)
- {
- return (mMemberVariables[name])->getSize();
- }
-
- const LLMessageVariable* getVariable(char* name) const
- {
- message_variable_map_t::const_iterator iter = mMemberVariables.find(name);
- return iter != mMemberVariables.end()? *iter : NULL;
- }
-
- friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg);
-
- typedef LLIndexedVector<LLMessageVariable*, const char *, 8> message_variable_map_t;
- message_variable_map_t mMemberVariables;
- char *mName;
- EMsgBlockType mType;
- S32 mNumber;
- S32 mTotalSize;
-};
-
-
-enum EMsgFrequency
-{
- MFT_NULL = 0, // value is size of message number in bytes
- MFT_HIGH = 1,
- MFT_MEDIUM = 2,
- MFT_LOW = 4
-};
-
-typedef enum e_message_trust
-{
- MT_TRUST,
- MT_NOTRUST
-} EMsgTrust;
-
-enum EMsgEncoding
-{
- ME_UNENCODED,
- ME_ZEROCODED
-};
-
-enum EMsgDeprecation
-{
- MD_NOTDEPRECATED,
- MD_UDPDEPRECATED,
- MD_UDPBLACKLISTED,
- MD_DEPRECATED
-};
-
-
-class LLMessageTemplate
-{
-public:
- LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq)
- :
- //mMemberBlocks(),
- mName(NULL),
- mFrequency(freq),
- mTrust(MT_NOTRUST),
- mEncoding(ME_ZEROCODED),
- mDeprecation(MD_NOTDEPRECATED),
- mMessageNumber(message_number),
- mTotalSize(0),
- mReceiveCount(0),
- mReceiveBytes(0),
- mReceiveInvalid(0),
- mDecodeTimeThisFrame(0.f),
- mTotalDecoded(0),
- mTotalDecodeTime(0.f),
- mMaxDecodeTimePerMsg(0.f),
- mBanFromTrusted(false),
- mBanFromUntrusted(false),
- mHandlerFunc(NULL),
- mUserData(NULL)
- {
- mName = LLMessageStringTable::getInstance()->getString(name);
- }
-
- ~LLMessageTemplate()
- {
- for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePointer());
- }
-
- void addBlock(LLMessageBlock *blockp)
- {
- LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName];
- if (*member_blockp != NULL)
- {
- LL_ERRS() << "Block " << blockp->mName
- << "has already been used as a block name!" << LL_ENDL;
- }
- *member_blockp = blockp;
- if ( (mTotalSize != -1)
- &&(blockp->mTotalSize != -1)
- &&( (blockp->mType == MBT_SINGLE)
- ||(blockp->mType == MBT_MULTIPLE)))
- {
- mTotalSize += blockp->mNumber*blockp->mTotalSize;
- }
- else
- {
- mTotalSize = -1;
- }
- }
-
- LLMessageBlock *getBlock(char *name)
- {
- return mMemberBlocks[name];
- }
-
- // Trusted messages can only be recieved on trusted circuits.
- void setTrust(EMsgTrust t)
- {
- mTrust = t;
- }
-
- EMsgTrust getTrust(void) const
- {
- return mTrust;
- }
-
- // controls for how the message should be encoded
- void setEncoding(EMsgEncoding e)
- {
- mEncoding = e;
- }
- EMsgEncoding getEncoding() const
- {
- return mEncoding;
- }
-
- void setDeprecation(EMsgDeprecation d)
- {
- mDeprecation = d;
- }
-
- EMsgDeprecation getDeprecation() const
- {
- return mDeprecation;
- }
-
- void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
- {
- mHandlerFunc = handler_func;
- mUserData = user_data;
- }
-
- bool callHandlerFunc(LLMessageSystem *msgsystem) const
- {
- if (mHandlerFunc)
- {
- mHandlerFunc(msgsystem, mUserData);
- return true;
- }
- return false;
- }
-
- bool isUdpBanned() const
- {
- return mDeprecation == MD_UDPBLACKLISTED;
- }
-
- void banUdp();
-
- bool isBanned(bool trustedSource) const
- {
- return trustedSource ? mBanFromTrusted : mBanFromUntrusted;
- }
-
- friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg);
-
- const LLMessageBlock* getBlock(char* name) const
- {
- message_block_map_t::const_iterator iter = mMemberBlocks.find(name);
- return iter != mMemberBlocks.end()? *iter : NULL;
- }
-
-public:
- typedef LLIndexedVector<LLMessageBlock*, char*, 8> message_block_map_t;
- message_block_map_t mMemberBlocks;
- char *mName;
- EMsgFrequency mFrequency;
- EMsgTrust mTrust;
- EMsgEncoding mEncoding;
- EMsgDeprecation mDeprecation;
- U32 mMessageNumber;
- S32 mTotalSize;
- U32 mReceiveCount; // how many of this template have been received since last reset
- U32 mReceiveBytes; // How many bytes received
- U32 mReceiveInvalid; // How many "invalid" packets
- F32 mDecodeTimeThisFrame; // Total seconds spent decoding this frame
- U32 mTotalDecoded; // Total messages successfully decoded
- F32 mTotalDecodeTime; // Total time successfully decoding messages
- F32 mMaxDecodeTimePerMsg;
-
- bool mBanFromTrusted;
- bool mBanFromUntrusted;
-
-private:
- // message handler function (this is set by each application)
- void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
- void **mUserData;
-};
-
-#endif // LL_LLMESSAGETEMPLATE_H
+/**
+ * @file llmessagetemplate.h
+ * @brief Declaration of the message template classes.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMESSAGETEMPLATE_H
+#define LL_LLMESSAGETEMPLATE_H
+
+#include "message.h" // TODO: babbage: Remove...
+#include "llstl.h"
+#include "llindexedvector.h"
+
+class LLMsgVarData
+{
+public:
+ LLMsgVarData() : mName(NULL), mSize(-1), mDataSize(-1), mData(NULL), mType(MVT_U8)
+ {
+ }
+
+ LLMsgVarData(const char *name, EMsgVariableType type) : mSize(-1), mDataSize(-1), mData(NULL), mType(type)
+ {
+ mName = (char *)name;
+ }
+
+ ~LLMsgVarData()
+ {
+ // copy constructor just copies the mData pointer, so only delete mData explicitly
+ }
+
+ void deleteData()
+ {
+ delete[] mData;
+ mData = NULL;
+ }
+
+ void addData(const void *indata, S32 size, EMsgVariableType type, S32 data_size = -1);
+
+ char *getName() const { return mName; }
+ S32 getSize() const { return mSize; }
+ void *getData() { return (void*)mData; }
+ const void *getData() const { return (const void*)mData; }
+ S32 getDataSize() const { return mDataSize; }
+ EMsgVariableType getType() const { return mType; }
+
+protected:
+ char *mName;
+ S32 mSize;
+ S32 mDataSize;
+
+ U8 *mData;
+ EMsgVariableType mType;
+};
+
+class LLMsgBlkData
+{
+public:
+ LLMsgBlkData(const char *name, S32 blocknum) : mBlockNumber(blocknum), mTotalSize(-1)
+ {
+ mName = (char *)name;
+ }
+
+ ~LLMsgBlkData()
+ {
+ for (msg_var_data_map_t::iterator iter = mMemberVarData.begin();
+ iter != mMemberVarData.end(); iter++)
+ {
+ iter->deleteData();
+ }
+ }
+
+ void addVariable(const char *name, EMsgVariableType type)
+ {
+ LLMsgVarData tmp(name,type);
+ mMemberVarData[name] = tmp;
+ }
+
+ void addData(char *name, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1)
+ {
+ LLMsgVarData* temp = &mMemberVarData[name]; // creates a new entry if one doesn't exist
+ temp->addData(data, size, type, data_size);
+ }
+
+ S32 mBlockNumber;
+ typedef LLIndexedVector<LLMsgVarData, const char *, 8> msg_var_data_map_t;
+ msg_var_data_map_t mMemberVarData;
+ char *mName;
+ S32 mTotalSize;
+};
+
+class LLMsgData
+{
+public:
+ LLMsgData(const char *name) : mTotalSize(-1)
+ {
+ mName = (char *)name;
+ }
+ ~LLMsgData()
+ {
+ for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePairedPointer());
+ mMemberBlocks.clear();
+ }
+
+ void addBlock(LLMsgBlkData *blockp)
+ {
+ mMemberBlocks[blockp->mName] = blockp;
+ }
+
+ void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1);
+
+public:
+ typedef std::map<char*, LLMsgBlkData*> msg_blk_data_map_t;
+ msg_blk_data_map_t mMemberBlocks;
+ char *mName;
+ S32 mTotalSize;
+};
+
+// LLMessage* classes store the template of messages
+class LLMessageVariable
+{
+public:
+ LLMessageVariable() : mName(NULL), mType(MVT_NULL), mSize(-1)
+ {
+ }
+
+ LLMessageVariable(char *name) : mType(MVT_NULL), mSize(-1)
+ {
+ mName = name;
+ }
+
+ LLMessageVariable(const char *name, const EMsgVariableType type, const S32 size) : mType(type), mSize(size)
+ {
+ mName = LLMessageStringTable::getInstance()->getString(name);
+ }
+
+ ~LLMessageVariable() {}
+
+ friend std::ostream& operator<<(std::ostream& s, LLMessageVariable &msg);
+
+ EMsgVariableType getType() const { return mType; }
+ S32 getSize() const { return mSize; }
+ char *getName() const { return mName; }
+protected:
+ char *mName;
+ EMsgVariableType mType;
+ S32 mSize;
+};
+
+
+typedef enum e_message_block_type
+{
+ MBT_NULL,
+ MBT_SINGLE,
+ MBT_MULTIPLE,
+ MBT_VARIABLE,
+ MBT_EOF
+} EMsgBlockType;
+
+class LLMessageBlock
+{
+public:
+ LLMessageBlock(const char *name, EMsgBlockType type, S32 number = 1) : mType(type), mNumber(number), mTotalSize(0)
+ {
+ mName = LLMessageStringTable::getInstance()->getString(name);
+ }
+
+ ~LLMessageBlock()
+ {
+ for_each(mMemberVariables.begin(), mMemberVariables.end(), DeletePointer());
+ }
+
+ void addVariable(char *name, const EMsgVariableType type, const S32 size)
+ {
+ LLMessageVariable** varp = &mMemberVariables[name];
+ if (*varp != NULL)
+ {
+ LL_ERRS() << name << " has already been used as a variable name!" << LL_ENDL;
+ }
+ *varp = new LLMessageVariable(name, type, size);
+ if (((*varp)->getType() != MVT_VARIABLE)
+ &&(mTotalSize != -1))
+ {
+ mTotalSize += (*varp)->getSize();
+ }
+ else
+ {
+ mTotalSize = -1;
+ }
+ }
+
+ EMsgVariableType getVariableType(char *name)
+ {
+ return (mMemberVariables[name])->getType();
+ }
+
+ S32 getVariableSize(char *name)
+ {
+ return (mMemberVariables[name])->getSize();
+ }
+
+ const LLMessageVariable* getVariable(char* name) const
+ {
+ message_variable_map_t::const_iterator iter = mMemberVariables.find(name);
+ return iter != mMemberVariables.end()? *iter : NULL;
+ }
+
+ friend std::ostream& operator<<(std::ostream& s, LLMessageBlock &msg);
+
+ typedef LLIndexedVector<LLMessageVariable*, const char *, 8> message_variable_map_t;
+ message_variable_map_t mMemberVariables;
+ char *mName;
+ EMsgBlockType mType;
+ S32 mNumber;
+ S32 mTotalSize;
+};
+
+
+enum EMsgFrequency
+{
+ MFT_NULL = 0, // value is size of message number in bytes
+ MFT_HIGH = 1,
+ MFT_MEDIUM = 2,
+ MFT_LOW = 4
+};
+
+typedef enum e_message_trust
+{
+ MT_TRUST,
+ MT_NOTRUST
+} EMsgTrust;
+
+enum EMsgEncoding
+{
+ ME_UNENCODED,
+ ME_ZEROCODED
+};
+
+enum EMsgDeprecation
+{
+ MD_NOTDEPRECATED,
+ MD_UDPDEPRECATED,
+ MD_UDPBLACKLISTED,
+ MD_DEPRECATED
+};
+
+
+class LLMessageTemplate
+{
+public:
+ LLMessageTemplate(const char *name, U32 message_number, EMsgFrequency freq)
+ :
+ //mMemberBlocks(),
+ mName(NULL),
+ mFrequency(freq),
+ mTrust(MT_NOTRUST),
+ mEncoding(ME_ZEROCODED),
+ mDeprecation(MD_NOTDEPRECATED),
+ mMessageNumber(message_number),
+ mTotalSize(0),
+ mReceiveCount(0),
+ mReceiveBytes(0),
+ mReceiveInvalid(0),
+ mDecodeTimeThisFrame(0.f),
+ mTotalDecoded(0),
+ mTotalDecodeTime(0.f),
+ mMaxDecodeTimePerMsg(0.f),
+ mBanFromTrusted(false),
+ mBanFromUntrusted(false),
+ mHandlerFunc(NULL),
+ mUserData(NULL)
+ {
+ mName = LLMessageStringTable::getInstance()->getString(name);
+ }
+
+ ~LLMessageTemplate()
+ {
+ for_each(mMemberBlocks.begin(), mMemberBlocks.end(), DeletePointer());
+ }
+
+ void addBlock(LLMessageBlock *blockp)
+ {
+ LLMessageBlock** member_blockp = &mMemberBlocks[blockp->mName];
+ if (*member_blockp != NULL)
+ {
+ LL_ERRS() << "Block " << blockp->mName
+ << "has already been used as a block name!" << LL_ENDL;
+ }
+ *member_blockp = blockp;
+ if ( (mTotalSize != -1)
+ &&(blockp->mTotalSize != -1)
+ &&( (blockp->mType == MBT_SINGLE)
+ ||(blockp->mType == MBT_MULTIPLE)))
+ {
+ mTotalSize += blockp->mNumber*blockp->mTotalSize;
+ }
+ else
+ {
+ mTotalSize = -1;
+ }
+ }
+
+ LLMessageBlock *getBlock(char *name)
+ {
+ return mMemberBlocks[name];
+ }
+
+ // Trusted messages can only be recieved on trusted circuits.
+ void setTrust(EMsgTrust t)
+ {
+ mTrust = t;
+ }
+
+ EMsgTrust getTrust(void) const
+ {
+ return mTrust;
+ }
+
+ // controls for how the message should be encoded
+ void setEncoding(EMsgEncoding e)
+ {
+ mEncoding = e;
+ }
+ EMsgEncoding getEncoding() const
+ {
+ return mEncoding;
+ }
+
+ void setDeprecation(EMsgDeprecation d)
+ {
+ mDeprecation = d;
+ }
+
+ EMsgDeprecation getDeprecation() const
+ {
+ return mDeprecation;
+ }
+
+ void setHandlerFunc(void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
+ {
+ mHandlerFunc = handler_func;
+ mUserData = user_data;
+ }
+
+ bool callHandlerFunc(LLMessageSystem *msgsystem) const
+ {
+ if (mHandlerFunc)
+ {
+ mHandlerFunc(msgsystem, mUserData);
+ return true;
+ }
+ return false;
+ }
+
+ bool isUdpBanned() const
+ {
+ return mDeprecation == MD_UDPBLACKLISTED;
+ }
+
+ void banUdp();
+
+ bool isBanned(bool trustedSource) const
+ {
+ return trustedSource ? mBanFromTrusted : mBanFromUntrusted;
+ }
+
+ friend std::ostream& operator<<(std::ostream& s, LLMessageTemplate &msg);
+
+ const LLMessageBlock* getBlock(char* name) const
+ {
+ message_block_map_t::const_iterator iter = mMemberBlocks.find(name);
+ return iter != mMemberBlocks.end()? *iter : NULL;
+ }
+
+public:
+ typedef LLIndexedVector<LLMessageBlock*, char*, 8> message_block_map_t;
+ message_block_map_t mMemberBlocks;
+ char *mName;
+ EMsgFrequency mFrequency;
+ EMsgTrust mTrust;
+ EMsgEncoding mEncoding;
+ EMsgDeprecation mDeprecation;
+ U32 mMessageNumber;
+ S32 mTotalSize;
+ U32 mReceiveCount; // how many of this template have been received since last reset
+ U32 mReceiveBytes; // How many bytes received
+ U32 mReceiveInvalid; // How many "invalid" packets
+ F32 mDecodeTimeThisFrame; // Total seconds spent decoding this frame
+ U32 mTotalDecoded; // Total messages successfully decoded
+ F32 mTotalDecodeTime; // Total time successfully decoding messages
+ F32 mMaxDecodeTimePerMsg;
+
+ bool mBanFromTrusted;
+ bool mBanFromUntrusted;
+
+private:
+ // message handler function (this is set by each application)
+ void (*mHandlerFunc)(LLMessageSystem *msgsystem, void **user_data);
+ void **mUserData;
+};
+
+#endif // LL_LLMESSAGETEMPLATE_H
diff --git a/indra/llmessage/llmessagetemplateparser.cpp b/indra/llmessage/llmessagetemplateparser.cpp
index 4b61272454..274ec3e273 100644
--- a/indra/llmessage/llmessagetemplateparser.cpp
+++ b/indra/llmessage/llmessagetemplateparser.cpp
@@ -1,761 +1,761 @@
-/**
- * @file llmessagetemplateparser.cpp
- * @brief LLMessageTemplateParser implementation
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llmessagetemplateparser.h"
-#include <boost/tokenizer.hpp>
-
-
-// What follows is a bunch of C functions to do validation.
-
-// Lets support a small subset of regular expressions here
-// Syntax is a string made up of:
-// a - checks against alphanumeric ([A-Za-z0-9])
-// c - checks against character ([A-Za-z])
-// f - checks against first variable character ([A-Za-z_])
-// v - checks against variable ([A-Za-z0-9_])
-// s - checks against sign of integer ([-0-9])
-// d - checks against integer digit ([0-9])
-// * - repeat last check
-
-// checks 'a'
-bool b_return_alphanumeric_ok(char c)
-{
- if ( ( (c < 'A')
- ||(c > 'Z'))
- &&( (c < 'a')
- ||(c > 'z'))
- &&( (c < '0')
- ||(c > '9')))
- {
- return false;
- }
- return true;
-}
-
-// checks 'c'
-bool b_return_character_ok(char c)
-{
- if ( ( (c < 'A')
- ||(c > 'Z'))
- &&( (c < 'a')
- ||(c > 'z')))
- {
- return false;
- }
- return true;
-}
-
-// checks 'f'
-bool b_return_first_variable_ok(char c)
-{
- if ( ( (c < 'A')
- ||(c > 'Z'))
- &&( (c < 'a')
- ||(c > 'z'))
- &&(c != '_'))
- {
- return false;
- }
- return true;
-}
-
-// checks 'v'
-bool b_return_variable_ok(char c)
-{
- if ( ( (c < 'A')
- ||(c > 'Z'))
- &&( (c < 'a')
- ||(c > 'z'))
- &&( (c < '0')
- ||(c > '9'))
- &&(c != '_'))
- {
- return false;
- }
- return true;
-}
-
-// checks 's'
-bool b_return_signed_integer_ok(char c)
-{
- if ( ( (c < '0')
- ||(c > '9'))
- &&(c != '-'))
- {
- return false;
- }
- return true;
-}
-
-// checks 'd'
-bool b_return_integer_ok(char c)
-{
- if ( (c < '0')
- ||(c > '9'))
- {
- return false;
- }
- return true;
-}
-
-bool (*gParseCheckCharacters[])(char c) =
-{
- b_return_alphanumeric_ok,
- b_return_character_ok,
- b_return_first_variable_ok,
- b_return_variable_ok,
- b_return_signed_integer_ok,
- b_return_integer_ok
-};
-
-S32 get_checker_number(char checker)
-{
- switch(checker)
- {
- case 'a':
- return 0;
- case 'c':
- return 1;
- case 'f':
- return 2;
- case 'v':
- return 3;
- case 's':
- return 4;
- case 'd':
- return 5;
- case '*':
- return 9999;
- default:
- return -1;
- }
-}
-
-// check token based on passed simplified regular expression
-bool b_check_token(const char *token, const char *regexp)
-{
- S32 tptr, rptr = 0;
- S32 current_checker, next_checker = 0;
-
- current_checker = get_checker_number(regexp[rptr++]);
-
- if (current_checker == -1)
- {
- LL_ERRS() << "Invalid regular expression value!" << LL_ENDL;
- return false;
- }
-
- if (current_checker == 9999)
- {
- LL_ERRS() << "Regular expression can't start with *!" << LL_ENDL;
- return false;
- }
-
- for (tptr = 0; token[tptr]; tptr++)
- {
- if (current_checker == -1)
- {
- LL_ERRS() << "Input exceeds regular expression!\nDid you forget a *?" << LL_ENDL;
- return false;
- }
-
- if (!gParseCheckCharacters[current_checker](token[tptr]))
- {
- return false;
- }
- if (next_checker != 9999)
- {
- next_checker = get_checker_number(regexp[rptr++]);
- if (next_checker != 9999)
- {
- current_checker = next_checker;
- }
- }
- }
- return true;
-}
-
-// C variable can be made up of upper or lower case letters, underscores, or numbers, but can't start with a number
-bool b_variable_ok(const char *token)
-{
- if (!b_check_token(token, "fv*"))
- {
- LL_WARNS() << "Token '" << token << "' isn't a variable!" << LL_ENDL;
- return false;
- }
- return true;
-}
-
-// An integer is made up of the digits 0-9 and may be preceded by a '-'
-bool b_integer_ok(const char *token)
-{
- if (!b_check_token(token, "sd*"))
- {
- LL_WARNS() << "Token isn't an integer!" << LL_ENDL;
- return false;
- }
- return true;
-}
-
-// An integer is made up of the digits 0-9
-bool b_positive_integer_ok(const char *token)
-{
- if (!b_check_token(token, "d*"))
- {
- LL_WARNS() << "Token isn't an integer!" << LL_ENDL;
- return false;
- }
- return true;
-}
-
-
-// Done with C functions, here's the tokenizer.
-
-typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
-
-LLTemplateTokenizer::LLTemplateTokenizer(const std::string & contents) : mStarted(false), mTokens()
-{
- boost::char_separator<char> newline("\r\n", "", boost::keep_empty_tokens);
- boost::char_separator<char> spaces(" \t");
- U32 line_counter = 1;
-
- tokenizer line_tokens(contents, newline);
- for(tokenizer::iterator line_iter = line_tokens.begin();
- line_iter != line_tokens.end();
- ++line_iter, ++line_counter)
- {
- tokenizer word_tokens(*line_iter, spaces);
- for(tokenizer::iterator word_iter = word_tokens.begin();
- word_iter != word_tokens.end();
- ++word_iter)
- {
- if((*word_iter)[0] == '/')
- {
- break; // skip to end of line on comments
- }
- positioned_token pt;// = new positioned_token();
- pt.str = std::string(*word_iter);
- pt.line = line_counter;
- mTokens.push_back(pt);
- }
- }
- mCurrent = mTokens.begin();
-}
-void LLTemplateTokenizer::inc()
-{
- if(atEOF())
- {
- error("trying to increment token of EOF");
- }
- else if(mStarted)
- {
- ++mCurrent;
- }
- else
- {
- mStarted = true;
- mCurrent = mTokens.begin();
- }
-}
-void LLTemplateTokenizer::dec()
-{
- if(mCurrent == mTokens.begin())
- {
- if(mStarted)
- {
- mStarted = false;
- }
- else
- {
- error("trying to decrement past beginning of file");
- }
- }
- else
- {
- mCurrent--;
- }
-}
-
-std::string LLTemplateTokenizer::get() const
-{
- if(atEOF())
- {
- error("trying to get EOF");
- }
- return mCurrent->str;
-}
-
-U32 LLTemplateTokenizer::line() const
-{
- if(atEOF())
- {
- return 0;
- }
- return mCurrent->line;
-}
-
-bool LLTemplateTokenizer::atEOF() const
-{
- return mCurrent == mTokens.end();
-}
-
-std::string LLTemplateTokenizer::next()
-{
- inc();
- return get();
-}
-
-bool LLTemplateTokenizer::want(const std::string & token)
-{
- if(atEOF()) return false;
- inc();
- if(atEOF()) return false;
- if(get() != token)
- {
- dec(); // back up a step
- return false;
- }
- return true;
-}
-
-bool LLTemplateTokenizer::wantEOF()
-{
- // see if the next token is EOF
- if(atEOF()) return true;
- inc();
- if(!atEOF())
- {
- dec(); // back up a step
- return false;
- }
- return true;
-}
-
-void LLTemplateTokenizer::error(std::string message) const
-{
- if(atEOF())
- {
- LL_ERRS() << "Unexpected end of file: " << message << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "Problem parsing message template at line "
- << line() << ", with token '" << get() << "' : "
- << message << LL_ENDL;
- }
-}
-
-
-// Done with tokenizer, next is the parser.
-
-LLTemplateParser::LLTemplateParser(LLTemplateTokenizer & tokens):
- mVersion(0.f),
- mMessages()
-{
- // the version number should be the first thing in the file
- if (tokens.want("version"))
- {
- // version number
- std::string vers_string = tokens.next();
- mVersion = (F32)atof(vers_string.c_str());
-
- LL_INFOS() << "### Message template version " << mVersion << " ###" << LL_ENDL;
- }
- else
- {
- LL_ERRS() << "Version must be first in the message template, found "
- << tokens.next() << LL_ENDL;
- }
-
- while(LLMessageTemplate * templatep = parseMessage(tokens))
- {
- if (templatep->getDeprecation() != MD_DEPRECATED)
- {
- mMessages.push_back(templatep);
- }
- else
- {
- delete templatep;
- }
- }
-
- if(!tokens.wantEOF())
- {
- LL_ERRS() << "Expected end of template or a message, instead found: "
- << tokens.next() << " at " << tokens.line() << LL_ENDL;
- }
-}
-
-F32 LLTemplateParser::getVersion() const
-{
- return mVersion;
-}
-
-LLTemplateParser::message_iterator LLTemplateParser::getMessagesBegin() const
-{
- return mMessages.begin();
-}
-
-LLTemplateParser::message_iterator LLTemplateParser::getMessagesEnd() const
-{
- return mMessages.end();
-}
-
-
-// static
-LLMessageTemplate * LLTemplateParser::parseMessage(LLTemplateTokenizer & tokens)
-{
- LLMessageTemplate *templatep = NULL;
- if(!tokens.want("{"))
- {
- return NULL;
- }
-
- // name first
- std::string template_name = tokens.next();
-
- // is name a legit C variable name
- if (!b_variable_ok(template_name.c_str()))
- {
- LL_ERRS() << "Not legit variable name: " << template_name << " at " << tokens.line() << LL_ENDL;
- }
-
- // ok, now get Frequency ("High", "Medium", or "Low")
- EMsgFrequency frequency = MFT_LOW;
- std::string freq_string = tokens.next();
- if (freq_string == "High")
- {
- frequency = MFT_HIGH;
- }
- else if (freq_string == "Medium")
- {
- frequency = MFT_MEDIUM;
- }
- else if (freq_string == "Low" || freq_string == "Fixed")
- {
- frequency = MFT_LOW;
- }
- else
- {
- LL_ERRS() << "Expected frequency, got " << freq_string << " at " << tokens.line() << LL_ENDL;
- }
-
- // TODO more explicit checking here pls
- U32 message_number = strtoul(tokens.next().c_str(),NULL,0);
-
- switch (frequency) {
- case MFT_HIGH:
- break;
- case MFT_MEDIUM:
- message_number = (255 << 8) | message_number;
- break;
- case MFT_LOW:
- message_number = (255 << 24) | (255 << 16) | message_number;
- break;
- default:
- LL_ERRS() << "Unknown frequency enum: " << frequency << LL_ENDL;
- }
-
- templatep = new LLMessageTemplate(
- template_name.c_str(),
- message_number,
- frequency);
-
- // Now get trust ("Trusted", "NotTrusted")
- std::string trust = tokens.next();
- if (trust == "Trusted")
- {
- templatep->setTrust(MT_TRUST);
- }
- else if (trust == "NotTrusted")
- {
- templatep->setTrust(MT_NOTRUST);
- }
- else
- {
- LL_ERRS() << "Bad trust " << trust << " at " << tokens.line() << LL_ENDL;
- }
-
- // get encoding
- std::string encoding = tokens.next();
- if(encoding == "Unencoded")
- {
- templatep->setEncoding(ME_UNENCODED);
- }
- else if(encoding == "Zerocoded")
- {
- templatep->setEncoding(ME_ZEROCODED);
- }
- else
- {
- LL_ERRS() << "Bad encoding " << encoding << " at " << tokens.line() << LL_ENDL;
- }
-
- // get deprecation
- if(tokens.want("Deprecated"))
- {
- templatep->setDeprecation(MD_DEPRECATED);
- }
- else if (tokens.want("UDPDeprecated"))
- {
- templatep->setDeprecation(MD_UDPDEPRECATED);
- }
- else if (tokens.want("UDPBlackListed"))
- {
- templatep->setDeprecation(MD_UDPBLACKLISTED);
- }
- else if (tokens.want("NotDeprecated"))
- {
- // this is the default value, but it can't hurt to set it twice
- templatep->setDeprecation(MD_NOTDEPRECATED);
- }
- else {
- // It's probably a brace, let's just start block processing
- }
-
- while(LLMessageBlock * blockp = parseBlock(tokens))
- {
- templatep->addBlock(blockp);
- }
-
- if(!tokens.want("}"))
- {
- LL_ERRS() << "Expecting closing } for message " << template_name
- << " at " << tokens.line() << LL_ENDL;
- }
- return templatep;
-}
-
-// static
-LLMessageBlock * LLTemplateParser::parseBlock(LLTemplateTokenizer & tokens)
-{
- LLMessageBlock * blockp = NULL;
-
- if(!tokens.want("{"))
- {
- return NULL;
- }
-
- // name first
- std::string block_name = tokens.next();
-
- // is name a legit C variable name
- if (!b_variable_ok(block_name.c_str()))
- {
- LL_ERRS() << "not a legal block name: " << block_name
- << " at " << tokens.line() << LL_ENDL;
- }
-
- // now, block type ("Single", "Multiple", or "Variable")
- std::string block_type = tokens.next();
- // which one is it?
- if (block_type == "Single")
- {
- // ok, we can create a block
- blockp = new LLMessageBlock(block_name.c_str(), MBT_SINGLE);
- }
- else if (block_type == "Multiple")
- {
- // need to get the number of repeats
- std::string repeats = tokens.next();
-
- // is it a legal integer
- if (!b_positive_integer_ok(repeats.c_str()))
- {
- LL_ERRS() << "not a legal integer for block multiple count: "
- << repeats << " at " << tokens.line() << LL_ENDL;
- }
-
- // ok, we can create a block
- blockp = new LLMessageBlock(block_name.c_str(),
- MBT_MULTIPLE,
- atoi(repeats.c_str()));
- }
- else if (block_type == "Variable")
- {
- // ok, we can create a block
- blockp = new LLMessageBlock(block_name.c_str(), MBT_VARIABLE);
- }
- else
- {
- LL_ERRS() << "bad block type: " << block_type
- << " at " << tokens.line() << LL_ENDL;
- }
-
-
- while(LLMessageVariable * varp = parseVariable(tokens))
- {
- blockp->addVariable(varp->getName(),
- varp->getType(),
- varp->getSize());
- delete varp;
- }
-
- if(!tokens.want("}"))
- {
- LL_ERRS() << "Expecting closing } for block " << block_name
- << " at " << tokens.line() << LL_ENDL;
- }
- return blockp;
-
-}
-
-// static
-LLMessageVariable * LLTemplateParser::parseVariable(LLTemplateTokenizer & tokens)
-{
- LLMessageVariable * varp = NULL;
- if(!tokens.want("{"))
- {
- return NULL;
- }
-
- std::string var_name = tokens.next();
-
- if (!b_variable_ok(var_name.c_str()))
- {
- LL_ERRS() << "Not a legit variable name: " << var_name
- << " at " << tokens.line() << LL_ENDL;
- }
-
- std::string var_type = tokens.next();
-
- if (var_type == "U8")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_U8, 1);
- }
- else if (var_type == "U16")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_U16, 2);
- }
- else if (var_type == "U32")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_U32, 4);
- }
- else if (var_type == "U64")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_U64, 8);
- }
- else if (var_type == "S8")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_S8, 1);
- }
- else if (var_type == "S16")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_S16, 2);
- }
- else if (var_type == "S32")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_S32, 4);
- }
- else if (var_type == "S64")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_S64, 8);
- }
- else if (var_type == "F32")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_F32, 4);
- }
- else if (var_type == "F64")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_F64, 8);
- }
- else if (var_type == "LLVector3")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3, 12);
- }
- else if (var_type == "LLVector3d")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3d, 24);
- }
- else if (var_type == "LLVector4")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector4, 16);
- }
- else if (var_type == "LLQuaternion")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_LLQuaternion, 12);
- }
- else if (var_type == "LLUUID")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_LLUUID, 16);
- }
- else if (var_type == "BOOL")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_BOOL, 1);
- }
- else if (var_type == "IPADDR")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_IP_ADDR, 4);
- }
- else if (var_type == "IPPORT")
- {
- varp = new LLMessageVariable(var_name.c_str(), MVT_IP_PORT, 2);
- }
- else if (var_type == "Fixed" || var_type == "Variable")
- {
- std::string variable_size = tokens.next();
-
- if (!b_positive_integer_ok(variable_size.c_str()))
- {
- LL_ERRS() << "not a legal integer variable size: " << variable_size
- << " at " << tokens.line() << LL_ENDL;
- }
-
- EMsgVariableType type_enum;
- if(var_type == "Variable")
- {
- type_enum = MVT_VARIABLE;
- }
- else if(var_type == "Fixed")
- {
- type_enum = MVT_FIXED;
- }
- else
- {
- type_enum = MVT_FIXED; // removes a warning
- LL_ERRS() << "bad variable type: " << var_type
- << " at " << tokens.line() << LL_ENDL;
- }
-
- varp = new LLMessageVariable(
- var_name.c_str(),
- type_enum,
- atoi(variable_size.c_str()));
- }
- else
- {
- LL_ERRS() << "bad variable type:" << var_type
- << " at " << tokens.line() << LL_ENDL;
- }
-
- if(!tokens.want("}"))
- {
- LL_ERRS() << "Expecting closing } for variable " << var_name
- << " at " << tokens.line() << LL_ENDL;
- }
- return varp;
-}
+/**
+ * @file llmessagetemplateparser.cpp
+ * @brief LLMessageTemplateParser implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llmessagetemplateparser.h"
+#include <boost/tokenizer.hpp>
+
+
+// What follows is a bunch of C functions to do validation.
+
+// Lets support a small subset of regular expressions here
+// Syntax is a string made up of:
+// a - checks against alphanumeric ([A-Za-z0-9])
+// c - checks against character ([A-Za-z])
+// f - checks against first variable character ([A-Za-z_])
+// v - checks against variable ([A-Za-z0-9_])
+// s - checks against sign of integer ([-0-9])
+// d - checks against integer digit ([0-9])
+// * - repeat last check
+
+// checks 'a'
+bool b_return_alphanumeric_ok(char c)
+{
+ if ( ( (c < 'A')
+ ||(c > 'Z'))
+ &&( (c < 'a')
+ ||(c > 'z'))
+ &&( (c < '0')
+ ||(c > '9')))
+ {
+ return false;
+ }
+ return true;
+}
+
+// checks 'c'
+bool b_return_character_ok(char c)
+{
+ if ( ( (c < 'A')
+ ||(c > 'Z'))
+ &&( (c < 'a')
+ ||(c > 'z')))
+ {
+ return false;
+ }
+ return true;
+}
+
+// checks 'f'
+bool b_return_first_variable_ok(char c)
+{
+ if ( ( (c < 'A')
+ ||(c > 'Z'))
+ &&( (c < 'a')
+ ||(c > 'z'))
+ &&(c != '_'))
+ {
+ return false;
+ }
+ return true;
+}
+
+// checks 'v'
+bool b_return_variable_ok(char c)
+{
+ if ( ( (c < 'A')
+ ||(c > 'Z'))
+ &&( (c < 'a')
+ ||(c > 'z'))
+ &&( (c < '0')
+ ||(c > '9'))
+ &&(c != '_'))
+ {
+ return false;
+ }
+ return true;
+}
+
+// checks 's'
+bool b_return_signed_integer_ok(char c)
+{
+ if ( ( (c < '0')
+ ||(c > '9'))
+ &&(c != '-'))
+ {
+ return false;
+ }
+ return true;
+}
+
+// checks 'd'
+bool b_return_integer_ok(char c)
+{
+ if ( (c < '0')
+ ||(c > '9'))
+ {
+ return false;
+ }
+ return true;
+}
+
+bool (*gParseCheckCharacters[])(char c) =
+{
+ b_return_alphanumeric_ok,
+ b_return_character_ok,
+ b_return_first_variable_ok,
+ b_return_variable_ok,
+ b_return_signed_integer_ok,
+ b_return_integer_ok
+};
+
+S32 get_checker_number(char checker)
+{
+ switch(checker)
+ {
+ case 'a':
+ return 0;
+ case 'c':
+ return 1;
+ case 'f':
+ return 2;
+ case 'v':
+ return 3;
+ case 's':
+ return 4;
+ case 'd':
+ return 5;
+ case '*':
+ return 9999;
+ default:
+ return -1;
+ }
+}
+
+// check token based on passed simplified regular expression
+bool b_check_token(const char *token, const char *regexp)
+{
+ S32 tptr, rptr = 0;
+ S32 current_checker, next_checker = 0;
+
+ current_checker = get_checker_number(regexp[rptr++]);
+
+ if (current_checker == -1)
+ {
+ LL_ERRS() << "Invalid regular expression value!" << LL_ENDL;
+ return false;
+ }
+
+ if (current_checker == 9999)
+ {
+ LL_ERRS() << "Regular expression can't start with *!" << LL_ENDL;
+ return false;
+ }
+
+ for (tptr = 0; token[tptr]; tptr++)
+ {
+ if (current_checker == -1)
+ {
+ LL_ERRS() << "Input exceeds regular expression!\nDid you forget a *?" << LL_ENDL;
+ return false;
+ }
+
+ if (!gParseCheckCharacters[current_checker](token[tptr]))
+ {
+ return false;
+ }
+ if (next_checker != 9999)
+ {
+ next_checker = get_checker_number(regexp[rptr++]);
+ if (next_checker != 9999)
+ {
+ current_checker = next_checker;
+ }
+ }
+ }
+ return true;
+}
+
+// C variable can be made up of upper or lower case letters, underscores, or numbers, but can't start with a number
+bool b_variable_ok(const char *token)
+{
+ if (!b_check_token(token, "fv*"))
+ {
+ LL_WARNS() << "Token '" << token << "' isn't a variable!" << LL_ENDL;
+ return false;
+ }
+ return true;
+}
+
+// An integer is made up of the digits 0-9 and may be preceded by a '-'
+bool b_integer_ok(const char *token)
+{
+ if (!b_check_token(token, "sd*"))
+ {
+ LL_WARNS() << "Token isn't an integer!" << LL_ENDL;
+ return false;
+ }
+ return true;
+}
+
+// An integer is made up of the digits 0-9
+bool b_positive_integer_ok(const char *token)
+{
+ if (!b_check_token(token, "d*"))
+ {
+ LL_WARNS() << "Token isn't an integer!" << LL_ENDL;
+ return false;
+ }
+ return true;
+}
+
+
+// Done with C functions, here's the tokenizer.
+
+typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
+
+LLTemplateTokenizer::LLTemplateTokenizer(const std::string & contents) : mStarted(false), mTokens()
+{
+ boost::char_separator<char> newline("\r\n", "", boost::keep_empty_tokens);
+ boost::char_separator<char> spaces(" \t");
+ U32 line_counter = 1;
+
+ tokenizer line_tokens(contents, newline);
+ for(tokenizer::iterator line_iter = line_tokens.begin();
+ line_iter != line_tokens.end();
+ ++line_iter, ++line_counter)
+ {
+ tokenizer word_tokens(*line_iter, spaces);
+ for(tokenizer::iterator word_iter = word_tokens.begin();
+ word_iter != word_tokens.end();
+ ++word_iter)
+ {
+ if((*word_iter)[0] == '/')
+ {
+ break; // skip to end of line on comments
+ }
+ positioned_token pt;// = new positioned_token();
+ pt.str = std::string(*word_iter);
+ pt.line = line_counter;
+ mTokens.push_back(pt);
+ }
+ }
+ mCurrent = mTokens.begin();
+}
+void LLTemplateTokenizer::inc()
+{
+ if(atEOF())
+ {
+ error("trying to increment token of EOF");
+ }
+ else if(mStarted)
+ {
+ ++mCurrent;
+ }
+ else
+ {
+ mStarted = true;
+ mCurrent = mTokens.begin();
+ }
+}
+void LLTemplateTokenizer::dec()
+{
+ if(mCurrent == mTokens.begin())
+ {
+ if(mStarted)
+ {
+ mStarted = false;
+ }
+ else
+ {
+ error("trying to decrement past beginning of file");
+ }
+ }
+ else
+ {
+ mCurrent--;
+ }
+}
+
+std::string LLTemplateTokenizer::get() const
+{
+ if(atEOF())
+ {
+ error("trying to get EOF");
+ }
+ return mCurrent->str;
+}
+
+U32 LLTemplateTokenizer::line() const
+{
+ if(atEOF())
+ {
+ return 0;
+ }
+ return mCurrent->line;
+}
+
+bool LLTemplateTokenizer::atEOF() const
+{
+ return mCurrent == mTokens.end();
+}
+
+std::string LLTemplateTokenizer::next()
+{
+ inc();
+ return get();
+}
+
+bool LLTemplateTokenizer::want(const std::string & token)
+{
+ if(atEOF()) return false;
+ inc();
+ if(atEOF()) return false;
+ if(get() != token)
+ {
+ dec(); // back up a step
+ return false;
+ }
+ return true;
+}
+
+bool LLTemplateTokenizer::wantEOF()
+{
+ // see if the next token is EOF
+ if(atEOF()) return true;
+ inc();
+ if(!atEOF())
+ {
+ dec(); // back up a step
+ return false;
+ }
+ return true;
+}
+
+void LLTemplateTokenizer::error(std::string message) const
+{
+ if(atEOF())
+ {
+ LL_ERRS() << "Unexpected end of file: " << message << LL_ENDL;
+ }
+ else
+ {
+ LL_ERRS() << "Problem parsing message template at line "
+ << line() << ", with token '" << get() << "' : "
+ << message << LL_ENDL;
+ }
+}
+
+
+// Done with tokenizer, next is the parser.
+
+LLTemplateParser::LLTemplateParser(LLTemplateTokenizer & tokens):
+ mVersion(0.f),
+ mMessages()
+{
+ // the version number should be the first thing in the file
+ if (tokens.want("version"))
+ {
+ // version number
+ std::string vers_string = tokens.next();
+ mVersion = (F32)atof(vers_string.c_str());
+
+ LL_INFOS() << "### Message template version " << mVersion << " ###" << LL_ENDL;
+ }
+ else
+ {
+ LL_ERRS() << "Version must be first in the message template, found "
+ << tokens.next() << LL_ENDL;
+ }
+
+ while(LLMessageTemplate * templatep = parseMessage(tokens))
+ {
+ if (templatep->getDeprecation() != MD_DEPRECATED)
+ {
+ mMessages.push_back(templatep);
+ }
+ else
+ {
+ delete templatep;
+ }
+ }
+
+ if(!tokens.wantEOF())
+ {
+ LL_ERRS() << "Expected end of template or a message, instead found: "
+ << tokens.next() << " at " << tokens.line() << LL_ENDL;
+ }
+}
+
+F32 LLTemplateParser::getVersion() const
+{
+ return mVersion;
+}
+
+LLTemplateParser::message_iterator LLTemplateParser::getMessagesBegin() const
+{
+ return mMessages.begin();
+}
+
+LLTemplateParser::message_iterator LLTemplateParser::getMessagesEnd() const
+{
+ return mMessages.end();
+}
+
+
+// static
+LLMessageTemplate * LLTemplateParser::parseMessage(LLTemplateTokenizer & tokens)
+{
+ LLMessageTemplate *templatep = NULL;
+ if(!tokens.want("{"))
+ {
+ return NULL;
+ }
+
+ // name first
+ std::string template_name = tokens.next();
+
+ // is name a legit C variable name
+ if (!b_variable_ok(template_name.c_str()))
+ {
+ LL_ERRS() << "Not legit variable name: " << template_name << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // ok, now get Frequency ("High", "Medium", or "Low")
+ EMsgFrequency frequency = MFT_LOW;
+ std::string freq_string = tokens.next();
+ if (freq_string == "High")
+ {
+ frequency = MFT_HIGH;
+ }
+ else if (freq_string == "Medium")
+ {
+ frequency = MFT_MEDIUM;
+ }
+ else if (freq_string == "Low" || freq_string == "Fixed")
+ {
+ frequency = MFT_LOW;
+ }
+ else
+ {
+ LL_ERRS() << "Expected frequency, got " << freq_string << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // TODO more explicit checking here pls
+ U32 message_number = strtoul(tokens.next().c_str(),NULL,0);
+
+ switch (frequency) {
+ case MFT_HIGH:
+ break;
+ case MFT_MEDIUM:
+ message_number = (255 << 8) | message_number;
+ break;
+ case MFT_LOW:
+ message_number = (255 << 24) | (255 << 16) | message_number;
+ break;
+ default:
+ LL_ERRS() << "Unknown frequency enum: " << frequency << LL_ENDL;
+ }
+
+ templatep = new LLMessageTemplate(
+ template_name.c_str(),
+ message_number,
+ frequency);
+
+ // Now get trust ("Trusted", "NotTrusted")
+ std::string trust = tokens.next();
+ if (trust == "Trusted")
+ {
+ templatep->setTrust(MT_TRUST);
+ }
+ else if (trust == "NotTrusted")
+ {
+ templatep->setTrust(MT_NOTRUST);
+ }
+ else
+ {
+ LL_ERRS() << "Bad trust " << trust << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // get encoding
+ std::string encoding = tokens.next();
+ if(encoding == "Unencoded")
+ {
+ templatep->setEncoding(ME_UNENCODED);
+ }
+ else if(encoding == "Zerocoded")
+ {
+ templatep->setEncoding(ME_ZEROCODED);
+ }
+ else
+ {
+ LL_ERRS() << "Bad encoding " << encoding << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // get deprecation
+ if(tokens.want("Deprecated"))
+ {
+ templatep->setDeprecation(MD_DEPRECATED);
+ }
+ else if (tokens.want("UDPDeprecated"))
+ {
+ templatep->setDeprecation(MD_UDPDEPRECATED);
+ }
+ else if (tokens.want("UDPBlackListed"))
+ {
+ templatep->setDeprecation(MD_UDPBLACKLISTED);
+ }
+ else if (tokens.want("NotDeprecated"))
+ {
+ // this is the default value, but it can't hurt to set it twice
+ templatep->setDeprecation(MD_NOTDEPRECATED);
+ }
+ else {
+ // It's probably a brace, let's just start block processing
+ }
+
+ while(LLMessageBlock * blockp = parseBlock(tokens))
+ {
+ templatep->addBlock(blockp);
+ }
+
+ if(!tokens.want("}"))
+ {
+ LL_ERRS() << "Expecting closing } for message " << template_name
+ << " at " << tokens.line() << LL_ENDL;
+ }
+ return templatep;
+}
+
+// static
+LLMessageBlock * LLTemplateParser::parseBlock(LLTemplateTokenizer & tokens)
+{
+ LLMessageBlock * blockp = NULL;
+
+ if(!tokens.want("{"))
+ {
+ return NULL;
+ }
+
+ // name first
+ std::string block_name = tokens.next();
+
+ // is name a legit C variable name
+ if (!b_variable_ok(block_name.c_str()))
+ {
+ LL_ERRS() << "not a legal block name: " << block_name
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // now, block type ("Single", "Multiple", or "Variable")
+ std::string block_type = tokens.next();
+ // which one is it?
+ if (block_type == "Single")
+ {
+ // ok, we can create a block
+ blockp = new LLMessageBlock(block_name.c_str(), MBT_SINGLE);
+ }
+ else if (block_type == "Multiple")
+ {
+ // need to get the number of repeats
+ std::string repeats = tokens.next();
+
+ // is it a legal integer
+ if (!b_positive_integer_ok(repeats.c_str()))
+ {
+ LL_ERRS() << "not a legal integer for block multiple count: "
+ << repeats << " at " << tokens.line() << LL_ENDL;
+ }
+
+ // ok, we can create a block
+ blockp = new LLMessageBlock(block_name.c_str(),
+ MBT_MULTIPLE,
+ atoi(repeats.c_str()));
+ }
+ else if (block_type == "Variable")
+ {
+ // ok, we can create a block
+ blockp = new LLMessageBlock(block_name.c_str(), MBT_VARIABLE);
+ }
+ else
+ {
+ LL_ERRS() << "bad block type: " << block_type
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+
+ while(LLMessageVariable * varp = parseVariable(tokens))
+ {
+ blockp->addVariable(varp->getName(),
+ varp->getType(),
+ varp->getSize());
+ delete varp;
+ }
+
+ if(!tokens.want("}"))
+ {
+ LL_ERRS() << "Expecting closing } for block " << block_name
+ << " at " << tokens.line() << LL_ENDL;
+ }
+ return blockp;
+
+}
+
+// static
+LLMessageVariable * LLTemplateParser::parseVariable(LLTemplateTokenizer & tokens)
+{
+ LLMessageVariable * varp = NULL;
+ if(!tokens.want("{"))
+ {
+ return NULL;
+ }
+
+ std::string var_name = tokens.next();
+
+ if (!b_variable_ok(var_name.c_str()))
+ {
+ LL_ERRS() << "Not a legit variable name: " << var_name
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+ std::string var_type = tokens.next();
+
+ if (var_type == "U8")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_U8, 1);
+ }
+ else if (var_type == "U16")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_U16, 2);
+ }
+ else if (var_type == "U32")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_U32, 4);
+ }
+ else if (var_type == "U64")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_U64, 8);
+ }
+ else if (var_type == "S8")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_S8, 1);
+ }
+ else if (var_type == "S16")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_S16, 2);
+ }
+ else if (var_type == "S32")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_S32, 4);
+ }
+ else if (var_type == "S64")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_S64, 8);
+ }
+ else if (var_type == "F32")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_F32, 4);
+ }
+ else if (var_type == "F64")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_F64, 8);
+ }
+ else if (var_type == "LLVector3")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3, 12);
+ }
+ else if (var_type == "LLVector3d")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector3d, 24);
+ }
+ else if (var_type == "LLVector4")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_LLVector4, 16);
+ }
+ else if (var_type == "LLQuaternion")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_LLQuaternion, 12);
+ }
+ else if (var_type == "LLUUID")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_LLUUID, 16);
+ }
+ else if (var_type == "BOOL")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_BOOL, 1);
+ }
+ else if (var_type == "IPADDR")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_IP_ADDR, 4);
+ }
+ else if (var_type == "IPPORT")
+ {
+ varp = new LLMessageVariable(var_name.c_str(), MVT_IP_PORT, 2);
+ }
+ else if (var_type == "Fixed" || var_type == "Variable")
+ {
+ std::string variable_size = tokens.next();
+
+ if (!b_positive_integer_ok(variable_size.c_str()))
+ {
+ LL_ERRS() << "not a legal integer variable size: " << variable_size
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+ EMsgVariableType type_enum;
+ if(var_type == "Variable")
+ {
+ type_enum = MVT_VARIABLE;
+ }
+ else if(var_type == "Fixed")
+ {
+ type_enum = MVT_FIXED;
+ }
+ else
+ {
+ type_enum = MVT_FIXED; // removes a warning
+ LL_ERRS() << "bad variable type: " << var_type
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+ varp = new LLMessageVariable(
+ var_name.c_str(),
+ type_enum,
+ atoi(variable_size.c_str()));
+ }
+ else
+ {
+ LL_ERRS() << "bad variable type:" << var_type
+ << " at " << tokens.line() << LL_ENDL;
+ }
+
+ if(!tokens.want("}"))
+ {
+ LL_ERRS() << "Expecting closing } for variable " << var_name
+ << " at " << tokens.line() << LL_ENDL;
+ }
+ return varp;
+}
diff --git a/indra/llmessage/llmessagetemplateparser.h b/indra/llmessage/llmessagetemplateparser.h
index 372a2b292d..83ed608429 100644
--- a/indra/llmessage/llmessagetemplateparser.h
+++ b/indra/llmessage/llmessagetemplateparser.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmessagetemplateparser.h
* @brief Classes to parse message template.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,48 +33,48 @@
class LLTemplateTokenizer
{
public:
- LLTemplateTokenizer(const std::string & contents);
+ LLTemplateTokenizer(const std::string & contents);
- U32 line() const;
- bool atEOF() const;
- std::string next();
+ U32 line() const;
+ bool atEOF() const;
+ std::string next();
- bool want(const std::string & token);
- bool wantEOF();
+ bool want(const std::string & token);
+ bool wantEOF();
private:
- void inc();
- void dec();
- std::string get() const;
- void error(std::string message = "generic") const;
+ void inc();
+ void dec();
+ std::string get() const;
+ void error(std::string message = "generic") const;
- struct positioned_token
- {
- std::string str;
- U32 line;
- };
-
- bool mStarted;
- std::list<positioned_token> mTokens;
- std::list<positioned_token>::const_iterator mCurrent;
+ struct positioned_token
+ {
+ std::string str;
+ U32 line;
+ };
+
+ bool mStarted;
+ std::list<positioned_token> mTokens;
+ std::list<positioned_token>::const_iterator mCurrent;
};
class LLTemplateParser
{
public:
- typedef std::list<LLMessageTemplate *>::const_iterator message_iterator;
-
- static LLMessageTemplate * parseMessage(LLTemplateTokenizer & tokens);
- static LLMessageBlock * parseBlock(LLTemplateTokenizer & tokens);
- static LLMessageVariable * parseVariable(LLTemplateTokenizer & tokens);
+ typedef std::list<LLMessageTemplate *>::const_iterator message_iterator;
+
+ static LLMessageTemplate * parseMessage(LLTemplateTokenizer & tokens);
+ static LLMessageBlock * parseBlock(LLTemplateTokenizer & tokens);
+ static LLMessageVariable * parseVariable(LLTemplateTokenizer & tokens);
+
+ LLTemplateParser(LLTemplateTokenizer & tokens);
+ message_iterator getMessagesBegin() const;
+ message_iterator getMessagesEnd() const;
+ F32 getVersion() const;
- LLTemplateParser(LLTemplateTokenizer & tokens);
- message_iterator getMessagesBegin() const;
- message_iterator getMessagesEnd() const;
- F32 getVersion() const;
-
private:
- F32 mVersion;
- std::list<LLMessageTemplate *> mMessages;
+ F32 mVersion;
+ std::list<LLMessageTemplate *> mMessages;
};
#endif
diff --git a/indra/llmessage/llmessagethrottle.cpp b/indra/llmessage/llmessagethrottle.cpp
index bddb9e14d6..77af27e404 100644
--- a/indra/llmessage/llmessagethrottle.cpp
+++ b/indra/llmessage/llmessagethrottle.cpp
@@ -1,153 +1,153 @@
-/**
- * @file llmessagethrottle.cpp
- * @brief LLMessageThrottle class used for throttling messages.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llhash.h"
-
-#include "llmessagethrottle.h"
-#include "llframetimer.h"
-
-// This is used for the stl search_n function.
-bool eq_message_throttle_entry(LLMessageThrottleEntry a, LLMessageThrottleEntry b)
- { return a.getHash() == b.getHash(); }
-
-const U64 SEC_TO_USEC = 1000000;
-
-// How long (in microseconds) each type of message stays in its throttle list.
-const U64 MAX_MESSAGE_AGE[MTC_EOF] =
-{
- 10 * SEC_TO_USEC, // MTC_VIEWER_ALERT
- 10 * SEC_TO_USEC // MTC_AGENT_ALERT
-};
-
-LLMessageThrottle::LLMessageThrottle()
-{
-}
-
-LLMessageThrottle::~LLMessageThrottle()
-{
-}
-
-void LLMessageThrottle::pruneEntries()
-{
- // Go through each message category, and prune entries older than max age.
- S32 cat;
- for (cat = 0; cat < MTC_EOF; cat++)
- {
- message_list_t* message_list = &(mMessageList[cat]);
-
- // Use a reverse iterator, since entries on the back will be the oldest.
- message_list_reverse_iterator_t r_iterator = message_list->rbegin();
- message_list_reverse_iterator_t r_last = message_list->rend();
-
- // Look for the first entry younger than the maximum age.
- F32 max_age = (F32)MAX_MESSAGE_AGE[cat];
- bool found = false;
- while (r_iterator != r_last && !found)
- {
- if ( LLFrameTimer::getTotalTime() - (*r_iterator).getEntryTime() < max_age )
- {
- // We found a young enough entry.
- found = true;
-
- // Did we find at least one entry to remove?
- if (r_iterator != message_list->rbegin())
- {
- // Yes, remove it.
- message_list->erase(r_iterator.base(), message_list->end());
- }
- }
- else
- {
- r_iterator++;
- }
- }
-
- // If we didn't find any entries young enough to keep, remove them all.
- if (!found)
- {
- message_list->clear();
- }
- }
-}
-
-bool LLMessageThrottle::addViewerAlert(const LLUUID& to, const std::string& mesg)
-{
- message_list_t* message_list = &(mMessageList[MTC_VIEWER_ALERT]);
-
- // Concatenate from,to,mesg into one string.
- std::ostringstream full_mesg;
- full_mesg << to << mesg;
-
- // Create an entry for this message.
- size_t hash = llhash(full_mesg.str().c_str());
- LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
-
- // Check if this message is already in the list.
- message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
- 1, entry, eq_message_throttle_entry);
- if (found == message_list->end())
- {
- // This message was not found. Add it to the list.
- message_list->push_front(entry);
- return true;
- }
- else
- {
- // This message was already in the list.
- return false;
- }
-}
-
-bool LLMessageThrottle::addAgentAlert(const LLUUID& agent, const LLUUID& task, const std::string& mesg)
-{
- message_list_t* message_list = &(mMessageList[MTC_AGENT_ALERT]);
-
- // Concatenate from,to,mesg into one string.
- std::ostringstream full_mesg;
- full_mesg << agent << task << mesg;
-
- // Create an entry for this message.
- size_t hash = llhash(full_mesg.str().c_str());
- LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
-
- // Check if this message is already in the list.
- message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
- 1, entry, eq_message_throttle_entry);
- if (found == message_list->end())
- {
- // This message was not found. Add it to the list.
- message_list->push_front(entry);
- return true;
- }
- else
- {
- // This message was already in the list.
- return false;
- }
-}
-
+/**
+ * @file llmessagethrottle.cpp
+ * @brief LLMessageThrottle class used for throttling messages.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llhash.h"
+
+#include "llmessagethrottle.h"
+#include "llframetimer.h"
+
+// This is used for the stl search_n function.
+bool eq_message_throttle_entry(LLMessageThrottleEntry a, LLMessageThrottleEntry b)
+ { return a.getHash() == b.getHash(); }
+
+const U64 SEC_TO_USEC = 1000000;
+
+// How long (in microseconds) each type of message stays in its throttle list.
+const U64 MAX_MESSAGE_AGE[MTC_EOF] =
+{
+ 10 * SEC_TO_USEC, // MTC_VIEWER_ALERT
+ 10 * SEC_TO_USEC // MTC_AGENT_ALERT
+};
+
+LLMessageThrottle::LLMessageThrottle()
+{
+}
+
+LLMessageThrottle::~LLMessageThrottle()
+{
+}
+
+void LLMessageThrottle::pruneEntries()
+{
+ // Go through each message category, and prune entries older than max age.
+ S32 cat;
+ for (cat = 0; cat < MTC_EOF; cat++)
+ {
+ message_list_t* message_list = &(mMessageList[cat]);
+
+ // Use a reverse iterator, since entries on the back will be the oldest.
+ message_list_reverse_iterator_t r_iterator = message_list->rbegin();
+ message_list_reverse_iterator_t r_last = message_list->rend();
+
+ // Look for the first entry younger than the maximum age.
+ F32 max_age = (F32)MAX_MESSAGE_AGE[cat];
+ bool found = false;
+ while (r_iterator != r_last && !found)
+ {
+ if ( LLFrameTimer::getTotalTime() - (*r_iterator).getEntryTime() < max_age )
+ {
+ // We found a young enough entry.
+ found = true;
+
+ // Did we find at least one entry to remove?
+ if (r_iterator != message_list->rbegin())
+ {
+ // Yes, remove it.
+ message_list->erase(r_iterator.base(), message_list->end());
+ }
+ }
+ else
+ {
+ r_iterator++;
+ }
+ }
+
+ // If we didn't find any entries young enough to keep, remove them all.
+ if (!found)
+ {
+ message_list->clear();
+ }
+ }
+}
+
+bool LLMessageThrottle::addViewerAlert(const LLUUID& to, const std::string& mesg)
+{
+ message_list_t* message_list = &(mMessageList[MTC_VIEWER_ALERT]);
+
+ // Concatenate from,to,mesg into one string.
+ std::ostringstream full_mesg;
+ full_mesg << to << mesg;
+
+ // Create an entry for this message.
+ size_t hash = llhash(full_mesg.str().c_str());
+ LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
+
+ // Check if this message is already in the list.
+ message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
+ 1, entry, eq_message_throttle_entry);
+ if (found == message_list->end())
+ {
+ // This message was not found. Add it to the list.
+ message_list->push_front(entry);
+ return true;
+ }
+ else
+ {
+ // This message was already in the list.
+ return false;
+ }
+}
+
+bool LLMessageThrottle::addAgentAlert(const LLUUID& agent, const LLUUID& task, const std::string& mesg)
+{
+ message_list_t* message_list = &(mMessageList[MTC_AGENT_ALERT]);
+
+ // Concatenate from,to,mesg into one string.
+ std::ostringstream full_mesg;
+ full_mesg << agent << task << mesg;
+
+ // Create an entry for this message.
+ size_t hash = llhash(full_mesg.str().c_str());
+ LLMessageThrottleEntry entry(hash, LLFrameTimer::getTotalTime());
+
+ // Check if this message is already in the list.
+ message_list_iterator_t found = std::search_n(message_list->begin(), message_list->end(),
+ 1, entry, eq_message_throttle_entry);
+ if (found == message_list->end())
+ {
+ // This message was not found. Add it to the list.
+ message_list->push_front(entry);
+ return true;
+ }
+ else
+ {
+ // This message was already in the list.
+ return false;
+ }
+}
+
diff --git a/indra/llmessage/llmessagethrottle.h b/indra/llmessage/llmessagethrottle.h
index ae62b43920..9597fbccdf 100644
--- a/indra/llmessage/llmessagethrottle.h
+++ b/indra/llmessage/llmessagethrottle.h
@@ -1,80 +1,80 @@
-/**
- * @file llmessagethrottle.h
- * @brief LLMessageThrottle class used for throttling messages.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMESSAGETHROTTLE_H
-#define LL_LLMESSAGETHROTTLE_H
-
-#include <deque>
-
-#include "linden_common.h"
-#include "lluuid.h"
-
-typedef enum e_message_throttle_categories
-{
- MTC_VIEWER_ALERT,
- MTC_AGENT_ALERT,
- MTC_EOF
-} EMessageThrottleCats;
-
-class LLMessageThrottleEntry
-{
-public:
- LLMessageThrottleEntry(const size_t hash, const U64 entry_time)
- : mHash(hash), mEntryTime(entry_time) {}
-
- size_t getHash() const { return mHash; }
- U64 getEntryTime() const { return mEntryTime; }
-protected:
- size_t mHash;
- U64 mEntryTime;
-};
-
-
-class LLMessageThrottle
-{
-public:
- LLMessageThrottle();
- ~LLMessageThrottle();
-
- bool addViewerAlert (const LLUUID& to, const std::string& mesg);
- bool addAgentAlert (const LLUUID& agent, const LLUUID& task, const std::string& mesg);
-
- void pruneEntries();
-
-protected:
- typedef std::deque<LLMessageThrottleEntry> message_list_t;
- typedef std::deque<LLMessageThrottleEntry>::iterator message_list_iterator_t;
- typedef std::deque<LLMessageThrottleEntry>::reverse_iterator message_list_reverse_iterator_t;
- typedef std::deque<LLMessageThrottleEntry>::const_iterator message_list_const_iterator_t;
- typedef std::deque<LLMessageThrottleEntry>::const_reverse_iterator message_list_const_reverse_iterator_t;
- message_list_t mMessageList[MTC_EOF];
-};
-
-extern LLMessageThrottle gMessageThrottle;
-
-#endif
-
-
+/**
+ * @file llmessagethrottle.h
+ * @brief LLMessageThrottle class used for throttling messages.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMESSAGETHROTTLE_H
+#define LL_LLMESSAGETHROTTLE_H
+
+#include <deque>
+
+#include "linden_common.h"
+#include "lluuid.h"
+
+typedef enum e_message_throttle_categories
+{
+ MTC_VIEWER_ALERT,
+ MTC_AGENT_ALERT,
+ MTC_EOF
+} EMessageThrottleCats;
+
+class LLMessageThrottleEntry
+{
+public:
+ LLMessageThrottleEntry(const size_t hash, const U64 entry_time)
+ : mHash(hash), mEntryTime(entry_time) {}
+
+ size_t getHash() const { return mHash; }
+ U64 getEntryTime() const { return mEntryTime; }
+protected:
+ size_t mHash;
+ U64 mEntryTime;
+};
+
+
+class LLMessageThrottle
+{
+public:
+ LLMessageThrottle();
+ ~LLMessageThrottle();
+
+ bool addViewerAlert (const LLUUID& to, const std::string& mesg);
+ bool addAgentAlert (const LLUUID& agent, const LLUUID& task, const std::string& mesg);
+
+ void pruneEntries();
+
+protected:
+ typedef std::deque<LLMessageThrottleEntry> message_list_t;
+ typedef std::deque<LLMessageThrottleEntry>::iterator message_list_iterator_t;
+ typedef std::deque<LLMessageThrottleEntry>::reverse_iterator message_list_reverse_iterator_t;
+ typedef std::deque<LLMessageThrottleEntry>::const_iterator message_list_const_iterator_t;
+ typedef std::deque<LLMessageThrottleEntry>::const_reverse_iterator message_list_const_reverse_iterator_t;
+ message_list_t mMessageList[MTC_EOF];
+};
+
+extern LLMessageThrottle gMessageThrottle;
+
+#endif
+
+
diff --git a/indra/llmessage/llmsgvariabletype.h b/indra/llmessage/llmsgvariabletype.h
index c4de822b46..74575f3a53 100644
--- a/indra/llmessage/llmsgvariabletype.h
+++ b/indra/llmessage/llmsgvariabletype.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llmsgvariabletype.h
* @brief Declaration of the EMsgVariableType enumeration.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,31 +29,31 @@
typedef enum e_message_variable_type
{
- MVT_NULL,
- MVT_FIXED,
- MVT_VARIABLE,
- MVT_U8,
- MVT_U16,
- MVT_U32,
- MVT_U64,
- MVT_S8,
- MVT_S16,
- MVT_S32,
- MVT_S64,
- MVT_F32,
- MVT_F64,
- MVT_LLVector3,
- MVT_LLVector3d,
- MVT_LLVector4,
- MVT_LLQuaternion,
- MVT_LLUUID,
- MVT_BOOL,
- MVT_IP_ADDR,
- MVT_IP_PORT,
- MVT_U16Vec3,
- MVT_U16Quat,
- MVT_S16Array,
- MVT_EOL
+ MVT_NULL,
+ MVT_FIXED,
+ MVT_VARIABLE,
+ MVT_U8,
+ MVT_U16,
+ MVT_U32,
+ MVT_U64,
+ MVT_S8,
+ MVT_S16,
+ MVT_S32,
+ MVT_S64,
+ MVT_F32,
+ MVT_F64,
+ MVT_LLVector3,
+ MVT_LLVector3d,
+ MVT_LLVector4,
+ MVT_LLQuaternion,
+ MVT_LLUUID,
+ MVT_BOOL,
+ MVT_IP_ADDR,
+ MVT_IP_PORT,
+ MVT_U16Vec3,
+ MVT_U16Quat,
+ MVT_S16Array,
+ MVT_EOL
} EMsgVariableType;
#endif // LL_LLMSGVARIABLETYPE_H
diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp
index 761e990c76..5254091481 100644
--- a/indra/llmessage/llnamevalue.cpp
+++ b/indra/llmessage/llnamevalue.cpp
@@ -1,970 +1,970 @@
-/**
- * @file llnamevalue.cpp
- * @brief class for defining name value pairs.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-// Examples:
-// AvatarCharacter STRING RW DSV male1
-
-#include "linden_common.h"
-
-#include "llnamevalue.h"
-
-#include "u64.h"
-#include "llstring.h"
-#include "llstringtable.h"
-
-// Anonymous enumeration to provide constants in this file.
-// *NOTE: These values may be used in sscanf statements below as their
-// value-1, so search for '2047' if you cange NV_BUFFER_LEN or '63' if
-// you change U64_BUFFER_LEN.
-enum
-{
- NV_BUFFER_LEN = 2048,
- U64_BUFFER_LEN = 64
-};
-
-LLStringTable gNVNameTable(256);
-
-char NameValueTypeStrings[NVT_EOF][NAME_VALUE_TYPE_STRING_LENGTH] = /*Flawfinder: Ignore*/
-{
- "NULL",
- "STRING",
- "F32",
- "S32",
- "VEC3",
- "U32",
- "CAMERA", // Deprecated, but leaving in case removing completely would cause problems
- "ASSET",
- "U64"
-};
-
-char NameValueClassStrings[NVC_EOF][NAME_VALUE_CLASS_STRING_LENGTH] = /*Flawfinder: Ignore*/
-{
- "NULL",
- "R", // read only
- "RW" // read write
-};
-
-char NameValueSendtoStrings[NVS_EOF][NAME_VALUE_SENDTO_STRING_LENGTH] = /*Flawfinder: Ignore*/
-{
- "NULL",
- "S", // "Sim", formerly SIM
- "DS", // "Data Sim" formerly SIM_SPACE
- "SV", // "Sim Viewer" formerly SIM_VIEWER
- "DSV" // "Data Sim Viewer", formerly SIM_SPACE_VIEWER
-}; /*Flawfinder: Ignore*/
-
-
-//
-// Class
-//
-
-LLNameValue::LLNameValue()
-{
- baseInit();
-}
-
-void LLNameValue::baseInit()
-{
- mNVNameTable = &gNVNameTable;
-
- mName = NULL;
- mNameValueReference.string = NULL;
-
- mType = NVT_NULL;
- mStringType = NameValueTypeStrings[NVT_NULL];
-
- mClass = NVC_NULL;
- mStringClass = NameValueClassStrings[NVC_NULL];
-
- mSendto = NVS_NULL;
- mStringSendto = NameValueSendtoStrings[NVS_NULL];
-}
-
-void LLNameValue::init(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto)
-{
- mNVNameTable = &gNVNameTable;
-
- mName = mNVNameTable->addString(name);
-
- // Nota Bene: Whatever global structure manages this should have these in the name table already!
- mStringType = mNVNameTable->addString(type);
- if (!strcmp(mStringType, "STRING"))
- {
- S32 string_length = (S32)strlen(data); /*Flawfinder: Ignore*/
- mType = NVT_STRING;
-
- delete[] mNameValueReference.string;
-
- // two options here. . . data can either look like foo or "foo"
- // WRONG! - this is a poorly implemented and incomplete escape
- // mechanism. For example, using this scheme, there is no way
- // to tell an intentional double quotes from a zero length
- // string. This needs to excised. Phoenix
- //if (strchr(data, '\"'))
- //{
- // string_length -= 2;
- // mNameValueReference.string = new char[string_length + 1];;
- // strncpy(mNameValueReference.string, data + 1, string_length);
- //}
- //else
- //{
- mNameValueReference.string = new char[string_length + 1];;
- strncpy(mNameValueReference.string, data, string_length); /*Flawfinder: Ignore*/
- //}
- mNameValueReference.string[string_length] = 0;
- }
- else if (!strcmp(mStringType, "F32"))
- {
- mType = NVT_F32;
- mNameValueReference.f32 = new F32((F32)atof(data));
- }
- else if (!strcmp(mStringType, "S32"))
- {
- mType = NVT_S32;
- mNameValueReference.s32 = new S32(atoi(data));
- }
- else if (!strcmp(mStringType, "U64"))
- {
- mType = NVT_U64;
- mNameValueReference.u64 = new U64(str_to_U64(ll_safe_string(data)));
- }
- else if (!strcmp(mStringType, "VEC3"))
- {
- mType = NVT_VEC3;
- F32 t1, t2, t3;
-
- // two options here. . . data can either look like 0, 1, 2 or <0, 1, 2>
-
- if (strchr(data, '<'))
- {
- sscanf(data, "<%f, %f, %f>", &t1, &t2, &t3);
- }
- else
- {
- sscanf(data, "%f, %f, %f", &t1, &t2, &t3);
- }
-
- // finite checks
- if (!llfinite(t1) || !llfinite(t2) || !llfinite(t3))
- {
- t1 = 0.f;
- t2 = 0.f;
- t3 = 0.f;
- }
-
- mNameValueReference.vec3 = new LLVector3(t1, t2, t3);
- }
- else if (!strcmp(mStringType, "U32"))
- {
- mType = NVT_U32;
- mNameValueReference.u32 = new U32(atoi(data));
- }
- else if(!strcmp(mStringType, (const char*)NameValueTypeStrings[NVT_ASSET]))
- {
- // assets are treated like strings, except that the name has
- // meaning to an LLAssetInfo object
- S32 string_length = (S32)strlen(data); /*Flawfinder: Ignore*/
- mType = NVT_ASSET;
-
- // two options here. . . data can either look like foo or "foo"
- // WRONG! - this is a poorly implemented and incomplete escape
- // mechanism. For example, using this scheme, there is no way
- // to tell an intentional double quotes from a zero length
- // string. This needs to excised. Phoenix
- //if (strchr(data, '\"'))
- //{
- // string_length -= 2;
- // mNameValueReference.string = new char[string_length + 1];;
- // strncpy(mNameValueReference.string, data + 1, string_length);
- //}
- //else
- //{
- mNameValueReference.string = new char[string_length + 1];;
- strncpy(mNameValueReference.string, data, string_length); /*Flawfinder: Ignore*/
- //}
- mNameValueReference.string[string_length] = 0;
- }
- else
- {
- LL_WARNS() << "Unknown name value type string " << mStringType << " for " << mName << LL_ENDL;
- mType = NVT_NULL;
- }
-
-
- // Nota Bene: Whatever global structure manages this should have these in the name table already!
- if (!strcmp(nvclass, "R") ||
- !strcmp(nvclass, "READ_ONLY")) // legacy
- {
- mClass = NVC_READ_ONLY;
- mStringClass = mNVNameTable->addString("R");
- }
- else if (!strcmp(nvclass, "RW") ||
- !strcmp(nvclass, "READ_WRITE")) // legacy
- {
- mClass = NVC_READ_WRITE;
- mStringClass = mNVNameTable->addString("RW");
- }
- else
- {
- // assume it's bad
- mClass = NVC_NULL;
- mStringClass = mNVNameTable->addString(nvclass);
- }
-
- // Initialize the sendto variable
- if (!strcmp(nvsendto, "S") ||
- !strcmp(nvsendto, "SIM")) // legacy
- {
- mSendto = NVS_SIM;
- mStringSendto = mNVNameTable->addString("S");
- }
- else if (!strcmp(nvsendto, "DS") ||
- !strcmp(nvsendto, "SIM_SPACE")) // legacy
- {
- mSendto = NVS_DATA_SIM;
- mStringSendto = mNVNameTable->addString("DS");
- }
- else if (!strcmp(nvsendto, "SV") ||
- !strcmp(nvsendto, "SIM_VIEWER")) // legacy
- {
- mSendto = NVS_SIM_VIEWER;
- mStringSendto = mNVNameTable->addString("SV");
- }
- else if (!strcmp(nvsendto, "DSV") ||
- !strcmp(nvsendto, "SIM_SPACE_VIEWER")) // legacy
- {
- mSendto = NVS_DATA_SIM_VIEWER;
- mStringSendto = mNVNameTable->addString("DSV");
- }
- else
- {
- LL_WARNS() << "LLNameValue::init() - unknown sendto field "
- << nvsendto << " for NV " << mName << LL_ENDL;
- mSendto = NVS_NULL;
- mStringSendto = mNVNameTable->addString("S");
- }
-
-}
-
-
-LLNameValue::LLNameValue(const char *name, const char *data, const char *type, const char *nvclass)
-{
- baseInit();
- // if not specified, send to simulator only
- init(name, data, type, nvclass, "SIM");
-}
-
-
-LLNameValue::LLNameValue(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto)
-{
- baseInit();
- init(name, data, type, nvclass, nvsendto);
-}
-
-
-
-// Initialize without any initial data.
-LLNameValue::LLNameValue(const char *name, const char *type, const char *nvclass)
-{
- baseInit();
- mName = mNVNameTable->addString(name);
-
- // Nota Bene: Whatever global structure manages this should have these in the name table already!
- mStringType = mNVNameTable->addString(type);
- if (!strcmp(mStringType, "STRING"))
- {
- mType = NVT_STRING;
- mNameValueReference.string = NULL;
- }
- else if (!strcmp(mStringType, "F32"))
- {
- mType = NVT_F32;
- mNameValueReference.f32 = NULL;
- }
- else if (!strcmp(mStringType, "S32"))
- {
- mType = NVT_S32;
- mNameValueReference.s32 = NULL;
- }
- else if (!strcmp(mStringType, "VEC3"))
- {
- mType = NVT_VEC3;
- mNameValueReference.vec3 = NULL;
- }
- else if (!strcmp(mStringType, "U32"))
- {
- mType = NVT_U32;
- mNameValueReference.u32 = NULL;
- }
- else if (!strcmp(mStringType, "U64"))
- {
- mType = NVT_U64;
- mNameValueReference.u64 = NULL;
- }
- else if(!strcmp(mStringType, (const char*)NameValueTypeStrings[NVT_ASSET]))
- {
- mType = NVT_ASSET;
- mNameValueReference.string = NULL;
- }
- else
- {
- mType = NVT_NULL;
- LL_INFOS() << "Unknown name-value type " << mStringType << LL_ENDL;
- }
-
- // Nota Bene: Whatever global structure manages this should have these in the name table already!
- mStringClass = mNVNameTable->addString(nvclass);
- if (!strcmp(mStringClass, "READ_ONLY"))
- {
- mClass = NVC_READ_ONLY;
- }
- else if (!strcmp(mStringClass, "READ_WRITE"))
- {
- mClass = NVC_READ_WRITE;
- }
- else
- {
- mClass = NVC_NULL;
- }
-
- // Initialize the sendto variable
- mStringSendto = mNVNameTable->addString("SIM");
- mSendto = NVS_SIM;
-}
-
-
-// data is in the format:
-// "NameValueName Type Class Data"
-LLNameValue::LLNameValue(const char *data)
-{
- baseInit();
- static char name[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
- static char type[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
- static char nvclass[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
- static char nvsendto[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
- static char nvdata[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
-
- S32 i;
-
- S32 character_count = 0;
- S32 length = 0;
-
- // go to first non-whitespace character
- while (1)
- {
- if ( (*(data + character_count) == ' ')
- ||(*(data + character_count) == '\n')
- ||(*(data + character_count) == '\t')
- ||(*(data + character_count) == '\r'))
- {
- character_count++;
- }
- else
- {
- break;
- }
- }
-
- // read in the name
- sscanf((data + character_count), "%2047s", name); /*Flawfinder: ignore*/
-
- // bump past it and add null terminator
- length = (S32)strlen(name); /* Flawfinder: ignore */
- name[length] = 0;
- character_count += length;
-
- // go to the next non-whitespace character
- while (1)
- {
- if ( (*(data + character_count) == ' ')
- ||(*(data + character_count) == '\n')
- ||(*(data + character_count) == '\t')
- ||(*(data + character_count) == '\r'))
- {
- character_count++;
- }
- else
- {
- break;
- }
- }
-
- // read in the type
- sscanf((data + character_count), "%2047s", type); /*Flawfinder: ignore*/
-
- // bump past it and add null terminator
- length = (S32)strlen(type); /* Flawfinder: ignore */
- type[length] = 0;
- character_count += length;
-
- // go to the next non-whitespace character
- while (1)
- {
- if ( (*(data + character_count) == ' ')
- ||(*(data + character_count) == '\n')
- ||(*(data + character_count) == '\t')
- ||(*(data + character_count) == '\r'))
- {
- character_count++;
- }
- else
- {
- break;
- }
- }
-
- // do we have a type argument?
- for (i = NVC_READ_ONLY; i < NVC_EOF; i++)
- {
- if (!strncmp(NameValueClassStrings[i], data + character_count, strlen(NameValueClassStrings[i]))) /* Flawfinder: ignore */
- {
- break;
- }
- }
-
- if (i != NVC_EOF)
- {
- // yes we do!
- // read in the class
- sscanf((data + character_count), "%2047s", nvclass); /*Flawfinder: ignore*/
-
- // bump past it and add null terminator
- length = (S32)strlen(nvclass); /* Flawfinder: ignore */
- nvclass[length] = 0;
- character_count += length;
-
- // go to the next non-whitespace character
- while (1)
- {
- if ( (*(data + character_count) == ' ')
- ||(*(data + character_count) == '\n')
- ||(*(data + character_count) == '\t')
- ||(*(data + character_count) == '\r'))
- {
- character_count++;
- }
- else
- {
- break;
- }
- }
- }
- else
- {
- // no type argument given, default to read-write
- strncpy(nvclass, "READ_WRITE", sizeof(nvclass) -1); /* Flawfinder: ignore */
- nvclass[sizeof(nvclass) -1] = '\0';
- }
-
- // Do we have a sendto argument?
- for (i = NVS_SIM; i < NVS_EOF; i++)
- {
- if (!strncmp(NameValueSendtoStrings[i], data + character_count, strlen(NameValueSendtoStrings[i]))) /* Flawfinder: ignore */
- {
- break;
- }
- }
-
- if (i != NVS_EOF)
- {
- // found a sendto argument
- sscanf((data + character_count), "%2047s", nvsendto); /*Flawfinder: ignore*/
-
- // add null terminator
- length = (S32)strlen(nvsendto); /* Flawfinder: ignore */
- nvsendto[length] = 0;
- character_count += length;
-
- // seek to next non-whitespace characer
- while (1)
- {
- if ( (*(data + character_count) == ' ')
- ||(*(data + character_count) == '\n')
- ||(*(data + character_count) == '\t')
- ||(*(data + character_count) == '\r'))
- {
- character_count++;
- }
- else
- {
- break;
- }
- }
- }
- else
- {
- // no sendto argument given, default to sim only
- strncpy(nvsendto, "SIM", sizeof(nvsendto) -1); /* Flawfinder: ignore */
- nvsendto[sizeof(nvsendto) -1] ='\0';
- }
-
-
- // copy the rest character by character into data
- length = 0;
-
- while ( (*(nvdata + length++) = *(data + character_count++)) )
- ;
-
- init(name, nvdata, type, nvclass, nvsendto);
-}
-
-
-LLNameValue::~LLNameValue()
-{
- mNVNameTable->removeString(mName);
- mName = NULL;
-
- switch(mType)
- {
- case NVT_STRING:
- case NVT_ASSET:
- delete [] mNameValueReference.string;
- mNameValueReference.string = NULL;
- break;
- case NVT_F32:
- delete mNameValueReference.f32;
- mNameValueReference.string = NULL;
- break;
- case NVT_S32:
- delete mNameValueReference.s32;
- mNameValueReference.string = NULL;
- break;
- case NVT_VEC3:
- delete mNameValueReference.vec3;
- mNameValueReference.string = NULL;
- break;
- case NVT_U32:
- delete mNameValueReference.u32;
- mNameValueReference.u32 = NULL;
- break;
- case NVT_U64:
- delete mNameValueReference.u64;
- mNameValueReference.u64 = NULL;
- break;
- default:
- break;
- }
-
- delete[] mNameValueReference.string;
- mNameValueReference.string = NULL;
-}
-
-char *LLNameValue::getString()
-{
- if (mType == NVT_STRING)
- {
- return mNameValueReference.string;
- }
- else
- {
- LL_ERRS() << mName << " not a string!" << LL_ENDL;
- return NULL;
- }
-}
-
-const char *LLNameValue::getAsset() const
-{
- if (mType == NVT_ASSET)
- {
- return mNameValueReference.string;
- }
- else
- {
- LL_ERRS() << mName << " not an asset!" << LL_ENDL;
- return NULL;
- }
-}
-
-F32 *LLNameValue::getF32()
-{
- if (mType == NVT_F32)
- {
- return mNameValueReference.f32;
- }
- else
- {
- LL_ERRS() << mName << " not a F32!" << LL_ENDL;
- return NULL;
- }
-}
-
-S32 *LLNameValue::getS32()
-{
- if (mType == NVT_S32)
- {
- return mNameValueReference.s32;
- }
- else
- {
- LL_ERRS() << mName << " not a S32!" << LL_ENDL;
- return NULL;
- }
-}
-
-U32 *LLNameValue::getU32()
-{
- if (mType == NVT_U32)
- {
- return mNameValueReference.u32;
- }
- else
- {
- LL_ERRS() << mName << " not a U32!" << LL_ENDL;
- return NULL;
- }
-}
-
-U64 *LLNameValue::getU64()
-{
- if (mType == NVT_U64)
- {
- return mNameValueReference.u64;
- }
- else
- {
- LL_ERRS() << mName << " not a U64!" << LL_ENDL;
- return NULL;
- }
-}
-
-void LLNameValue::getVec3(LLVector3 &vec)
-{
- if (mType == NVT_VEC3)
- {
- vec = *mNameValueReference.vec3;
- }
- else
- {
- LL_ERRS() << mName << " not a Vec3!" << LL_ENDL;
- }
-}
-
-LLVector3 *LLNameValue::getVec3()
-{
- if (mType == NVT_VEC3)
- {
- return (mNameValueReference.vec3);
- }
- else
- {
- LL_ERRS() << mName << " not a Vec3!" << LL_ENDL;
- return NULL;
- }
-}
-
-
-bool LLNameValue::sendToData() const
-{
- return (mSendto == NVS_DATA_SIM || mSendto == NVS_DATA_SIM_VIEWER);
-}
-
-
-bool LLNameValue::sendToViewer() const
-{
- return (mSendto == NVS_SIM_VIEWER || mSendto == NVS_DATA_SIM_VIEWER);
-}
-
-
-LLNameValue &LLNameValue::operator=(const LLNameValue &a)
-{
- if (mType != a.mType)
- {
- return *this;
- }
- if (mClass == NVC_READ_ONLY)
- return *this;
-
- switch(a.mType)
- {
- case NVT_STRING:
- case NVT_ASSET:
- if (mNameValueReference.string)
- delete [] mNameValueReference.string;
-
- mNameValueReference.string = new char [strlen(a.mNameValueReference.string) + 1]; /* Flawfinder: ignore */
- if(mNameValueReference.string != NULL)
- {
- strcpy(mNameValueReference.string, a.mNameValueReference.string); /* Flawfinder: ignore */
- }
- break;
- case NVT_F32:
- *mNameValueReference.f32 = *a.mNameValueReference.f32;
- break;
- case NVT_S32:
- *mNameValueReference.s32 = *a.mNameValueReference.s32;
- break;
- case NVT_VEC3:
- *mNameValueReference.vec3 = *a.mNameValueReference.vec3;
- break;
- case NVT_U32:
- *mNameValueReference.u32 = *a.mNameValueReference.u32;
- break;
- case NVT_U64:
- *mNameValueReference.u64 = *a.mNameValueReference.u64;
- break;
- default:
- LL_ERRS() << "Unknown Name value type " << (U32)a.mType << LL_ENDL;
- break;
- }
-
- return *this;
-}
-
-void LLNameValue::setString(const char *a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_STRING:
- if (a)
- {
- if (mNameValueReference.string)
- {
- delete [] mNameValueReference.string;
- }
-
- mNameValueReference.string = new char [strlen(a) + 1]; /* Flawfinder: ignore */
- if(mNameValueReference.string != NULL)
- {
- strcpy(mNameValueReference.string, a); /* Flawfinder: ignore */
- }
- }
- else
- {
- if (mNameValueReference.string)
- delete [] mNameValueReference.string;
-
- mNameValueReference.string = new char [1];
- mNameValueReference.string[0] = 0;
- }
- break;
- default:
- break;
- }
-
- return;
-}
-
-
-void LLNameValue::setAsset(const char *a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_ASSET:
- if (a)
- {
- if (mNameValueReference.string)
- {
- delete [] mNameValueReference.string;
- }
- mNameValueReference.string = new char [strlen(a) + 1]; /* Flawfinder: ignore */
- if(mNameValueReference.string != NULL)
- {
- strcpy(mNameValueReference.string, a); /* Flawfinder: ignore */
- }
- }
- else
- {
- if (mNameValueReference.string)
- delete [] mNameValueReference.string;
-
- mNameValueReference.string = new char [1];
- mNameValueReference.string[0] = 0;
- }
- break;
- default:
- break;
- }
-}
-
-
-void LLNameValue::setF32(const F32 a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_F32:
- *mNameValueReference.f32 = a;
- break;
- default:
- break;
- }
-
- return;
-}
-
-
-void LLNameValue::setS32(const S32 a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_S32:
- *mNameValueReference.s32 = a;
- break;
- case NVT_U32:
- *mNameValueReference.u32 = a;
- break;
- case NVT_F32:
- *mNameValueReference.f32 = (F32)a;
- break;
- default:
- break;
- }
-
- return;
-}
-
-
-void LLNameValue::setU32(const U32 a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_S32:
- *mNameValueReference.s32 = a;
- break;
- case NVT_U32:
- *mNameValueReference.u32 = a;
- break;
- case NVT_F32:
- *mNameValueReference.f32 = (F32)a;
- break;
- default:
- LL_ERRS() << "NameValue: Trying to set U32 into a " << mStringType << ", unknown conversion" << LL_ENDL;
- break;
- }
- return;
-}
-
-
-void LLNameValue::setVec3(const LLVector3 &a)
-{
- if (mClass == NVC_READ_ONLY)
- return;
-
- switch(mType)
- {
- case NVT_VEC3:
- *mNameValueReference.vec3 = a;
- break;
- default:
- LL_ERRS() << "NameValue: Trying to set LLVector3 into a " << mStringType << ", unknown conversion" << LL_ENDL;
- break;
- }
- return;
-}
-
-
-std::string LLNameValue::printNameValue() const
-{
- std::string buffer;
- buffer = llformat("%s %s %s %s ", mName, mStringType, mStringClass, mStringSendto);
- buffer += printData();
-// LL_INFOS() << "Name Value Length: " << buffer.size() + 1 << LL_ENDL;
- return buffer;
-}
-
-std::string LLNameValue::printData() const
-{
- std::string buffer;
- switch(mType)
- {
- case NVT_STRING:
- case NVT_ASSET:
- buffer = mNameValueReference.string;
- break;
- case NVT_F32:
- buffer = llformat("%f", *mNameValueReference.f32);
- break;
- case NVT_S32:
- buffer = llformat("%d", *mNameValueReference.s32);
- break;
- case NVT_U32:
- buffer = llformat("%u", *mNameValueReference.u32);
- break;
- case NVT_U64:
- {
- char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */
- U64_to_str(*mNameValueReference.u64, u64_string, sizeof(u64_string));
- buffer = u64_string;
- }
- break;
- case NVT_VEC3:
- buffer = llformat( "%f, %f, %f", mNameValueReference.vec3->mV[VX], mNameValueReference.vec3->mV[VY], mNameValueReference.vec3->mV[VZ]);
- break;
- default:
- LL_ERRS() << "Trying to print unknown NameValue type " << mStringType << LL_ENDL;
- break;
- }
- return buffer;
-}
-
-std::ostream& operator<<(std::ostream& s, const LLNameValue &a)
-{
- switch(a.mType)
- {
- case NVT_STRING:
- case NVT_ASSET:
- s << a.mNameValueReference.string;
- break;
- case NVT_F32:
- s << (*a.mNameValueReference.f32);
- break;
- case NVT_S32:
- s << *(a.mNameValueReference.s32);
- break;
- case NVT_U32:
- s << *(a.mNameValueReference.u32);
- break;
- case NVT_U64:
- {
- char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */
- U64_to_str(*a.mNameValueReference.u64, u64_string, sizeof(u64_string));
- s << u64_string;
- }
- break;
- case NVT_VEC3:
- s << *(a.mNameValueReference.vec3);
- break;
- default:
- LL_ERRS() << "Trying to print unknown NameValue type " << a.mStringType << LL_ENDL;
- break;
- }
- return s;
-}
-
+/**
+ * @file llnamevalue.cpp
+ * @brief class for defining name value pairs.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Examples:
+// AvatarCharacter STRING RW DSV male1
+
+#include "linden_common.h"
+
+#include "llnamevalue.h"
+
+#include "u64.h"
+#include "llstring.h"
+#include "llstringtable.h"
+
+// Anonymous enumeration to provide constants in this file.
+// *NOTE: These values may be used in sscanf statements below as their
+// value-1, so search for '2047' if you cange NV_BUFFER_LEN or '63' if
+// you change U64_BUFFER_LEN.
+enum
+{
+ NV_BUFFER_LEN = 2048,
+ U64_BUFFER_LEN = 64
+};
+
+LLStringTable gNVNameTable(256);
+
+char NameValueTypeStrings[NVT_EOF][NAME_VALUE_TYPE_STRING_LENGTH] = /*Flawfinder: Ignore*/
+{
+ "NULL",
+ "STRING",
+ "F32",
+ "S32",
+ "VEC3",
+ "U32",
+ "CAMERA", // Deprecated, but leaving in case removing completely would cause problems
+ "ASSET",
+ "U64"
+};
+
+char NameValueClassStrings[NVC_EOF][NAME_VALUE_CLASS_STRING_LENGTH] = /*Flawfinder: Ignore*/
+{
+ "NULL",
+ "R", // read only
+ "RW" // read write
+};
+
+char NameValueSendtoStrings[NVS_EOF][NAME_VALUE_SENDTO_STRING_LENGTH] = /*Flawfinder: Ignore*/
+{
+ "NULL",
+ "S", // "Sim", formerly SIM
+ "DS", // "Data Sim" formerly SIM_SPACE
+ "SV", // "Sim Viewer" formerly SIM_VIEWER
+ "DSV" // "Data Sim Viewer", formerly SIM_SPACE_VIEWER
+}; /*Flawfinder: Ignore*/
+
+
+//
+// Class
+//
+
+LLNameValue::LLNameValue()
+{
+ baseInit();
+}
+
+void LLNameValue::baseInit()
+{
+ mNVNameTable = &gNVNameTable;
+
+ mName = NULL;
+ mNameValueReference.string = NULL;
+
+ mType = NVT_NULL;
+ mStringType = NameValueTypeStrings[NVT_NULL];
+
+ mClass = NVC_NULL;
+ mStringClass = NameValueClassStrings[NVC_NULL];
+
+ mSendto = NVS_NULL;
+ mStringSendto = NameValueSendtoStrings[NVS_NULL];
+}
+
+void LLNameValue::init(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto)
+{
+ mNVNameTable = &gNVNameTable;
+
+ mName = mNVNameTable->addString(name);
+
+ // Nota Bene: Whatever global structure manages this should have these in the name table already!
+ mStringType = mNVNameTable->addString(type);
+ if (!strcmp(mStringType, "STRING"))
+ {
+ S32 string_length = (S32)strlen(data); /*Flawfinder: Ignore*/
+ mType = NVT_STRING;
+
+ delete[] mNameValueReference.string;
+
+ // two options here. . . data can either look like foo or "foo"
+ // WRONG! - this is a poorly implemented and incomplete escape
+ // mechanism. For example, using this scheme, there is no way
+ // to tell an intentional double quotes from a zero length
+ // string. This needs to excised. Phoenix
+ //if (strchr(data, '\"'))
+ //{
+ // string_length -= 2;
+ // mNameValueReference.string = new char[string_length + 1];;
+ // strncpy(mNameValueReference.string, data + 1, string_length);
+ //}
+ //else
+ //{
+ mNameValueReference.string = new char[string_length + 1];;
+ strncpy(mNameValueReference.string, data, string_length); /*Flawfinder: Ignore*/
+ //}
+ mNameValueReference.string[string_length] = 0;
+ }
+ else if (!strcmp(mStringType, "F32"))
+ {
+ mType = NVT_F32;
+ mNameValueReference.f32 = new F32((F32)atof(data));
+ }
+ else if (!strcmp(mStringType, "S32"))
+ {
+ mType = NVT_S32;
+ mNameValueReference.s32 = new S32(atoi(data));
+ }
+ else if (!strcmp(mStringType, "U64"))
+ {
+ mType = NVT_U64;
+ mNameValueReference.u64 = new U64(str_to_U64(ll_safe_string(data)));
+ }
+ else if (!strcmp(mStringType, "VEC3"))
+ {
+ mType = NVT_VEC3;
+ F32 t1, t2, t3;
+
+ // two options here. . . data can either look like 0, 1, 2 or <0, 1, 2>
+
+ if (strchr(data, '<'))
+ {
+ sscanf(data, "<%f, %f, %f>", &t1, &t2, &t3);
+ }
+ else
+ {
+ sscanf(data, "%f, %f, %f", &t1, &t2, &t3);
+ }
+
+ // finite checks
+ if (!llfinite(t1) || !llfinite(t2) || !llfinite(t3))
+ {
+ t1 = 0.f;
+ t2 = 0.f;
+ t3 = 0.f;
+ }
+
+ mNameValueReference.vec3 = new LLVector3(t1, t2, t3);
+ }
+ else if (!strcmp(mStringType, "U32"))
+ {
+ mType = NVT_U32;
+ mNameValueReference.u32 = new U32(atoi(data));
+ }
+ else if(!strcmp(mStringType, (const char*)NameValueTypeStrings[NVT_ASSET]))
+ {
+ // assets are treated like strings, except that the name has
+ // meaning to an LLAssetInfo object
+ S32 string_length = (S32)strlen(data); /*Flawfinder: Ignore*/
+ mType = NVT_ASSET;
+
+ // two options here. . . data can either look like foo or "foo"
+ // WRONG! - this is a poorly implemented and incomplete escape
+ // mechanism. For example, using this scheme, there is no way
+ // to tell an intentional double quotes from a zero length
+ // string. This needs to excised. Phoenix
+ //if (strchr(data, '\"'))
+ //{
+ // string_length -= 2;
+ // mNameValueReference.string = new char[string_length + 1];;
+ // strncpy(mNameValueReference.string, data + 1, string_length);
+ //}
+ //else
+ //{
+ mNameValueReference.string = new char[string_length + 1];;
+ strncpy(mNameValueReference.string, data, string_length); /*Flawfinder: Ignore*/
+ //}
+ mNameValueReference.string[string_length] = 0;
+ }
+ else
+ {
+ LL_WARNS() << "Unknown name value type string " << mStringType << " for " << mName << LL_ENDL;
+ mType = NVT_NULL;
+ }
+
+
+ // Nota Bene: Whatever global structure manages this should have these in the name table already!
+ if (!strcmp(nvclass, "R") ||
+ !strcmp(nvclass, "READ_ONLY")) // legacy
+ {
+ mClass = NVC_READ_ONLY;
+ mStringClass = mNVNameTable->addString("R");
+ }
+ else if (!strcmp(nvclass, "RW") ||
+ !strcmp(nvclass, "READ_WRITE")) // legacy
+ {
+ mClass = NVC_READ_WRITE;
+ mStringClass = mNVNameTable->addString("RW");
+ }
+ else
+ {
+ // assume it's bad
+ mClass = NVC_NULL;
+ mStringClass = mNVNameTable->addString(nvclass);
+ }
+
+ // Initialize the sendto variable
+ if (!strcmp(nvsendto, "S") ||
+ !strcmp(nvsendto, "SIM")) // legacy
+ {
+ mSendto = NVS_SIM;
+ mStringSendto = mNVNameTable->addString("S");
+ }
+ else if (!strcmp(nvsendto, "DS") ||
+ !strcmp(nvsendto, "SIM_SPACE")) // legacy
+ {
+ mSendto = NVS_DATA_SIM;
+ mStringSendto = mNVNameTable->addString("DS");
+ }
+ else if (!strcmp(nvsendto, "SV") ||
+ !strcmp(nvsendto, "SIM_VIEWER")) // legacy
+ {
+ mSendto = NVS_SIM_VIEWER;
+ mStringSendto = mNVNameTable->addString("SV");
+ }
+ else if (!strcmp(nvsendto, "DSV") ||
+ !strcmp(nvsendto, "SIM_SPACE_VIEWER")) // legacy
+ {
+ mSendto = NVS_DATA_SIM_VIEWER;
+ mStringSendto = mNVNameTable->addString("DSV");
+ }
+ else
+ {
+ LL_WARNS() << "LLNameValue::init() - unknown sendto field "
+ << nvsendto << " for NV " << mName << LL_ENDL;
+ mSendto = NVS_NULL;
+ mStringSendto = mNVNameTable->addString("S");
+ }
+
+}
+
+
+LLNameValue::LLNameValue(const char *name, const char *data, const char *type, const char *nvclass)
+{
+ baseInit();
+ // if not specified, send to simulator only
+ init(name, data, type, nvclass, "SIM");
+}
+
+
+LLNameValue::LLNameValue(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto)
+{
+ baseInit();
+ init(name, data, type, nvclass, nvsendto);
+}
+
+
+
+// Initialize without any initial data.
+LLNameValue::LLNameValue(const char *name, const char *type, const char *nvclass)
+{
+ baseInit();
+ mName = mNVNameTable->addString(name);
+
+ // Nota Bene: Whatever global structure manages this should have these in the name table already!
+ mStringType = mNVNameTable->addString(type);
+ if (!strcmp(mStringType, "STRING"))
+ {
+ mType = NVT_STRING;
+ mNameValueReference.string = NULL;
+ }
+ else if (!strcmp(mStringType, "F32"))
+ {
+ mType = NVT_F32;
+ mNameValueReference.f32 = NULL;
+ }
+ else if (!strcmp(mStringType, "S32"))
+ {
+ mType = NVT_S32;
+ mNameValueReference.s32 = NULL;
+ }
+ else if (!strcmp(mStringType, "VEC3"))
+ {
+ mType = NVT_VEC3;
+ mNameValueReference.vec3 = NULL;
+ }
+ else if (!strcmp(mStringType, "U32"))
+ {
+ mType = NVT_U32;
+ mNameValueReference.u32 = NULL;
+ }
+ else if (!strcmp(mStringType, "U64"))
+ {
+ mType = NVT_U64;
+ mNameValueReference.u64 = NULL;
+ }
+ else if(!strcmp(mStringType, (const char*)NameValueTypeStrings[NVT_ASSET]))
+ {
+ mType = NVT_ASSET;
+ mNameValueReference.string = NULL;
+ }
+ else
+ {
+ mType = NVT_NULL;
+ LL_INFOS() << "Unknown name-value type " << mStringType << LL_ENDL;
+ }
+
+ // Nota Bene: Whatever global structure manages this should have these in the name table already!
+ mStringClass = mNVNameTable->addString(nvclass);
+ if (!strcmp(mStringClass, "READ_ONLY"))
+ {
+ mClass = NVC_READ_ONLY;
+ }
+ else if (!strcmp(mStringClass, "READ_WRITE"))
+ {
+ mClass = NVC_READ_WRITE;
+ }
+ else
+ {
+ mClass = NVC_NULL;
+ }
+
+ // Initialize the sendto variable
+ mStringSendto = mNVNameTable->addString("SIM");
+ mSendto = NVS_SIM;
+}
+
+
+// data is in the format:
+// "NameValueName Type Class Data"
+LLNameValue::LLNameValue(const char *data)
+{
+ baseInit();
+ static char name[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
+ static char type[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
+ static char nvclass[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
+ static char nvsendto[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
+ static char nvdata[NV_BUFFER_LEN]; /*Flawfinder: ignore*/
+
+ S32 i;
+
+ S32 character_count = 0;
+ S32 length = 0;
+
+ // go to first non-whitespace character
+ while (1)
+ {
+ if ( (*(data + character_count) == ' ')
+ ||(*(data + character_count) == '\n')
+ ||(*(data + character_count) == '\t')
+ ||(*(data + character_count) == '\r'))
+ {
+ character_count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // read in the name
+ sscanf((data + character_count), "%2047s", name); /*Flawfinder: ignore*/
+
+ // bump past it and add null terminator
+ length = (S32)strlen(name); /* Flawfinder: ignore */
+ name[length] = 0;
+ character_count += length;
+
+ // go to the next non-whitespace character
+ while (1)
+ {
+ if ( (*(data + character_count) == ' ')
+ ||(*(data + character_count) == '\n')
+ ||(*(data + character_count) == '\t')
+ ||(*(data + character_count) == '\r'))
+ {
+ character_count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // read in the type
+ sscanf((data + character_count), "%2047s", type); /*Flawfinder: ignore*/
+
+ // bump past it and add null terminator
+ length = (S32)strlen(type); /* Flawfinder: ignore */
+ type[length] = 0;
+ character_count += length;
+
+ // go to the next non-whitespace character
+ while (1)
+ {
+ if ( (*(data + character_count) == ' ')
+ ||(*(data + character_count) == '\n')
+ ||(*(data + character_count) == '\t')
+ ||(*(data + character_count) == '\r'))
+ {
+ character_count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // do we have a type argument?
+ for (i = NVC_READ_ONLY; i < NVC_EOF; i++)
+ {
+ if (!strncmp(NameValueClassStrings[i], data + character_count, strlen(NameValueClassStrings[i]))) /* Flawfinder: ignore */
+ {
+ break;
+ }
+ }
+
+ if (i != NVC_EOF)
+ {
+ // yes we do!
+ // read in the class
+ sscanf((data + character_count), "%2047s", nvclass); /*Flawfinder: ignore*/
+
+ // bump past it and add null terminator
+ length = (S32)strlen(nvclass); /* Flawfinder: ignore */
+ nvclass[length] = 0;
+ character_count += length;
+
+ // go to the next non-whitespace character
+ while (1)
+ {
+ if ( (*(data + character_count) == ' ')
+ ||(*(data + character_count) == '\n')
+ ||(*(data + character_count) == '\t')
+ ||(*(data + character_count) == '\r'))
+ {
+ character_count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ // no type argument given, default to read-write
+ strncpy(nvclass, "READ_WRITE", sizeof(nvclass) -1); /* Flawfinder: ignore */
+ nvclass[sizeof(nvclass) -1] = '\0';
+ }
+
+ // Do we have a sendto argument?
+ for (i = NVS_SIM; i < NVS_EOF; i++)
+ {
+ if (!strncmp(NameValueSendtoStrings[i], data + character_count, strlen(NameValueSendtoStrings[i]))) /* Flawfinder: ignore */
+ {
+ break;
+ }
+ }
+
+ if (i != NVS_EOF)
+ {
+ // found a sendto argument
+ sscanf((data + character_count), "%2047s", nvsendto); /*Flawfinder: ignore*/
+
+ // add null terminator
+ length = (S32)strlen(nvsendto); /* Flawfinder: ignore */
+ nvsendto[length] = 0;
+ character_count += length;
+
+ // seek to next non-whitespace characer
+ while (1)
+ {
+ if ( (*(data + character_count) == ' ')
+ ||(*(data + character_count) == '\n')
+ ||(*(data + character_count) == '\t')
+ ||(*(data + character_count) == '\r'))
+ {
+ character_count++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ // no sendto argument given, default to sim only
+ strncpy(nvsendto, "SIM", sizeof(nvsendto) -1); /* Flawfinder: ignore */
+ nvsendto[sizeof(nvsendto) -1] ='\0';
+ }
+
+
+ // copy the rest character by character into data
+ length = 0;
+
+ while ( (*(nvdata + length++) = *(data + character_count++)) )
+ ;
+
+ init(name, nvdata, type, nvclass, nvsendto);
+}
+
+
+LLNameValue::~LLNameValue()
+{
+ mNVNameTable->removeString(mName);
+ mName = NULL;
+
+ switch(mType)
+ {
+ case NVT_STRING:
+ case NVT_ASSET:
+ delete [] mNameValueReference.string;
+ mNameValueReference.string = NULL;
+ break;
+ case NVT_F32:
+ delete mNameValueReference.f32;
+ mNameValueReference.string = NULL;
+ break;
+ case NVT_S32:
+ delete mNameValueReference.s32;
+ mNameValueReference.string = NULL;
+ break;
+ case NVT_VEC3:
+ delete mNameValueReference.vec3;
+ mNameValueReference.string = NULL;
+ break;
+ case NVT_U32:
+ delete mNameValueReference.u32;
+ mNameValueReference.u32 = NULL;
+ break;
+ case NVT_U64:
+ delete mNameValueReference.u64;
+ mNameValueReference.u64 = NULL;
+ break;
+ default:
+ break;
+ }
+
+ delete[] mNameValueReference.string;
+ mNameValueReference.string = NULL;
+}
+
+char *LLNameValue::getString()
+{
+ if (mType == NVT_STRING)
+ {
+ return mNameValueReference.string;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a string!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+const char *LLNameValue::getAsset() const
+{
+ if (mType == NVT_ASSET)
+ {
+ return mNameValueReference.string;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not an asset!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+F32 *LLNameValue::getF32()
+{
+ if (mType == NVT_F32)
+ {
+ return mNameValueReference.f32;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a F32!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+S32 *LLNameValue::getS32()
+{
+ if (mType == NVT_S32)
+ {
+ return mNameValueReference.s32;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a S32!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+U32 *LLNameValue::getU32()
+{
+ if (mType == NVT_U32)
+ {
+ return mNameValueReference.u32;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a U32!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+U64 *LLNameValue::getU64()
+{
+ if (mType == NVT_U64)
+ {
+ return mNameValueReference.u64;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a U64!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+void LLNameValue::getVec3(LLVector3 &vec)
+{
+ if (mType == NVT_VEC3)
+ {
+ vec = *mNameValueReference.vec3;
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a Vec3!" << LL_ENDL;
+ }
+}
+
+LLVector3 *LLNameValue::getVec3()
+{
+ if (mType == NVT_VEC3)
+ {
+ return (mNameValueReference.vec3);
+ }
+ else
+ {
+ LL_ERRS() << mName << " not a Vec3!" << LL_ENDL;
+ return NULL;
+ }
+}
+
+
+bool LLNameValue::sendToData() const
+{
+ return (mSendto == NVS_DATA_SIM || mSendto == NVS_DATA_SIM_VIEWER);
+}
+
+
+bool LLNameValue::sendToViewer() const
+{
+ return (mSendto == NVS_SIM_VIEWER || mSendto == NVS_DATA_SIM_VIEWER);
+}
+
+
+LLNameValue &LLNameValue::operator=(const LLNameValue &a)
+{
+ if (mType != a.mType)
+ {
+ return *this;
+ }
+ if (mClass == NVC_READ_ONLY)
+ return *this;
+
+ switch(a.mType)
+ {
+ case NVT_STRING:
+ case NVT_ASSET:
+ if (mNameValueReference.string)
+ delete [] mNameValueReference.string;
+
+ mNameValueReference.string = new char [strlen(a.mNameValueReference.string) + 1]; /* Flawfinder: ignore */
+ if(mNameValueReference.string != NULL)
+ {
+ strcpy(mNameValueReference.string, a.mNameValueReference.string); /* Flawfinder: ignore */
+ }
+ break;
+ case NVT_F32:
+ *mNameValueReference.f32 = *a.mNameValueReference.f32;
+ break;
+ case NVT_S32:
+ *mNameValueReference.s32 = *a.mNameValueReference.s32;
+ break;
+ case NVT_VEC3:
+ *mNameValueReference.vec3 = *a.mNameValueReference.vec3;
+ break;
+ case NVT_U32:
+ *mNameValueReference.u32 = *a.mNameValueReference.u32;
+ break;
+ case NVT_U64:
+ *mNameValueReference.u64 = *a.mNameValueReference.u64;
+ break;
+ default:
+ LL_ERRS() << "Unknown Name value type " << (U32)a.mType << LL_ENDL;
+ break;
+ }
+
+ return *this;
+}
+
+void LLNameValue::setString(const char *a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_STRING:
+ if (a)
+ {
+ if (mNameValueReference.string)
+ {
+ delete [] mNameValueReference.string;
+ }
+
+ mNameValueReference.string = new char [strlen(a) + 1]; /* Flawfinder: ignore */
+ if(mNameValueReference.string != NULL)
+ {
+ strcpy(mNameValueReference.string, a); /* Flawfinder: ignore */
+ }
+ }
+ else
+ {
+ if (mNameValueReference.string)
+ delete [] mNameValueReference.string;
+
+ mNameValueReference.string = new char [1];
+ mNameValueReference.string[0] = 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+
+void LLNameValue::setAsset(const char *a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_ASSET:
+ if (a)
+ {
+ if (mNameValueReference.string)
+ {
+ delete [] mNameValueReference.string;
+ }
+ mNameValueReference.string = new char [strlen(a) + 1]; /* Flawfinder: ignore */
+ if(mNameValueReference.string != NULL)
+ {
+ strcpy(mNameValueReference.string, a); /* Flawfinder: ignore */
+ }
+ }
+ else
+ {
+ if (mNameValueReference.string)
+ delete [] mNameValueReference.string;
+
+ mNameValueReference.string = new char [1];
+ mNameValueReference.string[0] = 0;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+void LLNameValue::setF32(const F32 a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_F32:
+ *mNameValueReference.f32 = a;
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+
+void LLNameValue::setS32(const S32 a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_S32:
+ *mNameValueReference.s32 = a;
+ break;
+ case NVT_U32:
+ *mNameValueReference.u32 = a;
+ break;
+ case NVT_F32:
+ *mNameValueReference.f32 = (F32)a;
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+
+void LLNameValue::setU32(const U32 a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_S32:
+ *mNameValueReference.s32 = a;
+ break;
+ case NVT_U32:
+ *mNameValueReference.u32 = a;
+ break;
+ case NVT_F32:
+ *mNameValueReference.f32 = (F32)a;
+ break;
+ default:
+ LL_ERRS() << "NameValue: Trying to set U32 into a " << mStringType << ", unknown conversion" << LL_ENDL;
+ break;
+ }
+ return;
+}
+
+
+void LLNameValue::setVec3(const LLVector3 &a)
+{
+ if (mClass == NVC_READ_ONLY)
+ return;
+
+ switch(mType)
+ {
+ case NVT_VEC3:
+ *mNameValueReference.vec3 = a;
+ break;
+ default:
+ LL_ERRS() << "NameValue: Trying to set LLVector3 into a " << mStringType << ", unknown conversion" << LL_ENDL;
+ break;
+ }
+ return;
+}
+
+
+std::string LLNameValue::printNameValue() const
+{
+ std::string buffer;
+ buffer = llformat("%s %s %s %s ", mName, mStringType, mStringClass, mStringSendto);
+ buffer += printData();
+// LL_INFOS() << "Name Value Length: " << buffer.size() + 1 << LL_ENDL;
+ return buffer;
+}
+
+std::string LLNameValue::printData() const
+{
+ std::string buffer;
+ switch(mType)
+ {
+ case NVT_STRING:
+ case NVT_ASSET:
+ buffer = mNameValueReference.string;
+ break;
+ case NVT_F32:
+ buffer = llformat("%f", *mNameValueReference.f32);
+ break;
+ case NVT_S32:
+ buffer = llformat("%d", *mNameValueReference.s32);
+ break;
+ case NVT_U32:
+ buffer = llformat("%u", *mNameValueReference.u32);
+ break;
+ case NVT_U64:
+ {
+ char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */
+ U64_to_str(*mNameValueReference.u64, u64_string, sizeof(u64_string));
+ buffer = u64_string;
+ }
+ break;
+ case NVT_VEC3:
+ buffer = llformat( "%f, %f, %f", mNameValueReference.vec3->mV[VX], mNameValueReference.vec3->mV[VY], mNameValueReference.vec3->mV[VZ]);
+ break;
+ default:
+ LL_ERRS() << "Trying to print unknown NameValue type " << mStringType << LL_ENDL;
+ break;
+ }
+ return buffer;
+}
+
+std::ostream& operator<<(std::ostream& s, const LLNameValue &a)
+{
+ switch(a.mType)
+ {
+ case NVT_STRING:
+ case NVT_ASSET:
+ s << a.mNameValueReference.string;
+ break;
+ case NVT_F32:
+ s << (*a.mNameValueReference.f32);
+ break;
+ case NVT_S32:
+ s << *(a.mNameValueReference.s32);
+ break;
+ case NVT_U32:
+ s << *(a.mNameValueReference.u32);
+ break;
+ case NVT_U64:
+ {
+ char u64_string[U64_BUFFER_LEN]; /* Flawfinder: ignore */
+ U64_to_str(*a.mNameValueReference.u64, u64_string, sizeof(u64_string));
+ s << u64_string;
+ }
+ break;
+ case NVT_VEC3:
+ s << *(a.mNameValueReference.vec3);
+ break;
+ default:
+ LL_ERRS() << "Trying to print unknown NameValue type " << a.mStringType << LL_ENDL;
+ break;
+ }
+ return s;
+}
+
diff --git a/indra/llmessage/llnamevalue.h b/indra/llmessage/llnamevalue.h
index 92b20284ef..6876c6020d 100644
--- a/indra/llmessage/llnamevalue.h
+++ b/indra/llmessage/llnamevalue.h
@@ -1,183 +1,183 @@
-/**
- * @file llnamevalue.h
- * @brief class for defining name value pairs.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLNAMEVALUE_H
-#define LL_LLNAMEVALUE_H
-
-// As of January 2008, I believe we only use the following name-value
-// pairs. This is hard to prove because they are initialized from
-// strings. JC
-//
-// FirstName STRING
-// LastName STRING
-// AttachPt U32
-// AttachmentItemId STRING
-// Title STRING
-// AttachmentOffset VEC3
-// AttachmentOrientation VEC3
-// SitObject STRING
-// SitPosition VEC3
-
-#include "llstringtable.h"
-#include "llmath.h"
-#include "v3math.h"
-#include "lldbstrings.h"
-
-class LLNameValue;
-class LLStringTable;
-
-typedef enum e_name_value_types
-{
- NVT_NULL,
- NVT_STRING,
- NVT_F32,
- NVT_S32,
- NVT_VEC3,
- NVT_U32,
- NVT_CAMERA, // Deprecated, but leaving in case removing this will cause problems
- NVT_ASSET,
- NVT_U64,
- NVT_EOF
-} ENameValueType;
-
-typedef enum e_name_value_class
-{
- NVC_NULL,
- NVC_READ_ONLY,
- NVC_READ_WRITE,
- NVC_EOF
-} ENameValueClass;
-
-typedef enum e_name_value_sento
-{
- NVS_NULL,
- NVS_SIM,
- NVS_DATA_SIM,
- NVS_SIM_VIEWER,
- NVS_DATA_SIM_VIEWER,
- NVS_EOF
-} ENameValueSendto;
-
-
-// NameValues can always be "printed" into a buffer of this length.
-const U32 NAME_VALUE_BUF_SIZE = 1024;
-
-
-const U32 NAME_VALUE_TYPE_STRING_LENGTH = 8;
-const U32 NAME_VALUE_CLASS_STRING_LENGTH = 16;
-const U32 NAME_VALUE_SENDTO_STRING_LENGTH = 18;
-const U32 NAME_VALUE_DATA_SIZE =
- NAME_VALUE_BUF_SIZE -
- ( DB_NV_NAME_BUF_SIZE +
- NAME_VALUE_TYPE_STRING_LENGTH +
- NAME_VALUE_CLASS_STRING_LENGTH +
- NAME_VALUE_SENDTO_STRING_LENGTH );
-
-
-extern char NameValueTypeStrings[NVT_EOF][NAME_VALUE_TYPE_STRING_LENGTH]; /* Flawfinder: Ignore */
-extern char NameValueClassStrings[NVC_EOF][NAME_VALUE_CLASS_STRING_LENGTH]; /* Flawfinder: Ignore */
-extern char NameValueSendtoStrings[NVS_EOF][NAME_VALUE_SENDTO_STRING_LENGTH]; /* Flawfinder: Ignore */
-
-typedef union u_name_value_reference
-{
- char *string;
- F32 *f32;
- S32 *s32;
- LLVector3 *vec3;
- U32 *u32;
- U64 *u64;
-} UNameValueReference;
-
-
-class LLNameValue
-{
-public:
- void baseInit();
- void init(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto );
-
- LLNameValue();
- LLNameValue(const char *data);
- LLNameValue(const char *name, const char *type, const char *nvclass );
- LLNameValue(const char *name, const char *data, const char *type, const char *nvclass );
- LLNameValue(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto );
-
- ~LLNameValue();
-
- char *getString();
- const char *getAsset() const;
- F32 *getF32();
- S32 *getS32();
- void getVec3(LLVector3 &vec);
- LLVector3 *getVec3();
- U32 *getU32();
- U64 *getU64();
-
- const char *getType() const { return mStringType; }
- const char *getClass() const { return mStringClass; }
- const char *getSendto() const { return mStringSendto; }
-
- bool sendToData() const;
- bool sendToViewer() const;
-
- void callCallback();
- std::string printNameValue() const;
- std::string printData() const;
-
- ENameValueType getTypeEnum() const { return mType; }
- ENameValueClass getClassEnum() const { return mClass; }
- ENameValueSendto getSendtoEnum() const { return mSendto; }
-
- LLNameValue &operator=(const LLNameValue &a);
- void setString(const char *a);
- void setAsset(const char *a);
- void setF32(const F32 a);
- void setS32(const S32 a);
- void setVec3(const LLVector3 &a);
- void setU32(const U32 a);
-
- friend std::ostream& operator<<(std::ostream& s, const LLNameValue &a);
-
-private:
- void printNameValue(std::ostream& s);
-
-public:
- char *mName;
-
- char *mStringType;
- ENameValueType mType;
- char *mStringClass;
- ENameValueClass mClass;
- char *mStringSendto;
- ENameValueSendto mSendto;
-
- UNameValueReference mNameValueReference;
- LLStringTable *mNVNameTable;
-};
-
-extern LLStringTable gNVNameTable;
-
-
-#endif
+/**
+ * @file llnamevalue.h
+ * @brief class for defining name value pairs.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNAMEVALUE_H
+#define LL_LLNAMEVALUE_H
+
+// As of January 2008, I believe we only use the following name-value
+// pairs. This is hard to prove because they are initialized from
+// strings. JC
+//
+// FirstName STRING
+// LastName STRING
+// AttachPt U32
+// AttachmentItemId STRING
+// Title STRING
+// AttachmentOffset VEC3
+// AttachmentOrientation VEC3
+// SitObject STRING
+// SitPosition VEC3
+
+#include "llstringtable.h"
+#include "llmath.h"
+#include "v3math.h"
+#include "lldbstrings.h"
+
+class LLNameValue;
+class LLStringTable;
+
+typedef enum e_name_value_types
+{
+ NVT_NULL,
+ NVT_STRING,
+ NVT_F32,
+ NVT_S32,
+ NVT_VEC3,
+ NVT_U32,
+ NVT_CAMERA, // Deprecated, but leaving in case removing this will cause problems
+ NVT_ASSET,
+ NVT_U64,
+ NVT_EOF
+} ENameValueType;
+
+typedef enum e_name_value_class
+{
+ NVC_NULL,
+ NVC_READ_ONLY,
+ NVC_READ_WRITE,
+ NVC_EOF
+} ENameValueClass;
+
+typedef enum e_name_value_sento
+{
+ NVS_NULL,
+ NVS_SIM,
+ NVS_DATA_SIM,
+ NVS_SIM_VIEWER,
+ NVS_DATA_SIM_VIEWER,
+ NVS_EOF
+} ENameValueSendto;
+
+
+// NameValues can always be "printed" into a buffer of this length.
+const U32 NAME_VALUE_BUF_SIZE = 1024;
+
+
+const U32 NAME_VALUE_TYPE_STRING_LENGTH = 8;
+const U32 NAME_VALUE_CLASS_STRING_LENGTH = 16;
+const U32 NAME_VALUE_SENDTO_STRING_LENGTH = 18;
+const U32 NAME_VALUE_DATA_SIZE =
+ NAME_VALUE_BUF_SIZE -
+ ( DB_NV_NAME_BUF_SIZE +
+ NAME_VALUE_TYPE_STRING_LENGTH +
+ NAME_VALUE_CLASS_STRING_LENGTH +
+ NAME_VALUE_SENDTO_STRING_LENGTH );
+
+
+extern char NameValueTypeStrings[NVT_EOF][NAME_VALUE_TYPE_STRING_LENGTH]; /* Flawfinder: Ignore */
+extern char NameValueClassStrings[NVC_EOF][NAME_VALUE_CLASS_STRING_LENGTH]; /* Flawfinder: Ignore */
+extern char NameValueSendtoStrings[NVS_EOF][NAME_VALUE_SENDTO_STRING_LENGTH]; /* Flawfinder: Ignore */
+
+typedef union u_name_value_reference
+{
+ char *string;
+ F32 *f32;
+ S32 *s32;
+ LLVector3 *vec3;
+ U32 *u32;
+ U64 *u64;
+} UNameValueReference;
+
+
+class LLNameValue
+{
+public:
+ void baseInit();
+ void init(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto );
+
+ LLNameValue();
+ LLNameValue(const char *data);
+ LLNameValue(const char *name, const char *type, const char *nvclass );
+ LLNameValue(const char *name, const char *data, const char *type, const char *nvclass );
+ LLNameValue(const char *name, const char *data, const char *type, const char *nvclass, const char *nvsendto );
+
+ ~LLNameValue();
+
+ char *getString();
+ const char *getAsset() const;
+ F32 *getF32();
+ S32 *getS32();
+ void getVec3(LLVector3 &vec);
+ LLVector3 *getVec3();
+ U32 *getU32();
+ U64 *getU64();
+
+ const char *getType() const { return mStringType; }
+ const char *getClass() const { return mStringClass; }
+ const char *getSendto() const { return mStringSendto; }
+
+ bool sendToData() const;
+ bool sendToViewer() const;
+
+ void callCallback();
+ std::string printNameValue() const;
+ std::string printData() const;
+
+ ENameValueType getTypeEnum() const { return mType; }
+ ENameValueClass getClassEnum() const { return mClass; }
+ ENameValueSendto getSendtoEnum() const { return mSendto; }
+
+ LLNameValue &operator=(const LLNameValue &a);
+ void setString(const char *a);
+ void setAsset(const char *a);
+ void setF32(const F32 a);
+ void setS32(const S32 a);
+ void setVec3(const LLVector3 &a);
+ void setU32(const U32 a);
+
+ friend std::ostream& operator<<(std::ostream& s, const LLNameValue &a);
+
+private:
+ void printNameValue(std::ostream& s);
+
+public:
+ char *mName;
+
+ char *mStringType;
+ ENameValueType mType;
+ char *mStringClass;
+ ENameValueClass mClass;
+ char *mStringSendto;
+ ENameValueSendto mSendto;
+
+ UNameValueReference mNameValueReference;
+ LLStringTable *mNVNameTable;
+};
+
+extern LLStringTable gNVNameTable;
+
+
+#endif
diff --git a/indra/llmessage/llnullcipher.cpp b/indra/llmessage/llnullcipher.cpp
index b32e7e6fa6..47230f58d4 100644
--- a/indra/llmessage/llnullcipher.cpp
+++ b/indra/llmessage/llnullcipher.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llnullcipher.cpp
* @brief Implementation of a cipher which does not encrypt.
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,25 +34,25 @@
U32 LLNullCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
{
- if((src_len == dst_len) && src && dst)
- {
- memmove(dst, src, src_len);
- return src_len;
- }
- return 0;
+ if((src_len == dst_len) && src && dst)
+ {
+ memmove(dst, src, src_len);
+ return src_len;
+ }
+ return 0;
}
U32 LLNullCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
{
- if((src_len == dst_len) && src && dst)
- {
- memmove(dst, src, src_len);
- return src_len;
- }
- return 0;
+ if((src_len == dst_len) && src && dst)
+ {
+ memmove(dst, src, src_len);
+ return src_len;
+ }
+ return 0;
}
U32 LLNullCipher::requiredEncryptionSpace(U32 len) const
{
- return len;
+ return len;
}
diff --git a/indra/llmessage/llnullcipher.h b/indra/llmessage/llnullcipher.h
index a9f9a1ce03..8b397d46cf 100644
--- a/indra/llmessage/llnullcipher.h
+++ b/indra/llmessage/llnullcipher.h
@@ -1,24 +1,24 @@
-/**
+/**
* @file llnullcipher.h
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,11 +38,11 @@
class LLNullCipher : public LLCipher
{
public:
- LLNullCipher() {}
- virtual ~LLNullCipher() {}
- virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
- virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
- virtual U32 requiredEncryptionSpace(U32 src_len) const;
+ LLNullCipher() {}
+ virtual ~LLNullCipher() {}
+ virtual U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
+ virtual U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len);
+ virtual U32 requiredEncryptionSpace(U32 src_len) const;
};
#endif
diff --git a/indra/llmessage/llpacketack.cpp b/indra/llmessage/llpacketack.cpp
index 8e04934286..19d21bf5d0 100644
--- a/indra/llmessage/llpacketack.cpp
+++ b/indra/llmessage/llpacketack.cpp
@@ -1,82 +1,82 @@
-/**
- * @file llpacketack.cpp
- * @author Phoenix
- * @date 2007-05-09
- * @brief Implementation of the LLReliablePacket.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llpacketack.h"
-
-#if !LL_WINDOWS
-#include <netinet/in.h>
-#else
-#include "winsock2.h"
-#endif
-
-#include "message.h"
-
-LLReliablePacket::LLReliablePacket(
- S32 socket,
- U8* buf_ptr,
- S32 buf_len,
- LLReliablePacketParams* params) :
- mBuffer(NULL),
- mBufferLength(0)
-{
- if (params)
- {
- mHost = params->mHost;
- mRetries = params->mRetries;
- mPingBasedRetry = params->mPingBasedRetry;
- mTimeout = F32Seconds(params->mTimeout);
- mCallback = params->mCallback;
- mCallbackData = params->mCallbackData;
- mMessageName = params->mMessageName;
- }
- else
- {
- mRetries = 0;
- mPingBasedRetry = true;
- mTimeout = F32Seconds(0.f);
- mCallback = NULL;
- mCallbackData = NULL;
- mMessageName = NULL;
- }
-
- mExpirationTime = (F64Seconds)totalTime() + mTimeout;
- mPacketID = ntohl(*((U32*)(&buf_ptr[PHL_PACKET_ID])));
-
- mSocket = socket;
- if (mRetries)
- {
- mBuffer = new U8[buf_len];
- if (mBuffer != NULL)
- {
- memcpy(mBuffer,buf_ptr,buf_len); /*Flawfinder: ignore*/
- mBufferLength = buf_len;
- }
-
- }
-}
+/**
+ * @file llpacketack.cpp
+ * @author Phoenix
+ * @date 2007-05-09
+ * @brief Implementation of the LLReliablePacket.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llpacketack.h"
+
+#if !LL_WINDOWS
+#include <netinet/in.h>
+#else
+#include "winsock2.h"
+#endif
+
+#include "message.h"
+
+LLReliablePacket::LLReliablePacket(
+ S32 socket,
+ U8* buf_ptr,
+ S32 buf_len,
+ LLReliablePacketParams* params) :
+ mBuffer(NULL),
+ mBufferLength(0)
+{
+ if (params)
+ {
+ mHost = params->mHost;
+ mRetries = params->mRetries;
+ mPingBasedRetry = params->mPingBasedRetry;
+ mTimeout = F32Seconds(params->mTimeout);
+ mCallback = params->mCallback;
+ mCallbackData = params->mCallbackData;
+ mMessageName = params->mMessageName;
+ }
+ else
+ {
+ mRetries = 0;
+ mPingBasedRetry = true;
+ mTimeout = F32Seconds(0.f);
+ mCallback = NULL;
+ mCallbackData = NULL;
+ mMessageName = NULL;
+ }
+
+ mExpirationTime = (F64Seconds)totalTime() + mTimeout;
+ mPacketID = ntohl(*((U32*)(&buf_ptr[PHL_PACKET_ID])));
+
+ mSocket = socket;
+ if (mRetries)
+ {
+ mBuffer = new U8[buf_len];
+ if (mBuffer != NULL)
+ {
+ memcpy(mBuffer,buf_ptr,buf_len); /*Flawfinder: ignore*/
+ mBufferLength = buf_len;
+ }
+
+ }
+}
diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h
index 76e2e43acb..c359ec2c0e 100644
--- a/indra/llmessage/llpacketack.h
+++ b/indra/llmessage/llpacketack.h
@@ -1,116 +1,116 @@
-/**
- * @file llpacketack.h
- * @brief Reliable UDP helpers for the message system.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPACKETACK_H
-#define LL_LLPACKETACK_H
-
-#include "llhost.h"
-#include "llunits.h"
-
-class LLReliablePacketParams
-{
-public:
- LLHost mHost;
- S32 mRetries;
- bool mPingBasedRetry;
- F32Seconds mTimeout;
- void (*mCallback)(void **,S32);
- void** mCallbackData;
- char* mMessageName;
-
-public:
- LLReliablePacketParams()
- {
- clear();
- };
-
- ~LLReliablePacketParams() { };
-
- void clear()
- {
- mHost.invalidate();
- mRetries = 0;
- mPingBasedRetry = true;
- mTimeout = F32Seconds(0.f);
- mCallback = NULL;
- mCallbackData = NULL;
- mMessageName = NULL;
- };
-
- void set(
- const LLHost& host,
- S32 retries,
- bool ping_based_retry,
- F32Seconds timeout,
- void (*callback)(void**,S32),
- void** callback_data, char* name)
- {
- mHost = host;
- mRetries = retries;
- mPingBasedRetry = ping_based_retry;
- mTimeout = timeout;
- mCallback = callback;
- mCallbackData = callback_data;
- mMessageName = name;
- };
-};
-
-class LLReliablePacket
-{
-public:
- LLReliablePacket(
- S32 socket,
- U8* buf_ptr,
- S32 buf_len,
- LLReliablePacketParams* params);
- ~LLReliablePacket()
- {
- mCallback = NULL;
- delete [] mBuffer;
- mBuffer = NULL;
- };
-
- friend class LLCircuitData;
-protected:
- S32 mSocket;
- LLHost mHost;
- S32 mRetries;
- bool mPingBasedRetry;
- F32Seconds mTimeout;
- void (*mCallback)(void**,S32);
- void** mCallbackData;
- char* mMessageName;
-
- U8* mBuffer;
- S32 mBufferLength;
-
- TPACKETID mPacketID;
-
- F64Seconds mExpirationTime;
-};
-
-#endif
-
+/**
+ * @file llpacketack.h
+ * @brief Reliable UDP helpers for the message system.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPACKETACK_H
+#define LL_LLPACKETACK_H
+
+#include "llhost.h"
+#include "llunits.h"
+
+class LLReliablePacketParams
+{
+public:
+ LLHost mHost;
+ S32 mRetries;
+ bool mPingBasedRetry;
+ F32Seconds mTimeout;
+ void (*mCallback)(void **,S32);
+ void** mCallbackData;
+ char* mMessageName;
+
+public:
+ LLReliablePacketParams()
+ {
+ clear();
+ };
+
+ ~LLReliablePacketParams() { };
+
+ void clear()
+ {
+ mHost.invalidate();
+ mRetries = 0;
+ mPingBasedRetry = true;
+ mTimeout = F32Seconds(0.f);
+ mCallback = NULL;
+ mCallbackData = NULL;
+ mMessageName = NULL;
+ };
+
+ void set(
+ const LLHost& host,
+ S32 retries,
+ bool ping_based_retry,
+ F32Seconds timeout,
+ void (*callback)(void**,S32),
+ void** callback_data, char* name)
+ {
+ mHost = host;
+ mRetries = retries;
+ mPingBasedRetry = ping_based_retry;
+ mTimeout = timeout;
+ mCallback = callback;
+ mCallbackData = callback_data;
+ mMessageName = name;
+ };
+};
+
+class LLReliablePacket
+{
+public:
+ LLReliablePacket(
+ S32 socket,
+ U8* buf_ptr,
+ S32 buf_len,
+ LLReliablePacketParams* params);
+ ~LLReliablePacket()
+ {
+ mCallback = NULL;
+ delete [] mBuffer;
+ mBuffer = NULL;
+ };
+
+ friend class LLCircuitData;
+protected:
+ S32 mSocket;
+ LLHost mHost;
+ S32 mRetries;
+ bool mPingBasedRetry;
+ F32Seconds mTimeout;
+ void (*mCallback)(void**,S32);
+ void** mCallbackData;
+ char* mMessageName;
+
+ U8* mBuffer;
+ S32 mBufferLength;
+
+ TPACKETID mPacketID;
+
+ F64Seconds mExpirationTime;
+};
+
+#endif
+
diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp
index ccf991b1a7..dc5c7a73cb 100644
--- a/indra/llmessage/llpacketbuffer.cpp
+++ b/indra/llmessage/llpacketbuffer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpacketbuffer.cpp
* @brief implementation of LLPacketBuffer class for a packet.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,27 +36,27 @@
LLPacketBuffer::LLPacketBuffer(const LLHost &host, const char *datap, const S32 size) : mHost(host)
{
- mSize = 0;
- mData[0] = '!';
+ mSize = 0;
+ mData[0] = '!';
+
+ if (size > NET_BUFFER_SIZE)
+ {
+ LL_ERRS() << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << LL_ENDL;
+ }
+ else
+ {
+ if (datap != NULL)
+ {
+ memcpy(mData, datap, size);
+ mSize = size;
+ }
+ }
- if (size > NET_BUFFER_SIZE)
- {
- LL_ERRS() << "Sending packet > " << NET_BUFFER_SIZE << " of size " << size << LL_ENDL;
- }
- else
- {
- if (datap != NULL)
- {
- memcpy(mData, datap, size);
- mSize = size;
- }
- }
-
}
LLPacketBuffer::LLPacketBuffer (S32 hSocket)
{
- init(hSocket);
+ init(hSocket);
}
///////////////////////////////////////////////////////////
@@ -69,8 +69,8 @@ LLPacketBuffer::~LLPacketBuffer ()
void LLPacketBuffer::init (S32 hSocket)
{
- mSize = receive_packet(hSocket, mData);
- mHost = ::get_sender();
- mReceivingIF = ::get_receiving_interface();
+ mSize = receive_packet(hSocket, mData);
+ mHost = ::get_sender();
+ mReceivingIF = ::get_receiving_interface();
}
diff --git a/indra/llmessage/llpacketbuffer.h b/indra/llmessage/llpacketbuffer.h
index 14b6f9d5d2..a2d2973fb0 100644
--- a/indra/llmessage/llpacketbuffer.h
+++ b/indra/llmessage/llpacketbuffer.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpacketbuffer.h
* @brief definition of LLPacketBuffer class for implementing a
* resend, drop, or delay in packet transmissions.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,27 +28,27 @@
#ifndef LL_LLPACKETBUFFER_H
#define LL_LLPACKETBUFFER_H
-#include "net.h" // for NET_BUFFER_SIZE
+#include "net.h" // for NET_BUFFER_SIZE
#include "llhost.h"
class LLPacketBuffer
{
public:
- LLPacketBuffer(const LLHost &host, const char *datap, const S32 size);
- LLPacketBuffer(S32 hSocket); // receive a packet
- ~LLPacketBuffer();
+ LLPacketBuffer(const LLHost &host, const char *datap, const S32 size);
+ LLPacketBuffer(S32 hSocket); // receive a packet
+ ~LLPacketBuffer();
- S32 getSize() const { return mSize; }
- const char *getData() const { return mData; }
- LLHost getHost() const { return mHost; }
- LLHost getReceivingInterface() const { return mReceivingIF; }
- void init(S32 hSocket);
+ S32 getSize() const { return mSize; }
+ const char *getData() const { return mData; }
+ LLHost getHost() const { return mHost; }
+ LLHost getReceivingInterface() const { return mReceivingIF; }
+ void init(S32 hSocket);
protected:
- char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */
- S32 mSize; // size of buffer in bytes
- LLHost mHost; // source/dest IP and port
- LLHost mReceivingIF; // source/dest IP and port
+ char mData[NET_BUFFER_SIZE]; // packet data /* Flawfinder : ignore */
+ S32 mSize; // size of buffer in bytes
+ LLHost mHost; // source/dest IP and port
+ LLHost mReceivingIF; // source/dest IP and port
};
#endif
diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp
index 8e098bfc8c..8f96554939 100644
--- a/indra/llmessage/llpacketring.cpp
+++ b/indra/llmessage/llpacketring.cpp
@@ -1,371 +1,371 @@
-/**
- * @file llpacketring.cpp
- * @brief implementation of LLPacketRing class for a packet.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llpacketring.h"
-
-#if LL_WINDOWS
- #include <winsock2.h>
-#else
- #include <sys/socket.h>
- #include <netinet/in.h>
-#endif
-
-// linden library includes
-#include "llerror.h"
-#include "lltimer.h"
-#include "llproxy.h"
-#include "llrand.h"
-#include "message.h"
-#include "u64.h"
-
-///////////////////////////////////////////////////////////
-LLPacketRing::LLPacketRing () :
- mUseInThrottle(false),
- mUseOutThrottle(false),
- mInThrottle(256000.f),
- mOutThrottle(64000.f),
- mActualBitsIn(0),
- mActualBitsOut(0),
- mMaxBufferLength(64000),
- mInBufferLength(0),
- mOutBufferLength(0),
- mDropPercentage(0.0f),
- mPacketsToDrop(0x0)
-{
-}
-
-///////////////////////////////////////////////////////////
-LLPacketRing::~LLPacketRing ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-void LLPacketRing::cleanup ()
-{
- LLPacketBuffer *packetp;
-
- while (!mReceiveQueue.empty())
- {
- packetp = mReceiveQueue.front();
- delete packetp;
- mReceiveQueue.pop();
- }
-
- while (!mSendQueue.empty())
- {
- packetp = mSendQueue.front();
- delete packetp;
- mSendQueue.pop();
- }
-}
-
-///////////////////////////////////////////////////////////
-void LLPacketRing::dropPackets (U32 num_to_drop)
-{
- mPacketsToDrop += num_to_drop;
-}
-
-///////////////////////////////////////////////////////////
-void LLPacketRing::setDropPercentage (F32 percent_to_drop)
-{
- mDropPercentage = percent_to_drop;
-}
-
-void LLPacketRing::setUseInThrottle(const bool use_throttle)
-{
- mUseInThrottle = use_throttle;
-}
-
-void LLPacketRing::setUseOutThrottle(const bool use_throttle)
-{
- mUseOutThrottle = use_throttle;
-}
-
-void LLPacketRing::setInBandwidth(const F32 bps)
-{
- mInThrottle.setRate(bps);
-}
-
-void LLPacketRing::setOutBandwidth(const F32 bps)
-{
- mOutThrottle.setRate(bps);
-}
-///////////////////////////////////////////////////////////
-S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
-{
-
- if (mInThrottle.checkOverflow(0))
- {
- // We don't have enough bandwidth, don't give them a packet.
- return 0;
- }
-
- LLPacketBuffer *packetp = NULL;
- if (mReceiveQueue.empty())
- {
- // No packets on the queue, don't give them any.
- return 0;
- }
-
- S32 packet_size = 0;
- packetp = mReceiveQueue.front();
- mReceiveQueue.pop();
- packet_size = packetp->getSize();
- if (packetp->getData() != NULL)
- {
- memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
- }
- // need to set sender IP/port!!
- mLastSender = packetp->getHost();
- mLastReceivingIF = packetp->getReceivingInterface();
- delete packetp;
-
- this->mInBufferLength -= packet_size;
-
- // Adjust the throttle
- mInThrottle.throttleOverflow(packet_size * 8.f);
- return packet_size;
-}
-
-///////////////////////////////////////////////////////////
-S32 LLPacketRing::receivePacket (S32 socket, char *datap)
-{
- S32 packet_size = 0;
-
- // If using the throttle, simulate a limited size input buffer.
- if (mUseInThrottle)
- {
- bool done = false;
-
- // push any current net packet (if any) onto delay ring
- while (!done)
- {
- LLPacketBuffer *packetp;
- packetp = new LLPacketBuffer(socket);
-
- if (packetp->getSize())
- {
- mActualBitsIn += packetp->getSize() * 8;
-
- // Fake packet loss
- if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
- {
- mPacketsToDrop++;
- }
-
- if (mPacketsToDrop)
- {
- delete packetp;
- packetp = NULL;
- packet_size = 0;
- mPacketsToDrop--;
- }
- }
-
- // If we faked packet loss, then we don't have a packet
- // to use for buffer overflow testing
- if (packetp)
- {
- if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
- {
- // Toss it.
- LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL;
- delete packetp;
- packetp = NULL;
- }
- else if (packetp->getSize())
- {
- mReceiveQueue.push(packetp);
- mInBufferLength += packetp->getSize();
- }
- else
- {
- delete packetp;
- packetp = NULL;
- done = true;
- }
- }
- else
- {
- // No packetp, keep going? - no packetp == faked packet loss
- }
- }
-
- // Now, grab data off of the receive queue according to our
- // throttled bandwidth settings.
- packet_size = receiveFromRing(socket, datap);
- }
- else
- {
- // no delay, pull straight from net
- if (LLProxy::isSOCKSProxyEnabled())
- {
- U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
- packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
-
- if (packet_size > SOCKS_HEADER_SIZE)
- {
- // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
- memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
- proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
- mLastSender.setAddress(header->addr);
- mLastSender.setPort(ntohs(header->port));
-
- packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
- }
- else
- {
- packet_size = 0;
- }
- }
- else
- {
- packet_size = receive_packet(socket, datap);
- mLastSender = ::get_sender();
- }
-
- mLastReceivingIF = ::get_receiving_interface();
-
- if (packet_size) // did we actually get a packet?
- {
- if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
- {
- mPacketsToDrop++;
- }
-
- if (mPacketsToDrop)
- {
- packet_size = 0;
- mPacketsToDrop--;
- }
- }
- }
-
- return packet_size;
-}
-
-bool LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
-{
- bool status = true;
- if (!mUseOutThrottle)
- {
- return sendPacketImpl(h_socket, send_buffer, buf_size, host );
- }
- else
- {
- mActualBitsOut += buf_size * 8;
- LLPacketBuffer *packetp = NULL;
- // See if we've got enough throttle to send a packet.
- while (!mOutThrottle.checkOverflow(0.f))
- {
- // While we have enough bandwidth, send a packet from the queue or the current packet
-
- S32 packet_size = 0;
- if (!mSendQueue.empty())
- {
- // Send a packet off of the queue
- LLPacketBuffer *packetp = mSendQueue.front();
- mSendQueue.pop();
-
- mOutBufferLength -= packetp->getSize();
- packet_size = packetp->getSize();
-
- status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());
-
- delete packetp;
- // Update the throttle
- mOutThrottle.throttleOverflow(packet_size * 8.f);
- }
- else
- {
- // If the queue's empty, we can just send this packet right away.
- status = sendPacketImpl(h_socket, send_buffer, buf_size, host );
- packet_size = buf_size;
-
- // Update the throttle
- mOutThrottle.throttleOverflow(packet_size * 8.f);
-
- // This was the packet we're sending now, there are no other packets
- // that we need to send
- return status;
- }
-
- }
-
- // We haven't sent the incoming packet, add it to the queue
- if (mOutBufferLength + buf_size > mMaxBufferLength)
- {
- // Nuke this packet, we overflowed the buffer.
- // Toss it.
- LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL;
- }
- else
- {
- static LLTimer queue_timer;
- if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
- {
- // Add it to the queue
- LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL;
- queue_timer.reset();
- }
- packetp = new LLPacketBuffer(host, send_buffer, buf_size);
-
- mOutBufferLength += packetp->getSize();
- mSendQueue.push(packetp);
- }
- }
-
- return status;
-}
-
-bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
-{
-
- if (!LLProxy::isSOCKSProxyEnabled())
- {
- return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
- }
-
- char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
-
- proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
- socks_header->rsv = 0;
- socks_header->addr = host.getAddress();
- socks_header->port = htons(host.getPort());
- socks_header->atype = ADDRESS_IPV4;
- socks_header->frag = 0;
-
- memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
-
- return send_packet( h_socket,
- headered_send_buffer,
- buf_size + SOCKS_HEADER_SIZE,
- LLProxy::getInstance()->getUDPProxy().getAddress(),
- LLProxy::getInstance()->getUDPProxy().getPort());
-}
+/**
+ * @file llpacketring.cpp
+ * @brief implementation of LLPacketRing class for a packet.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llpacketring.h"
+
+#if LL_WINDOWS
+ #include <winsock2.h>
+#else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+#endif
+
+// linden library includes
+#include "llerror.h"
+#include "lltimer.h"
+#include "llproxy.h"
+#include "llrand.h"
+#include "message.h"
+#include "u64.h"
+
+///////////////////////////////////////////////////////////
+LLPacketRing::LLPacketRing () :
+ mUseInThrottle(false),
+ mUseOutThrottle(false),
+ mInThrottle(256000.f),
+ mOutThrottle(64000.f),
+ mActualBitsIn(0),
+ mActualBitsOut(0),
+ mMaxBufferLength(64000),
+ mInBufferLength(0),
+ mOutBufferLength(0),
+ mDropPercentage(0.0f),
+ mPacketsToDrop(0x0)
+{
+}
+
+///////////////////////////////////////////////////////////
+LLPacketRing::~LLPacketRing ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+void LLPacketRing::cleanup ()
+{
+ LLPacketBuffer *packetp;
+
+ while (!mReceiveQueue.empty())
+ {
+ packetp = mReceiveQueue.front();
+ delete packetp;
+ mReceiveQueue.pop();
+ }
+
+ while (!mSendQueue.empty())
+ {
+ packetp = mSendQueue.front();
+ delete packetp;
+ mSendQueue.pop();
+ }
+}
+
+///////////////////////////////////////////////////////////
+void LLPacketRing::dropPackets (U32 num_to_drop)
+{
+ mPacketsToDrop += num_to_drop;
+}
+
+///////////////////////////////////////////////////////////
+void LLPacketRing::setDropPercentage (F32 percent_to_drop)
+{
+ mDropPercentage = percent_to_drop;
+}
+
+void LLPacketRing::setUseInThrottle(const bool use_throttle)
+{
+ mUseInThrottle = use_throttle;
+}
+
+void LLPacketRing::setUseOutThrottle(const bool use_throttle)
+{
+ mUseOutThrottle = use_throttle;
+}
+
+void LLPacketRing::setInBandwidth(const F32 bps)
+{
+ mInThrottle.setRate(bps);
+}
+
+void LLPacketRing::setOutBandwidth(const F32 bps)
+{
+ mOutThrottle.setRate(bps);
+}
+///////////////////////////////////////////////////////////
+S32 LLPacketRing::receiveFromRing (S32 socket, char *datap)
+{
+
+ if (mInThrottle.checkOverflow(0))
+ {
+ // We don't have enough bandwidth, don't give them a packet.
+ return 0;
+ }
+
+ LLPacketBuffer *packetp = NULL;
+ if (mReceiveQueue.empty())
+ {
+ // No packets on the queue, don't give them any.
+ return 0;
+ }
+
+ S32 packet_size = 0;
+ packetp = mReceiveQueue.front();
+ mReceiveQueue.pop();
+ packet_size = packetp->getSize();
+ if (packetp->getData() != NULL)
+ {
+ memcpy(datap, packetp->getData(), packet_size); /*Flawfinder: ignore*/
+ }
+ // need to set sender IP/port!!
+ mLastSender = packetp->getHost();
+ mLastReceivingIF = packetp->getReceivingInterface();
+ delete packetp;
+
+ this->mInBufferLength -= packet_size;
+
+ // Adjust the throttle
+ mInThrottle.throttleOverflow(packet_size * 8.f);
+ return packet_size;
+}
+
+///////////////////////////////////////////////////////////
+S32 LLPacketRing::receivePacket (S32 socket, char *datap)
+{
+ S32 packet_size = 0;
+
+ // If using the throttle, simulate a limited size input buffer.
+ if (mUseInThrottle)
+ {
+ bool done = false;
+
+ // push any current net packet (if any) onto delay ring
+ while (!done)
+ {
+ LLPacketBuffer *packetp;
+ packetp = new LLPacketBuffer(socket);
+
+ if (packetp->getSize())
+ {
+ mActualBitsIn += packetp->getSize() * 8;
+
+ // Fake packet loss
+ if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
+ {
+ mPacketsToDrop++;
+ }
+
+ if (mPacketsToDrop)
+ {
+ delete packetp;
+ packetp = NULL;
+ packet_size = 0;
+ mPacketsToDrop--;
+ }
+ }
+
+ // If we faked packet loss, then we don't have a packet
+ // to use for buffer overflow testing
+ if (packetp)
+ {
+ if (mInBufferLength + packetp->getSize() > mMaxBufferLength)
+ {
+ // Toss it.
+ LL_WARNS() << "Throwing away packet, overflowing buffer" << LL_ENDL;
+ delete packetp;
+ packetp = NULL;
+ }
+ else if (packetp->getSize())
+ {
+ mReceiveQueue.push(packetp);
+ mInBufferLength += packetp->getSize();
+ }
+ else
+ {
+ delete packetp;
+ packetp = NULL;
+ done = true;
+ }
+ }
+ else
+ {
+ // No packetp, keep going? - no packetp == faked packet loss
+ }
+ }
+
+ // Now, grab data off of the receive queue according to our
+ // throttled bandwidth settings.
+ packet_size = receiveFromRing(socket, datap);
+ }
+ else
+ {
+ // no delay, pull straight from net
+ if (LLProxy::isSOCKSProxyEnabled())
+ {
+ U8 buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
+ packet_size = receive_packet(socket, static_cast<char*>(static_cast<void*>(buffer)));
+
+ if (packet_size > SOCKS_HEADER_SIZE)
+ {
+ // *FIX We are assuming ATYP is 0x01 (IPv4), not 0x03 (hostname) or 0x04 (IPv6)
+ memcpy(datap, buffer + SOCKS_HEADER_SIZE, packet_size - SOCKS_HEADER_SIZE);
+ proxywrap_t * header = static_cast<proxywrap_t*>(static_cast<void*>(buffer));
+ mLastSender.setAddress(header->addr);
+ mLastSender.setPort(ntohs(header->port));
+
+ packet_size -= SOCKS_HEADER_SIZE; // The unwrapped packet size
+ }
+ else
+ {
+ packet_size = 0;
+ }
+ }
+ else
+ {
+ packet_size = receive_packet(socket, datap);
+ mLastSender = ::get_sender();
+ }
+
+ mLastReceivingIF = ::get_receiving_interface();
+
+ if (packet_size) // did we actually get a packet?
+ {
+ if (mDropPercentage && (ll_frand(100.f) < mDropPercentage))
+ {
+ mPacketsToDrop++;
+ }
+
+ if (mPacketsToDrop)
+ {
+ packet_size = 0;
+ mPacketsToDrop--;
+ }
+ }
+ }
+
+ return packet_size;
+}
+
+bool LLPacketRing::sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host)
+{
+ bool status = true;
+ if (!mUseOutThrottle)
+ {
+ return sendPacketImpl(h_socket, send_buffer, buf_size, host );
+ }
+ else
+ {
+ mActualBitsOut += buf_size * 8;
+ LLPacketBuffer *packetp = NULL;
+ // See if we've got enough throttle to send a packet.
+ while (!mOutThrottle.checkOverflow(0.f))
+ {
+ // While we have enough bandwidth, send a packet from the queue or the current packet
+
+ S32 packet_size = 0;
+ if (!mSendQueue.empty())
+ {
+ // Send a packet off of the queue
+ LLPacketBuffer *packetp = mSendQueue.front();
+ mSendQueue.pop();
+
+ mOutBufferLength -= packetp->getSize();
+ packet_size = packetp->getSize();
+
+ status = sendPacketImpl(h_socket, packetp->getData(), packet_size, packetp->getHost());
+
+ delete packetp;
+ // Update the throttle
+ mOutThrottle.throttleOverflow(packet_size * 8.f);
+ }
+ else
+ {
+ // If the queue's empty, we can just send this packet right away.
+ status = sendPacketImpl(h_socket, send_buffer, buf_size, host );
+ packet_size = buf_size;
+
+ // Update the throttle
+ mOutThrottle.throttleOverflow(packet_size * 8.f);
+
+ // This was the packet we're sending now, there are no other packets
+ // that we need to send
+ return status;
+ }
+
+ }
+
+ // We haven't sent the incoming packet, add it to the queue
+ if (mOutBufferLength + buf_size > mMaxBufferLength)
+ {
+ // Nuke this packet, we overflowed the buffer.
+ // Toss it.
+ LL_WARNS() << "Throwing away outbound packet, overflowing buffer" << LL_ENDL;
+ }
+ else
+ {
+ static LLTimer queue_timer;
+ if ((mOutBufferLength > 4192) && queue_timer.getElapsedTimeF32() > 1.f)
+ {
+ // Add it to the queue
+ LL_INFOS() << "Outbound packet queue " << mOutBufferLength << " bytes" << LL_ENDL;
+ queue_timer.reset();
+ }
+ packetp = new LLPacketBuffer(host, send_buffer, buf_size);
+
+ mOutBufferLength += packetp->getSize();
+ mSendQueue.push(packetp);
+ }
+ }
+
+ return status;
+}
+
+bool LLPacketRing::sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host)
+{
+
+ if (!LLProxy::isSOCKSProxyEnabled())
+ {
+ return send_packet(h_socket, send_buffer, buf_size, host.getAddress(), host.getPort());
+ }
+
+ char headered_send_buffer[NET_BUFFER_SIZE + SOCKS_HEADER_SIZE];
+
+ proxywrap_t *socks_header = static_cast<proxywrap_t*>(static_cast<void*>(&headered_send_buffer));
+ socks_header->rsv = 0;
+ socks_header->addr = host.getAddress();
+ socks_header->port = htons(host.getPort());
+ socks_header->atype = ADDRESS_IPV4;
+ socks_header->frag = 0;
+
+ memcpy(headered_send_buffer + SOCKS_HEADER_SIZE, send_buffer, buf_size);
+
+ return send_packet( h_socket,
+ headered_send_buffer,
+ buf_size + SOCKS_HEADER_SIZE,
+ LLProxy::getInstance()->getUDPProxy().getAddress(),
+ LLProxy::getInstance()->getUDPProxy().getPort());
+}
diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h
index 888ee927b5..64f9f937af 100644
--- a/indra/llmessage/llpacketring.h
+++ b/indra/llmessage/llpacketring.h
@@ -1,101 +1,101 @@
-/**
- * @file llpacketring.h
- * @brief definition of LLPacketRing class for implementing a resend,
- * drop, or delay in packet transmissions
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPACKETRING_H
-#define LL_LLPACKETRING_H
-
-#include <queue>
-
-#include "llhost.h"
-#include "llpacketbuffer.h"
-#include "llproxy.h"
-#include "llthrottle.h"
-#include "net.h"
-
-class LLPacketRing
-{
-public:
- LLPacketRing();
- ~LLPacketRing();
-
- void cleanup();
-
- void dropPackets(U32);
- void setDropPercentage (F32 percent_to_drop);
- void setUseInThrottle(const bool use_throttle);
- void setUseOutThrottle(const bool use_throttle);
- void setInBandwidth(const F32 bps);
- void setOutBandwidth(const F32 bps);
- S32 receivePacket (S32 socket, char *datap);
- S32 receiveFromRing (S32 socket, char *datap);
-
- bool sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host);
-
- inline LLHost getLastSender();
- inline LLHost getLastReceivingInterface();
-
- S32 getAndResetActualInBits() { S32 bits = mActualBitsIn; mActualBitsIn = 0; return bits;}
- S32 getAndResetActualOutBits() { S32 bits = mActualBitsOut; mActualBitsOut = 0; return bits;}
-protected:
- bool mUseInThrottle;
- bool mUseOutThrottle;
-
- // For simulating a lower-bandwidth connection - BPS
- LLThrottle mInThrottle;
- LLThrottle mOutThrottle;
-
- S32 mActualBitsIn;
- S32 mActualBitsOut;
- S32 mMaxBufferLength; // How much data can we queue up before dropping data.
- S32 mInBufferLength; // Current incoming buffer length
- S32 mOutBufferLength; // Current outgoing buffer length
-
- F32 mDropPercentage; // % of packets to drop
- U32 mPacketsToDrop; // drop next n packets
-
- std::queue<LLPacketBuffer *> mReceiveQueue;
- std::queue<LLPacketBuffer *> mSendQueue;
-
- LLHost mLastSender;
- LLHost mLastReceivingIF;
-
-private:
- bool sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
-};
-
-
-inline LLHost LLPacketRing::getLastSender()
-{
- return mLastSender;
-}
-
-inline LLHost LLPacketRing::getLastReceivingInterface()
-{
- return mLastReceivingIF;
-}
-
-#endif
+/**
+ * @file llpacketring.h
+ * @brief definition of LLPacketRing class for implementing a resend,
+ * drop, or delay in packet transmissions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPACKETRING_H
+#define LL_LLPACKETRING_H
+
+#include <queue>
+
+#include "llhost.h"
+#include "llpacketbuffer.h"
+#include "llproxy.h"
+#include "llthrottle.h"
+#include "net.h"
+
+class LLPacketRing
+{
+public:
+ LLPacketRing();
+ ~LLPacketRing();
+
+ void cleanup();
+
+ void dropPackets(U32);
+ void setDropPercentage (F32 percent_to_drop);
+ void setUseInThrottle(const bool use_throttle);
+ void setUseOutThrottle(const bool use_throttle);
+ void setInBandwidth(const F32 bps);
+ void setOutBandwidth(const F32 bps);
+ S32 receivePacket (S32 socket, char *datap);
+ S32 receiveFromRing (S32 socket, char *datap);
+
+ bool sendPacket(int h_socket, char * send_buffer, S32 buf_size, LLHost host);
+
+ inline LLHost getLastSender();
+ inline LLHost getLastReceivingInterface();
+
+ S32 getAndResetActualInBits() { S32 bits = mActualBitsIn; mActualBitsIn = 0; return bits;}
+ S32 getAndResetActualOutBits() { S32 bits = mActualBitsOut; mActualBitsOut = 0; return bits;}
+protected:
+ bool mUseInThrottle;
+ bool mUseOutThrottle;
+
+ // For simulating a lower-bandwidth connection - BPS
+ LLThrottle mInThrottle;
+ LLThrottle mOutThrottle;
+
+ S32 mActualBitsIn;
+ S32 mActualBitsOut;
+ S32 mMaxBufferLength; // How much data can we queue up before dropping data.
+ S32 mInBufferLength; // Current incoming buffer length
+ S32 mOutBufferLength; // Current outgoing buffer length
+
+ F32 mDropPercentage; // % of packets to drop
+ U32 mPacketsToDrop; // drop next n packets
+
+ std::queue<LLPacketBuffer *> mReceiveQueue;
+ std::queue<LLPacketBuffer *> mSendQueue;
+
+ LLHost mLastSender;
+ LLHost mLastReceivingIF;
+
+private:
+ bool sendPacketImpl(int h_socket, const char * send_buffer, S32 buf_size, LLHost host);
+};
+
+
+inline LLHost LLPacketRing::getLastSender()
+{
+ return mLastSender;
+}
+
+inline LLHost LLPacketRing::getLastReceivingInterface()
+{
+ return mLastReceivingIF;
+}
+
+#endif
diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp
index a4852cefba..afbc74b847 100644
--- a/indra/llmessage/llpartdata.cpp
+++ b/indra/llmessage/llpartdata.cpp
@@ -1,419 +1,419 @@
-/**
- * @file llpartdata.cpp
- * @brief Particle system data packing
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llpartdata.h"
-#include "message.h"
-
-#include "lldatapacker.h"
-#include "v4coloru.h"
-
-#include "llsdutil.h"
-#include "llsdutil_math.h"
-
-
-
-const S32 PS_PART_DATA_GLOW_SIZE = 2;
-const S32 PS_PART_DATA_BLEND_SIZE = 2;
-const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
-const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
-const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
- PS_LEGACY_PART_DATA_BLOCK_SIZE +
- PS_PART_DATA_BLEND_SIZE +
- PS_PART_DATA_GLOW_SIZE+
- 8; //two S32 size fields
-
-const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
-
-const F32 MAX_PART_SCALE = 4.f;
-
-bool LLPartData::hasGlow() const
-{
- return mStartGlow > 0.f || mEndGlow > 0.f;
-}
-
-bool LLPartData::hasBlendFunc() const
-{
- return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
-}
-
-S32 LLPartData::getSize() const
-{
- S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
- if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
- if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
-
- return size;
-}
-
-
-bool LLPartData::unpackLegacy(LLDataPacker &dp)
-{
- LLColor4U coloru;
-
- dp.unpackU32(mFlags, "pdflags");
- dp.unpackFixed(mMaxAge, "pdmaxage", false, 8, 8);
-
- dp.unpackColor4U(coloru, "pdstartcolor");
- mStartColor.setVec(coloru);
- dp.unpackColor4U(coloru, "pdendcolor");
- mEndColor.setVec(coloru);
- dp.unpackFixed(mStartScale.mV[0], "pdstartscalex", false, 3, 5);
- dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", false, 3, 5);
- dp.unpackFixed(mEndScale.mV[0], "pdendscalex", false, 3, 5);
- dp.unpackFixed(mEndScale.mV[1], "pdendscaley", false, 3, 5);
-
- mStartGlow = 0.f;
- mEndGlow = 0.f;
- mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
-
- return true;
-}
-
-bool LLPartData::unpack(LLDataPacker &dp)
-{
- S32 size = 0;
- dp.unpackS32(size, "partsize");
-
- unpackLegacy(dp);
- size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
-
- if (mFlags & LL_PART_DATA_GLOW)
- {
- if (size < PS_PART_DATA_GLOW_SIZE) return false;
-
- U8 tmp_glow = 0;
- dp.unpackU8(tmp_glow,"pdstartglow");
- mStartGlow = tmp_glow / 255.f;
- dp.unpackU8(tmp_glow,"pdendglow");
- mEndGlow = tmp_glow / 255.f;
-
- size -= PS_PART_DATA_GLOW_SIZE;
- }
- else
- {
- mStartGlow = 0.f;
- mEndGlow = 0.f;
- }
-
- if (mFlags & LL_PART_DATA_BLEND)
- {
- if (size < PS_PART_DATA_BLEND_SIZE) return false;
- dp.unpackU8(mBlendFuncSource,"pdblendsource");
- dp.unpackU8(mBlendFuncDest,"pdblenddest");
- size -= PS_PART_DATA_BLEND_SIZE;
- }
- else
- {
- mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
- }
-
- if (size > 0)
- { //leftover bytes, unrecognized parameters
- U8 feh = 0;
- while (size > 0)
- { //read remaining bytes in block
- dp.unpackU8(feh, "whippang");
- size--;
- }
-
- //this particle system won't display properly, better to not show anything
- return false;
- }
-
-
- return true;
-}
-
-void LLPartData::setFlags(const U32 flags)
-{
- mFlags = flags;
-}
-
-
-void LLPartData::setMaxAge(const F32 max_age)
-{
- mMaxAge = llclamp(max_age, 0.f, 30.f);
-}
-
-
-void LLPartData::setStartScale(const F32 xs, const F32 ys)
-{
- mStartScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
- mStartScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
-}
-
-
-void LLPartData::setEndScale(const F32 xs, const F32 ys)
-{
- mEndScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
- mEndScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
-}
-
-
-void LLPartData::setStartColor(const LLVector3 &rgb)
-{
- mStartColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
-}
-
-
-void LLPartData::setEndColor(const LLVector3 &rgb)
-{
- mEndColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
-}
-
-void LLPartData::setStartAlpha(const F32 alpha)
-{
- mStartColor.mV[3] = alpha;
-}
-void LLPartData::setEndAlpha(const F32 alpha)
-{
- mEndColor.mV[3] = alpha;
-}
-
-// static
-bool LLPartData::validBlendFunc(S32 func)
-{
- if (func >= 0
- && func < LL_PART_BF_COUNT
- && func != UNSUPPORTED_DEST_ALPHA
- && func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
- {
- return true;
- }
- return false;
-}
-
-LLPartSysData::LLPartSysData()
-{
- mCRC = 0;
- mFlags = 0;
-
- mPartData.mFlags = 0;
- mPartData.mStartColor = LLColor4(1.f, 1.f, 1.f, 1.f);
- mPartData.mEndColor = LLColor4(1.f, 1.f, 1.f, 1.f);
- mPartData.mStartScale = LLVector2(1.f, 1.f);
- mPartData.mEndScale = LLVector2(1.f, 1.f);
- mPartData.mMaxAge = 10.0;
- mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
- mPartData.mStartGlow = 0.f;
- mPartData.mEndGlow = 0.f;
-
- mMaxAge = 0.0;
- mStartAge = 0.0;
- mPattern = LL_PART_SRC_PATTERN_DROP; // Pattern for particle velocity
- mInnerAngle = 0.0; // Inner angle of PATTERN_ANGLE_*
- mOuterAngle = 0.0; // Outer angle of PATTERN_ANGLE_*
- mBurstRate = 0.1f; // How often to do a burst of particles
- mBurstPartCount = 1; // How many particles in a burst
- mBurstSpeedMin = 1.f; // Minimum particle velocity
- mBurstSpeedMax = 1.f; // Maximum particle velocity
- mBurstRadius = 0.f;
-
- mNumParticles = 0;
-}
-
-bool LLPartSysData::unpackSystem(LLDataPacker &dp)
-{
- dp.unpackU32(mCRC, "pscrc");
- dp.unpackU32(mFlags, "psflags");
- dp.unpackU8(mPattern, "pspattern");
- dp.unpackFixed(mMaxAge, "psmaxage", false, 8, 8);
- dp.unpackFixed(mStartAge, "psstartage", false, 8, 8);
- dp.unpackFixed(mInnerAngle, "psinnerangle", false, 3, 5);
- dp.unpackFixed(mOuterAngle, "psouterangle", false, 3, 5);
- dp.unpackFixed(mBurstRate, "psburstrate", false, 8, 8);
- mBurstRate = llmax(0.01f, mBurstRate);
- dp.unpackFixed(mBurstRadius, "psburstradius", false, 8, 8);
- dp.unpackFixed(mBurstSpeedMin, "psburstspeedmin", false, 8, 8);
- dp.unpackFixed(mBurstSpeedMax, "psburstspeedmax", false, 8, 8);
- dp.unpackU8(mBurstPartCount, "psburstpartcount");
-
- dp.unpackFixed(mAngularVelocity.mV[0], "psangvelx", true, 8, 7);
- dp.unpackFixed(mAngularVelocity.mV[1], "psangvely", true, 8, 7);
- dp.unpackFixed(mAngularVelocity.mV[2], "psangvelz", true, 8, 7);
-
- dp.unpackFixed(mPartAccel.mV[0], "psaccelx", true, 8, 7);
- dp.unpackFixed(mPartAccel.mV[1], "psaccely", true, 8, 7);
- dp.unpackFixed(mPartAccel.mV[2], "psaccelz", true, 8, 7);
-
- dp.unpackUUID(mPartImageID, "psuuid");
- dp.unpackUUID(mTargetUUID, "pstargetuuid");
- return true;
-}
-
-bool LLPartSysData::unpackLegacy(LLDataPacker &dp)
-{
- unpackSystem(dp);
- mPartData.unpackLegacy(dp);
-
- return true;
-}
-
-bool LLPartSysData::unpack(LLDataPacker &dp)
-{
- // syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
- S32 size = 0;
- dp.unpackS32(size, "syssize");
-
- if (size != PS_SYS_DATA_BLOCK_SIZE)
- { //unexpected size, this viewer doesn't know how to parse this particle system
-
- //skip to LLPartData block
- U8 feh = 0;
-
- for (U32 i = 0; i < size; ++i)
- {
- dp.unpackU8(feh, "whippang");
- }
-
- dp.unpackS32(size, "partsize");
- //skip LLPartData block
- for (U32 i = 0; i < size; ++i)
- {
- dp.unpackU8(feh, "whippang");
- }
- return false;
- }
-
- unpackSystem(dp);
-
- return mPartData.unpack(dp);
-}
-
-std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
-{
- s << "Flags: " << std::hex << data.mFlags;
- s << "Pattern: " << std::hex << (U32) data.mPattern << "\n";
- s << "Source Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
- s << "Particle Age: " << data.mPartData.mMaxAge << "\n";
- s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
- s << "Burst Rate: " << data.mBurstRate << "\n";
- s << "Burst Radius: " << data.mBurstRadius << "\n";
- s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
- s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
- s << "Angular Velocity: " << data.mAngularVelocity << "\n";
- s << "Accel: " << data.mPartAccel;
- return s;
-}
-
-bool LLPartSysData::isNullPS(const S32 block_num)
-{
- U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
- U32 crc;
-
- S32 size;
- // Check size of block
- size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
-
- if (!size)
- {
- return true;
- }
-
- if (size > PS_MAX_DATA_BLOCK_SIZE)
- {
- //size is too big, newer particle version unsupported
- return true;
- }
-
- gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
-
- LLDataPackerBinaryBuffer dp(ps_data_block, size);
- if (size > PS_LEGACY_DATA_BLOCK_SIZE)
- {
- // non legacy systems pack a size before the CRC
- S32 tmp = 0;
- dp.unpackS32(tmp, "syssize");
-
- if (tmp > PS_SYS_DATA_BLOCK_SIZE)
- { //unknown system data block size, don't know how to parse it, treat as NULL
- return true;
- }
- }
-
- dp.unpackU32(crc, "crc");
-
- if (crc == 0)
- {
- return true;
- }
- return false;
-}
-
-bool LLPartSysData::unpackBlock(const S32 block_num)
-{
- U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
-
- // Check size of block
- S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
-
- if (size > PS_MAX_DATA_BLOCK_SIZE)
- {
- // Larger packets are newer and unsupported
- return false;
- }
-
- // Get from message
- gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
-
- LLDataPackerBinaryBuffer dp(ps_data_block, size);
-
- if (size == PS_LEGACY_DATA_BLOCK_SIZE)
- {
- return unpackLegacy(dp);
- }
- else
- {
- return unpack(dp);
- }
-}
-
-bool LLPartSysData::isLegacyCompatible() const
-{
- return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
-}
-
-void LLPartSysData::clampSourceParticleRate()
-{
- F32 particle_rate = 0;
- particle_rate = mBurstPartCount/mBurstRate;
- if (particle_rate > 256.f)
- {
- mBurstPartCount = llfloor(((F32)mBurstPartCount)*(256.f/particle_rate));
- }
-}
-
-void LLPartSysData::setPartAccel(const LLVector3 &accel)
-{
- mPartAccel.mV[VX] = llclamp(accel.mV[VX], -100.f, 100.f);
- mPartAccel.mV[VY] = llclamp(accel.mV[VY], -100.f, 100.f);
- mPartAccel.mV[VZ] = llclamp(accel.mV[VZ], -100.f, 100.f);
-}
+/**
+ * @file llpartdata.cpp
+ * @brief Particle system data packing
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llpartdata.h"
+#include "message.h"
+
+#include "lldatapacker.h"
+#include "v4coloru.h"
+
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+
+
+
+const S32 PS_PART_DATA_GLOW_SIZE = 2;
+const S32 PS_PART_DATA_BLEND_SIZE = 2;
+const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
+const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
+const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
+ PS_LEGACY_PART_DATA_BLOCK_SIZE +
+ PS_PART_DATA_BLEND_SIZE +
+ PS_PART_DATA_GLOW_SIZE+
+ 8; //two S32 size fields
+
+const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
+
+const F32 MAX_PART_SCALE = 4.f;
+
+bool LLPartData::hasGlow() const
+{
+ return mStartGlow > 0.f || mEndGlow > 0.f;
+}
+
+bool LLPartData::hasBlendFunc() const
+{
+ return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+}
+
+S32 LLPartData::getSize() const
+{
+ S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
+ if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
+ if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
+
+ return size;
+}
+
+
+bool LLPartData::unpackLegacy(LLDataPacker &dp)
+{
+ LLColor4U coloru;
+
+ dp.unpackU32(mFlags, "pdflags");
+ dp.unpackFixed(mMaxAge, "pdmaxage", false, 8, 8);
+
+ dp.unpackColor4U(coloru, "pdstartcolor");
+ mStartColor.setVec(coloru);
+ dp.unpackColor4U(coloru, "pdendcolor");
+ mEndColor.setVec(coloru);
+ dp.unpackFixed(mStartScale.mV[0], "pdstartscalex", false, 3, 5);
+ dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", false, 3, 5);
+ dp.unpackFixed(mEndScale.mV[0], "pdendscalex", false, 3, 5);
+ dp.unpackFixed(mEndScale.mV[1], "pdendscaley", false, 3, 5);
+
+ mStartGlow = 0.f;
+ mEndGlow = 0.f;
+ mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+
+ return true;
+}
+
+bool LLPartData::unpack(LLDataPacker &dp)
+{
+ S32 size = 0;
+ dp.unpackS32(size, "partsize");
+
+ unpackLegacy(dp);
+ size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
+
+ if (mFlags & LL_PART_DATA_GLOW)
+ {
+ if (size < PS_PART_DATA_GLOW_SIZE) return false;
+
+ U8 tmp_glow = 0;
+ dp.unpackU8(tmp_glow,"pdstartglow");
+ mStartGlow = tmp_glow / 255.f;
+ dp.unpackU8(tmp_glow,"pdendglow");
+ mEndGlow = tmp_glow / 255.f;
+
+ size -= PS_PART_DATA_GLOW_SIZE;
+ }
+ else
+ {
+ mStartGlow = 0.f;
+ mEndGlow = 0.f;
+ }
+
+ if (mFlags & LL_PART_DATA_BLEND)
+ {
+ if (size < PS_PART_DATA_BLEND_SIZE) return false;
+ dp.unpackU8(mBlendFuncSource,"pdblendsource");
+ dp.unpackU8(mBlendFuncDest,"pdblenddest");
+ size -= PS_PART_DATA_BLEND_SIZE;
+ }
+ else
+ {
+ mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+ }
+
+ if (size > 0)
+ { //leftover bytes, unrecognized parameters
+ U8 feh = 0;
+ while (size > 0)
+ { //read remaining bytes in block
+ dp.unpackU8(feh, "whippang");
+ size--;
+ }
+
+ //this particle system won't display properly, better to not show anything
+ return false;
+ }
+
+
+ return true;
+}
+
+void LLPartData::setFlags(const U32 flags)
+{
+ mFlags = flags;
+}
+
+
+void LLPartData::setMaxAge(const F32 max_age)
+{
+ mMaxAge = llclamp(max_age, 0.f, 30.f);
+}
+
+
+void LLPartData::setStartScale(const F32 xs, const F32 ys)
+{
+ mStartScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
+ mStartScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
+}
+
+
+void LLPartData::setEndScale(const F32 xs, const F32 ys)
+{
+ mEndScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
+ mEndScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
+}
+
+
+void LLPartData::setStartColor(const LLVector3 &rgb)
+{
+ mStartColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
+}
+
+
+void LLPartData::setEndColor(const LLVector3 &rgb)
+{
+ mEndColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
+}
+
+void LLPartData::setStartAlpha(const F32 alpha)
+{
+ mStartColor.mV[3] = alpha;
+}
+void LLPartData::setEndAlpha(const F32 alpha)
+{
+ mEndColor.mV[3] = alpha;
+}
+
+// static
+bool LLPartData::validBlendFunc(S32 func)
+{
+ if (func >= 0
+ && func < LL_PART_BF_COUNT
+ && func != UNSUPPORTED_DEST_ALPHA
+ && func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
+ {
+ return true;
+ }
+ return false;
+}
+
+LLPartSysData::LLPartSysData()
+{
+ mCRC = 0;
+ mFlags = 0;
+
+ mPartData.mFlags = 0;
+ mPartData.mStartColor = LLColor4(1.f, 1.f, 1.f, 1.f);
+ mPartData.mEndColor = LLColor4(1.f, 1.f, 1.f, 1.f);
+ mPartData.mStartScale = LLVector2(1.f, 1.f);
+ mPartData.mEndScale = LLVector2(1.f, 1.f);
+ mPartData.mMaxAge = 10.0;
+ mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+ mPartData.mStartGlow = 0.f;
+ mPartData.mEndGlow = 0.f;
+
+ mMaxAge = 0.0;
+ mStartAge = 0.0;
+ mPattern = LL_PART_SRC_PATTERN_DROP; // Pattern for particle velocity
+ mInnerAngle = 0.0; // Inner angle of PATTERN_ANGLE_*
+ mOuterAngle = 0.0; // Outer angle of PATTERN_ANGLE_*
+ mBurstRate = 0.1f; // How often to do a burst of particles
+ mBurstPartCount = 1; // How many particles in a burst
+ mBurstSpeedMin = 1.f; // Minimum particle velocity
+ mBurstSpeedMax = 1.f; // Maximum particle velocity
+ mBurstRadius = 0.f;
+
+ mNumParticles = 0;
+}
+
+bool LLPartSysData::unpackSystem(LLDataPacker &dp)
+{
+ dp.unpackU32(mCRC, "pscrc");
+ dp.unpackU32(mFlags, "psflags");
+ dp.unpackU8(mPattern, "pspattern");
+ dp.unpackFixed(mMaxAge, "psmaxage", false, 8, 8);
+ dp.unpackFixed(mStartAge, "psstartage", false, 8, 8);
+ dp.unpackFixed(mInnerAngle, "psinnerangle", false, 3, 5);
+ dp.unpackFixed(mOuterAngle, "psouterangle", false, 3, 5);
+ dp.unpackFixed(mBurstRate, "psburstrate", false, 8, 8);
+ mBurstRate = llmax(0.01f, mBurstRate);
+ dp.unpackFixed(mBurstRadius, "psburstradius", false, 8, 8);
+ dp.unpackFixed(mBurstSpeedMin, "psburstspeedmin", false, 8, 8);
+ dp.unpackFixed(mBurstSpeedMax, "psburstspeedmax", false, 8, 8);
+ dp.unpackU8(mBurstPartCount, "psburstpartcount");
+
+ dp.unpackFixed(mAngularVelocity.mV[0], "psangvelx", true, 8, 7);
+ dp.unpackFixed(mAngularVelocity.mV[1], "psangvely", true, 8, 7);
+ dp.unpackFixed(mAngularVelocity.mV[2], "psangvelz", true, 8, 7);
+
+ dp.unpackFixed(mPartAccel.mV[0], "psaccelx", true, 8, 7);
+ dp.unpackFixed(mPartAccel.mV[1], "psaccely", true, 8, 7);
+ dp.unpackFixed(mPartAccel.mV[2], "psaccelz", true, 8, 7);
+
+ dp.unpackUUID(mPartImageID, "psuuid");
+ dp.unpackUUID(mTargetUUID, "pstargetuuid");
+ return true;
+}
+
+bool LLPartSysData::unpackLegacy(LLDataPacker &dp)
+{
+ unpackSystem(dp);
+ mPartData.unpackLegacy(dp);
+
+ return true;
+}
+
+bool LLPartSysData::unpack(LLDataPacker &dp)
+{
+ // syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
+ S32 size = 0;
+ dp.unpackS32(size, "syssize");
+
+ if (size != PS_SYS_DATA_BLOCK_SIZE)
+ { //unexpected size, this viewer doesn't know how to parse this particle system
+
+ //skip to LLPartData block
+ U8 feh = 0;
+
+ for (U32 i = 0; i < size; ++i)
+ {
+ dp.unpackU8(feh, "whippang");
+ }
+
+ dp.unpackS32(size, "partsize");
+ //skip LLPartData block
+ for (U32 i = 0; i < size; ++i)
+ {
+ dp.unpackU8(feh, "whippang");
+ }
+ return false;
+ }
+
+ unpackSystem(dp);
+
+ return mPartData.unpack(dp);
+}
+
+std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
+{
+ s << "Flags: " << std::hex << data.mFlags;
+ s << "Pattern: " << std::hex << (U32) data.mPattern << "\n";
+ s << "Source Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
+ s << "Particle Age: " << data.mPartData.mMaxAge << "\n";
+ s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
+ s << "Burst Rate: " << data.mBurstRate << "\n";
+ s << "Burst Radius: " << data.mBurstRadius << "\n";
+ s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
+ s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
+ s << "Angular Velocity: " << data.mAngularVelocity << "\n";
+ s << "Accel: " << data.mPartAccel;
+ return s;
+}
+
+bool LLPartSysData::isNullPS(const S32 block_num)
+{
+ U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
+ U32 crc;
+
+ S32 size;
+ // Check size of block
+ size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
+
+ if (!size)
+ {
+ return true;
+ }
+
+ if (size > PS_MAX_DATA_BLOCK_SIZE)
+ {
+ //size is too big, newer particle version unsupported
+ return true;
+ }
+
+ gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
+
+ LLDataPackerBinaryBuffer dp(ps_data_block, size);
+ if (size > PS_LEGACY_DATA_BLOCK_SIZE)
+ {
+ // non legacy systems pack a size before the CRC
+ S32 tmp = 0;
+ dp.unpackS32(tmp, "syssize");
+
+ if (tmp > PS_SYS_DATA_BLOCK_SIZE)
+ { //unknown system data block size, don't know how to parse it, treat as NULL
+ return true;
+ }
+ }
+
+ dp.unpackU32(crc, "crc");
+
+ if (crc == 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool LLPartSysData::unpackBlock(const S32 block_num)
+{
+ U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
+
+ // Check size of block
+ S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
+
+ if (size > PS_MAX_DATA_BLOCK_SIZE)
+ {
+ // Larger packets are newer and unsupported
+ return false;
+ }
+
+ // Get from message
+ gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
+
+ LLDataPackerBinaryBuffer dp(ps_data_block, size);
+
+ if (size == PS_LEGACY_DATA_BLOCK_SIZE)
+ {
+ return unpackLegacy(dp);
+ }
+ else
+ {
+ return unpack(dp);
+ }
+}
+
+bool LLPartSysData::isLegacyCompatible() const
+{
+ return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
+}
+
+void LLPartSysData::clampSourceParticleRate()
+{
+ F32 particle_rate = 0;
+ particle_rate = mBurstPartCount/mBurstRate;
+ if (particle_rate > 256.f)
+ {
+ mBurstPartCount = llfloor(((F32)mBurstPartCount)*(256.f/particle_rate));
+ }
+}
+
+void LLPartSysData::setPartAccel(const LLVector3 &accel)
+{
+ mPartAccel.mV[VX] = llclamp(accel.mV[VX], -100.f, 100.f);
+ mPartAccel.mV[VY] = llclamp(accel.mV[VY], -100.f, 100.f);
+ mPartAccel.mV[VZ] = llclamp(accel.mV[VZ], -100.f, 100.f);
+}
diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h
index c61e411a23..70c425b0a5 100644
--- a/indra/llmessage/llpartdata.h
+++ b/indra/llmessage/llpartdata.h
@@ -1,279 +1,279 @@
-/**
- * @file llpartdata.h
- * @brief Particle system data packing
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPARTDATA_H
-#define LL_LLPARTDATA_H
-
-#include "lluuid.h"
-#include "v3math.h"
-#include "v3dmath.h"
-#include "v2math.h"
-#include "v4color.h"
-
-class LLMessageSystem;
-class LLDataPacker;
-
-const S32 PS_CUR_VERSION = 18;
-
-//
-// These constants are used by the script code, not by the particle system itself
-//
-
-enum LLPSScriptFlags
-{
- // Flags for the different parameters of individual particles
- LLPS_PART_FLAGS,
- LLPS_PART_START_COLOR,
- LLPS_PART_START_ALPHA,
- LLPS_PART_END_COLOR,
- LLPS_PART_END_ALPHA,
- LLPS_PART_START_SCALE,
- LLPS_PART_END_SCALE,
- LLPS_PART_MAX_AGE,
-
- // Flags for the different parameters of the particle source
- LLPS_SRC_ACCEL,
- LLPS_SRC_PATTERN,
- LLPS_SRC_INNERANGLE,
- LLPS_SRC_OUTERANGLE,
- LLPS_SRC_TEXTURE,
- LLPS_SRC_BURST_RATE,
- LLPS_SRC_BURST_DURATION,
- LLPS_SRC_BURST_PART_COUNT,
- LLPS_SRC_BURST_RADIUS,
- LLPS_SRC_BURST_SPEED_MIN,
- LLPS_SRC_BURST_SPEED_MAX,
- LLPS_SRC_MAX_AGE,
- LLPS_SRC_TARGET_UUID,
- LLPS_SRC_OMEGA,
- LLPS_SRC_ANGLE_BEGIN,
- LLPS_SRC_ANGLE_END,
-
- LLPS_PART_BLEND_FUNC_SOURCE,
- LLPS_PART_BLEND_FUNC_DEST,
- LLPS_PART_START_GLOW,
- LLPS_PART_END_GLOW
-};
-
-
-class LLPartData
-{
-public:
- LLPartData() :
- mFlags(0),
- mMaxAge(0.f),
- mParameter(0.f)
- {
- }
- bool unpackLegacy(LLDataPacker &dp);
- bool unpack(LLDataPacker &dp);
-
- bool pack(LLDataPacker &dp);
-
- bool hasGlow() const;
- bool hasBlendFunc() const;
-
- // Masks for the different particle flags
- enum
- {
- LL_PART_INTERP_COLOR_MASK = 0x01,
- LL_PART_INTERP_SCALE_MASK = 0x02,
- LL_PART_BOUNCE_MASK = 0x04,
- LL_PART_WIND_MASK = 0x08,
- LL_PART_FOLLOW_SRC_MASK = 0x10, // Follows source, no rotation following (expensive!)
- LL_PART_FOLLOW_VELOCITY_MASK = 0x20, // Particles orient themselves with velocity
- LL_PART_TARGET_POS_MASK = 0x40,
- LL_PART_TARGET_LINEAR_MASK = 0x80, // Particle uses a direct linear interpolation
- LL_PART_EMISSIVE_MASK = 0x100, // Particle is "emissive", instead of being lit
- LL_PART_BEAM_MASK = 0x200, // Particle is a "beam" connecting source and target
- LL_PART_RIBBON_MASK = 0x400, // Particles are joined together into one continuous triangle strip
-
- // Not implemented yet!
- //LL_PART_RANDOM_ACCEL_MASK = 0x100, // Particles have random acceleration
- //LL_PART_RANDOM_VEL_MASK = 0x200, // Particles have random velocity shifts"
- //LL_PART_TRAIL_MASK = 0x400, // Particles have historical "trails"
-
- //sYSTEM SET FLAGS
- LL_PART_DATA_GLOW = 0x10000,
- LL_PART_DATA_BLEND = 0x20000,
-
- // Viewer side use only!
- LL_PART_HUD = 0x40000000,
- LL_PART_DEAD_MASK = 0x80000000,
- };
-
- enum
- {
- LL_PART_BF_ONE = 0,
- LL_PART_BF_ZERO = 1,
- LL_PART_BF_DEST_COLOR = 2,
- LL_PART_BF_SOURCE_COLOR = 3,
- LL_PART_BF_ONE_MINUS_DEST_COLOR = 4,
- LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5,
- UNSUPPORTED_DEST_ALPHA = 6,
- LL_PART_BF_SOURCE_ALPHA = 7,
- UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8,
- LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9,
- LL_PART_BF_COUNT = 10
- };
-
- static bool validBlendFunc(S32 func);
-
- void setFlags(const U32 flags);
- void setMaxAge(const F32 max_age);
- void setStartScale(const F32 xs, F32 ys);
- void setEndScale(const F32 xs, F32 ys);
- void setStartColor(const LLVector3 &rgb);
- void setEndColor(const LLVector3 &rgb);
- void setStartAlpha(const F32 alpha);
- void setEndAlpha(const F32 alpha);
-
-
- friend class LLPartSysData;
- friend class LLViewerPartSourceScript;
-
-private:
- S32 getSize() const;
-
- // These are public because I'm really lazy...
-public:
- U32 mFlags; // Particle state/interpolators in effect
- F32 mMaxAge; // Maximum age of the particle
- LLColor4 mStartColor; // Start color
- LLColor4 mEndColor; // End color
- LLVector2 mStartScale; // Start scale
- LLVector2 mEndScale; // End scale
-
- LLVector3 mPosOffset; // Offset from source if using FOLLOW_SOURCE
- F32 mParameter; // A single floating point parameter
-
- F32 mStartGlow;
- F32 mEndGlow;
-
- U8 mBlendFuncSource;
- U8 mBlendFuncDest;
-};
-
-
-class LLPartSysData
-{
-public:
- LLPartSysData();
-
- bool unpack(LLDataPacker &dp);
- bool unpackLegacy(LLDataPacker &dp);
- bool unpackBlock(const S32 block_num);
-
- static bool isNullPS(const S32 block_num); // Returns false if this is a "NULL" particle system (i.e. no system)
-
- bool isLegacyCompatible() const;
-
- // Different masks for effects on the source
- enum
- {
- LL_PART_SRC_OBJ_REL_MASK = 0x01, // Accel and velocity for particles relative object rotation
- LL_PART_USE_NEW_ANGLE = 0x02, // Particles uses new 'correct' angle parameters.
- };
-
- // The different patterns for how particles are created
- enum
- {
- LL_PART_SRC_PATTERN_DROP = 0x01,
- LL_PART_SRC_PATTERN_EXPLODE = 0x02,
- // Not implemented fully yet
- LL_PART_SRC_PATTERN_ANGLE = 0x04,
- LL_PART_SRC_PATTERN_ANGLE_CONE = 0x08,
- LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY = 0x10,
- };
-
-
- void setBurstSpeedMin(const F32 spd) { mBurstSpeedMin = llclamp(spd, -100.f, 100.f); }
- void setBurstSpeedMax(const F32 spd) { mBurstSpeedMax = llclamp(spd, -100.f, 100.f); }
- void setBurstRadius(const F32 rad) { mBurstRadius = llclamp(rad, 0.f, 50.f); }
- void setPartAccel(const LLVector3 &accel);
- void setUseNewAngle() { mFlags |= LL_PART_USE_NEW_ANGLE; }
- void unsetUseNewAngle() { mFlags &= ~LL_PART_USE_NEW_ANGLE; }
-
- // Since the actual particle creation rate is
- // a combination of multiple parameters, we
- // need to clamp it using a separate method instead of an accessor.
- void clampSourceParticleRate();
-
- friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a
-
- S32 getdataBlockSize() const;
-
-private:
- bool unpackSystem(LLDataPacker &dp);
-
-public:
- // Public because I'm lazy....
-
- //
- // There are two kinds of data for the particle system
- // 1. Parameters which specify parameters of the source (mSource*)
- // 2. Parameters which specify parameters of the particles generated by the source (mPart*)
- //
-
- U32 mCRC;
- U32 mFlags;
-
- U8 mPattern; // Pattern for particle velocity/output
- F32 mInnerAngle; // Inner angle for PATTERN_ANGLE
- F32 mOuterAngle; // Outer angle for PATTERN_ANGLE
- LLVector3 mAngularVelocity; // Angular velocity for emission axis (for PATTERN_ANGLE)
-
- F32 mBurstRate; // How often to do a burst of particles
- U8 mBurstPartCount; // How many particles in a burst
- F32 mBurstRadius;
- F32 mBurstSpeedMin; // Minimum particle velocity
- F32 mBurstSpeedMax; // Maximum particle velocity
-
- F32 mMaxAge; // Maximum lifetime of this particle source
-
- LLUUID mTargetUUID; // Target UUID for the particle system
-
- F32 mStartAge; // Age at which to start the particle system (for an update after the
- // particle system has started)
-
-
- //
- // These are actually particle properties, but can be mutated by the source,
- // so are stored here instead
- //
- LLVector3 mPartAccel;
- LLUUID mPartImageID;
-
- //
- // The "template" partdata where we actually store the non-mutable particle parameters
- //
- LLPartData mPartData;
-
-protected:
- S32 mNumParticles; // Number of particles generated
-};
-
-#endif // LL_LLPARTDATA_H
+/**
+ * @file llpartdata.h
+ * @brief Particle system data packing
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPARTDATA_H
+#define LL_LLPARTDATA_H
+
+#include "lluuid.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "v2math.h"
+#include "v4color.h"
+
+class LLMessageSystem;
+class LLDataPacker;
+
+const S32 PS_CUR_VERSION = 18;
+
+//
+// These constants are used by the script code, not by the particle system itself
+//
+
+enum LLPSScriptFlags
+{
+ // Flags for the different parameters of individual particles
+ LLPS_PART_FLAGS,
+ LLPS_PART_START_COLOR,
+ LLPS_PART_START_ALPHA,
+ LLPS_PART_END_COLOR,
+ LLPS_PART_END_ALPHA,
+ LLPS_PART_START_SCALE,
+ LLPS_PART_END_SCALE,
+ LLPS_PART_MAX_AGE,
+
+ // Flags for the different parameters of the particle source
+ LLPS_SRC_ACCEL,
+ LLPS_SRC_PATTERN,
+ LLPS_SRC_INNERANGLE,
+ LLPS_SRC_OUTERANGLE,
+ LLPS_SRC_TEXTURE,
+ LLPS_SRC_BURST_RATE,
+ LLPS_SRC_BURST_DURATION,
+ LLPS_SRC_BURST_PART_COUNT,
+ LLPS_SRC_BURST_RADIUS,
+ LLPS_SRC_BURST_SPEED_MIN,
+ LLPS_SRC_BURST_SPEED_MAX,
+ LLPS_SRC_MAX_AGE,
+ LLPS_SRC_TARGET_UUID,
+ LLPS_SRC_OMEGA,
+ LLPS_SRC_ANGLE_BEGIN,
+ LLPS_SRC_ANGLE_END,
+
+ LLPS_PART_BLEND_FUNC_SOURCE,
+ LLPS_PART_BLEND_FUNC_DEST,
+ LLPS_PART_START_GLOW,
+ LLPS_PART_END_GLOW
+};
+
+
+class LLPartData
+{
+public:
+ LLPartData() :
+ mFlags(0),
+ mMaxAge(0.f),
+ mParameter(0.f)
+ {
+ }
+ bool unpackLegacy(LLDataPacker &dp);
+ bool unpack(LLDataPacker &dp);
+
+ bool pack(LLDataPacker &dp);
+
+ bool hasGlow() const;
+ bool hasBlendFunc() const;
+
+ // Masks for the different particle flags
+ enum
+ {
+ LL_PART_INTERP_COLOR_MASK = 0x01,
+ LL_PART_INTERP_SCALE_MASK = 0x02,
+ LL_PART_BOUNCE_MASK = 0x04,
+ LL_PART_WIND_MASK = 0x08,
+ LL_PART_FOLLOW_SRC_MASK = 0x10, // Follows source, no rotation following (expensive!)
+ LL_PART_FOLLOW_VELOCITY_MASK = 0x20, // Particles orient themselves with velocity
+ LL_PART_TARGET_POS_MASK = 0x40,
+ LL_PART_TARGET_LINEAR_MASK = 0x80, // Particle uses a direct linear interpolation
+ LL_PART_EMISSIVE_MASK = 0x100, // Particle is "emissive", instead of being lit
+ LL_PART_BEAM_MASK = 0x200, // Particle is a "beam" connecting source and target
+ LL_PART_RIBBON_MASK = 0x400, // Particles are joined together into one continuous triangle strip
+
+ // Not implemented yet!
+ //LL_PART_RANDOM_ACCEL_MASK = 0x100, // Particles have random acceleration
+ //LL_PART_RANDOM_VEL_MASK = 0x200, // Particles have random velocity shifts"
+ //LL_PART_TRAIL_MASK = 0x400, // Particles have historical "trails"
+
+ //sYSTEM SET FLAGS
+ LL_PART_DATA_GLOW = 0x10000,
+ LL_PART_DATA_BLEND = 0x20000,
+
+ // Viewer side use only!
+ LL_PART_HUD = 0x40000000,
+ LL_PART_DEAD_MASK = 0x80000000,
+ };
+
+ enum
+ {
+ LL_PART_BF_ONE = 0,
+ LL_PART_BF_ZERO = 1,
+ LL_PART_BF_DEST_COLOR = 2,
+ LL_PART_BF_SOURCE_COLOR = 3,
+ LL_PART_BF_ONE_MINUS_DEST_COLOR = 4,
+ LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5,
+ UNSUPPORTED_DEST_ALPHA = 6,
+ LL_PART_BF_SOURCE_ALPHA = 7,
+ UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8,
+ LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9,
+ LL_PART_BF_COUNT = 10
+ };
+
+ static bool validBlendFunc(S32 func);
+
+ void setFlags(const U32 flags);
+ void setMaxAge(const F32 max_age);
+ void setStartScale(const F32 xs, F32 ys);
+ void setEndScale(const F32 xs, F32 ys);
+ void setStartColor(const LLVector3 &rgb);
+ void setEndColor(const LLVector3 &rgb);
+ void setStartAlpha(const F32 alpha);
+ void setEndAlpha(const F32 alpha);
+
+
+ friend class LLPartSysData;
+ friend class LLViewerPartSourceScript;
+
+private:
+ S32 getSize() const;
+
+ // These are public because I'm really lazy...
+public:
+ U32 mFlags; // Particle state/interpolators in effect
+ F32 mMaxAge; // Maximum age of the particle
+ LLColor4 mStartColor; // Start color
+ LLColor4 mEndColor; // End color
+ LLVector2 mStartScale; // Start scale
+ LLVector2 mEndScale; // End scale
+
+ LLVector3 mPosOffset; // Offset from source if using FOLLOW_SOURCE
+ F32 mParameter; // A single floating point parameter
+
+ F32 mStartGlow;
+ F32 mEndGlow;
+
+ U8 mBlendFuncSource;
+ U8 mBlendFuncDest;
+};
+
+
+class LLPartSysData
+{
+public:
+ LLPartSysData();
+
+ bool unpack(LLDataPacker &dp);
+ bool unpackLegacy(LLDataPacker &dp);
+ bool unpackBlock(const S32 block_num);
+
+ static bool isNullPS(const S32 block_num); // Returns false if this is a "NULL" particle system (i.e. no system)
+
+ bool isLegacyCompatible() const;
+
+ // Different masks for effects on the source
+ enum
+ {
+ LL_PART_SRC_OBJ_REL_MASK = 0x01, // Accel and velocity for particles relative object rotation
+ LL_PART_USE_NEW_ANGLE = 0x02, // Particles uses new 'correct' angle parameters.
+ };
+
+ // The different patterns for how particles are created
+ enum
+ {
+ LL_PART_SRC_PATTERN_DROP = 0x01,
+ LL_PART_SRC_PATTERN_EXPLODE = 0x02,
+ // Not implemented fully yet
+ LL_PART_SRC_PATTERN_ANGLE = 0x04,
+ LL_PART_SRC_PATTERN_ANGLE_CONE = 0x08,
+ LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY = 0x10,
+ };
+
+
+ void setBurstSpeedMin(const F32 spd) { mBurstSpeedMin = llclamp(spd, -100.f, 100.f); }
+ void setBurstSpeedMax(const F32 spd) { mBurstSpeedMax = llclamp(spd, -100.f, 100.f); }
+ void setBurstRadius(const F32 rad) { mBurstRadius = llclamp(rad, 0.f, 50.f); }
+ void setPartAccel(const LLVector3 &accel);
+ void setUseNewAngle() { mFlags |= LL_PART_USE_NEW_ANGLE; }
+ void unsetUseNewAngle() { mFlags &= ~LL_PART_USE_NEW_ANGLE; }
+
+ // Since the actual particle creation rate is
+ // a combination of multiple parameters, we
+ // need to clamp it using a separate method instead of an accessor.
+ void clampSourceParticleRate();
+
+ friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a
+
+ S32 getdataBlockSize() const;
+
+private:
+ bool unpackSystem(LLDataPacker &dp);
+
+public:
+ // Public because I'm lazy....
+
+ //
+ // There are two kinds of data for the particle system
+ // 1. Parameters which specify parameters of the source (mSource*)
+ // 2. Parameters which specify parameters of the particles generated by the source (mPart*)
+ //
+
+ U32 mCRC;
+ U32 mFlags;
+
+ U8 mPattern; // Pattern for particle velocity/output
+ F32 mInnerAngle; // Inner angle for PATTERN_ANGLE
+ F32 mOuterAngle; // Outer angle for PATTERN_ANGLE
+ LLVector3 mAngularVelocity; // Angular velocity for emission axis (for PATTERN_ANGLE)
+
+ F32 mBurstRate; // How often to do a burst of particles
+ U8 mBurstPartCount; // How many particles in a burst
+ F32 mBurstRadius;
+ F32 mBurstSpeedMin; // Minimum particle velocity
+ F32 mBurstSpeedMax; // Maximum particle velocity
+
+ F32 mMaxAge; // Maximum lifetime of this particle source
+
+ LLUUID mTargetUUID; // Target UUID for the particle system
+
+ F32 mStartAge; // Age at which to start the particle system (for an update after the
+ // particle system has started)
+
+
+ //
+ // These are actually particle properties, but can be mutated by the source,
+ // so are stored here instead
+ //
+ LLVector3 mPartAccel;
+ LLUUID mPartImageID;
+
+ //
+ // The "template" partdata where we actually store the non-mutable particle parameters
+ //
+ LLPartData mPartData;
+
+protected:
+ S32 mNumParticles; // Number of particles generated
+};
+
+#endif // LL_LLPARTDATA_H
diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp
index 749e599c66..3e1e5daa02 100644
--- a/indra/llmessage/llproxy.cpp
+++ b/indra/llmessage/llproxy.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -48,15 +48,15 @@ static LLSocket::ptr_t tcp_open_channel(LLHost host); // Open a TCP channel to a
static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP channel
LLProxy::LLProxy():
- mHTTPProxyEnabled(false),
- mProxyMutex(),
- mUDPProxy(),
- mTCPProxy(),
- mHTTPProxy(),
- mProxyType(LLPROXY_SOCKS),
- mAuthMethodSelected(METHOD_NOAUTH),
- mSocksUsername(),
- mSocksPassword()
+ mHTTPProxyEnabled(false),
+ mProxyMutex(),
+ mUDPProxy(),
+ mTCPProxy(),
+ mHTTPProxy(),
+ mProxyType(LLPROXY_SOCKS),
+ mAuthMethodSelected(METHOD_NOAUTH),
+ mSocksUsername(),
+ mSocksPassword()
{}
LLProxy::~LLProxy()
@@ -88,112 +88,112 @@ void LLProxy::initSingleton()
*/
S32 LLProxy::proxyHandshake(LLHost proxy)
{
- S32 result;
-
- /* SOCKS 5 Auth request */
- socks_auth_request_t socks_auth_request;
- socks_auth_response_t socks_auth_response;
-
- socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
- socks_auth_request.num_methods = 1; // Sending 1 method.
- socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method.
-
- result = tcp_blocking_handshake(mProxyControlChannel,
- static_cast<char*>(static_cast<void*>(&socks_auth_request)),
- sizeof(socks_auth_request),
- static_cast<char*>(static_cast<void*>(&socks_auth_response)),
- sizeof(socks_auth_response));
- if (result != APR_SUCCESS)
- {
- LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_CONNECT_ERROR;
- }
-
- if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
- {
- LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods." << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_NOT_ACCEPTABLE;
- }
-
- /* SOCKS 5 USERNAME/PASSWORD authentication */
- if (socks_auth_response.method == METHOD_PASSWORD)
- {
- // The server has requested a username/password combination
- std::string socks_username(getSocksUser());
- std::string socks_password(getSocksPwd());
- U32 request_size = socks_username.size() + socks_password.size() + 3;
- char * password_auth = new char[request_size];
- password_auth[0] = 0x01;
- password_auth[1] = (char)(socks_username.size());
- memcpy(&password_auth[2], socks_username.c_str(), socks_username.size());
- password_auth[socks_username.size() + 2] = (char)(socks_password.size());
- memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size());
-
- authmethod_password_reply_t password_reply;
-
- result = tcp_blocking_handshake(mProxyControlChannel,
- password_auth,
- request_size,
- static_cast<char*>(static_cast<void*>(&password_reply)),
- sizeof(password_reply));
- delete[] password_auth;
-
- if (result != APR_SUCCESS)
- {
- LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_CONNECT_ERROR;
- }
-
- if (password_reply.status != AUTH_SUCCESS)
- {
- LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_AUTH_FAIL;
- }
- }
-
- /* SOCKS5 connect request */
-
- socks_command_request_t connect_request;
- socks_command_response_t connect_reply;
-
- connect_request.version = SOCKS_VERSION; // SOCKS V5
- connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP
- connect_request.reserved = FIELD_RESERVED;
- connect_request.atype = ADDRESS_IPV4;
- connect_request.address = htonl(0); // 0.0.0.0
- connect_request.port = htons(0); // 0
- // "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
- // the client MUST use a port number and address of all zeros. RFC 1928"
-
- result = tcp_blocking_handshake(mProxyControlChannel,
- static_cast<char*>(static_cast<void*>(&connect_request)),
- sizeof(connect_request),
- static_cast<char*>(static_cast<void*>(&connect_reply)),
- sizeof(connect_reply));
- if (result != APR_SUCCESS)
- {
- LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_CONNECT_ERROR;
- }
-
- if (connect_reply.reply != REPLY_REQUEST_GRANTED)
- {
- LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL;
- stopSOCKSProxy();
- return SOCKS_UDP_FWD_NOT_GRANTED;
- }
-
- mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
- mUDPProxy.setAddress(proxy.getAddress());
- // The connection was successful. We now have the UDP port to send requests that need forwarding to.
- LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL;
-
- return SOCKS_OK;
+ S32 result;
+
+ /* SOCKS 5 Auth request */
+ socks_auth_request_t socks_auth_request;
+ socks_auth_response_t socks_auth_response;
+
+ socks_auth_request.version = SOCKS_VERSION; // SOCKS version 5
+ socks_auth_request.num_methods = 1; // Sending 1 method.
+ socks_auth_request.methods = getSelectedAuthMethod(); // Send only the selected method.
+
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ static_cast<char*>(static_cast<void*>(&socks_auth_request)),
+ sizeof(socks_auth_request),
+ static_cast<char*>(static_cast<void*>(&socks_auth_response)),
+ sizeof(socks_auth_response));
+ if (result != APR_SUCCESS)
+ {
+ LL_WARNS("Proxy") << "SOCKS authentication request failed, error on TCP control channel : " << result << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_CONNECT_ERROR;
+ }
+
+ if (socks_auth_response.method == AUTH_NOT_ACCEPTABLE)
+ {
+ LL_WARNS("Proxy") << "SOCKS 5 server refused all our authentication methods." << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_NOT_ACCEPTABLE;
+ }
+
+ /* SOCKS 5 USERNAME/PASSWORD authentication */
+ if (socks_auth_response.method == METHOD_PASSWORD)
+ {
+ // The server has requested a username/password combination
+ std::string socks_username(getSocksUser());
+ std::string socks_password(getSocksPwd());
+ U32 request_size = socks_username.size() + socks_password.size() + 3;
+ char * password_auth = new char[request_size];
+ password_auth[0] = 0x01;
+ password_auth[1] = (char)(socks_username.size());
+ memcpy(&password_auth[2], socks_username.c_str(), socks_username.size());
+ password_auth[socks_username.size() + 2] = (char)(socks_password.size());
+ memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size());
+
+ authmethod_password_reply_t password_reply;
+
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ password_auth,
+ request_size,
+ static_cast<char*>(static_cast<void*>(&password_reply)),
+ sizeof(password_reply));
+ delete[] password_auth;
+
+ if (result != APR_SUCCESS)
+ {
+ LL_WARNS("Proxy") << "SOCKS authentication failed, error on TCP control channel : " << result << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_CONNECT_ERROR;
+ }
+
+ if (password_reply.status != AUTH_SUCCESS)
+ {
+ LL_WARNS("Proxy") << "SOCKS authentication failed" << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_AUTH_FAIL;
+ }
+ }
+
+ /* SOCKS5 connect request */
+
+ socks_command_request_t connect_request;
+ socks_command_response_t connect_reply;
+
+ connect_request.version = SOCKS_VERSION; // SOCKS V5
+ connect_request.command = COMMAND_UDP_ASSOCIATE; // Associate UDP
+ connect_request.reserved = FIELD_RESERVED;
+ connect_request.atype = ADDRESS_IPV4;
+ connect_request.address = htonl(0); // 0.0.0.0
+ connect_request.port = htons(0); // 0
+ // "If the client is not in possession of the information at the time of the UDP ASSOCIATE,
+ // the client MUST use a port number and address of all zeros. RFC 1928"
+
+ result = tcp_blocking_handshake(mProxyControlChannel,
+ static_cast<char*>(static_cast<void*>(&connect_request)),
+ sizeof(connect_request),
+ static_cast<char*>(static_cast<void*>(&connect_reply)),
+ sizeof(connect_reply));
+ if (result != APR_SUCCESS)
+ {
+ LL_WARNS("Proxy") << "SOCKS connect request failed, error on TCP control channel : " << result << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_CONNECT_ERROR;
+ }
+
+ if (connect_reply.reply != REPLY_REQUEST_GRANTED)
+ {
+ LL_WARNS("Proxy") << "Connection to SOCKS 5 server failed, UDP forward request not granted" << LL_ENDL;
+ stopSOCKSProxy();
+ return SOCKS_UDP_FWD_NOT_GRANTED;
+ }
+
+ mUDPProxy.setPort(ntohs(connect_reply.port)); // reply port is in network byte order
+ mUDPProxy.setAddress(proxy.getAddress());
+ // The connection was successful. We now have the UDP port to send requests that need forwarding to.
+ LL_INFOS("Proxy") << "SOCKS 5 UDP proxy connected on " << mUDPProxy << LL_ENDL;
+
+ return SOCKS_OK;
}
/**
@@ -209,38 +209,38 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
*/
S32 LLProxy::startSOCKSProxy(LLHost host)
{
- if (host.isOk())
- {
- mTCPProxy = host;
- }
- else
- {
- return SOCKS_INVALID_HOST;
- }
-
- // Close any running SOCKS connection.
- stopSOCKSProxy();
-
- mProxyControlChannel = tcp_open_channel(mTCPProxy);
- if (!mProxyControlChannel)
- {
- return SOCKS_HOST_CONNECT_FAILED;
- }
-
- S32 status = proxyHandshake(mTCPProxy);
-
- if (status != SOCKS_OK)
- {
- // Shut down the proxy if any of the above steps failed.
- stopSOCKSProxy();
- }
- else
- {
- // Connection was successful.
- sUDPProxyEnabled = true;
- }
-
- return status;
+ if (host.isOk())
+ {
+ mTCPProxy = host;
+ }
+ else
+ {
+ return SOCKS_INVALID_HOST;
+ }
+
+ // Close any running SOCKS connection.
+ stopSOCKSProxy();
+
+ mProxyControlChannel = tcp_open_channel(mTCPProxy);
+ if (!mProxyControlChannel)
+ {
+ return SOCKS_HOST_CONNECT_FAILED;
+ }
+
+ S32 status = proxyHandshake(mTCPProxy);
+
+ if (status != SOCKS_OK)
+ {
+ // Shut down the proxy if any of the above steps failed.
+ stopSOCKSProxy();
+ }
+ else
+ {
+ // Connection was successful.
+ sUDPProxyEnabled = true;
+ }
+
+ return status;
}
/**
@@ -252,21 +252,21 @@ S32 LLProxy::startSOCKSProxy(LLHost host)
*/
void LLProxy::stopSOCKSProxy()
{
- sUDPProxyEnabled = false;
+ sUDPProxyEnabled = false;
- // If the SOCKS proxy is requested to stop and we are using that for HTTP as well
- // then we must shut down any HTTP proxy operations. But it is allowable if web
- // proxy is being used to continue proxying HTTP.
+ // If the SOCKS proxy is requested to stop and we are using that for HTTP as well
+ // then we must shut down any HTTP proxy operations. But it is allowable if web
+ // proxy is being used to continue proxying HTTP.
- if (LLPROXY_SOCKS == getHTTPProxyType())
- {
- disableHTTPProxy();
- }
+ if (LLPROXY_SOCKS == getHTTPProxyType())
+ {
+ disableHTTPProxy();
+ }
- if (mProxyControlChannel)
- {
- tcp_close_channel(&mProxyControlChannel);
- }
+ if (mProxyControlChannel)
+ {
+ tcp_close_channel(&mProxyControlChannel);
+ }
}
/**
@@ -274,9 +274,9 @@ void LLProxy::stopSOCKSProxy()
*/
void LLProxy::setAuthNone()
{
- LLMutexLock lock(&mProxyMutex);
+ LLMutexLock lock(&mProxyMutex);
- mAuthMethodSelected = METHOD_NOAUTH;
+ mAuthMethodSelected = METHOD_NOAUTH;
}
/**
@@ -286,27 +286,27 @@ void LLProxy::setAuthNone()
* and password conform to the lengths allowed by the
* SOCKS protocol.
*
- * @param username The SOCKS username to send.
- * @param password The SOCKS password to send.
+ * @param username The SOCKS username to send.
+ * @param password The SOCKS password to send.
* @return Return true if applying the settings was successful. No changes are made if false.
*
*/
bool LLProxy::setAuthPassword(const std::string &username, const std::string &password)
{
- if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN ||
- username.length() < SOCKSMINUSERNAMELEN || password.length() < SOCKSMINPASSWORDLEN)
- {
- LL_WARNS("Proxy") << "Invalid SOCKS 5 password or username length." << LL_ENDL;
- return false;
- }
+ if (username.length() > SOCKSMAXUSERNAMELEN || password.length() > SOCKSMAXPASSWORDLEN ||
+ username.length() < SOCKSMINUSERNAMELEN || password.length() < SOCKSMINPASSWORDLEN)
+ {
+ LL_WARNS("Proxy") << "Invalid SOCKS 5 password or username length." << LL_ENDL;
+ return false;
+ }
- LLMutexLock lock(&mProxyMutex);
+ LLMutexLock lock(&mProxyMutex);
- mAuthMethodSelected = METHOD_PASSWORD;
- mSocksUsername = username;
- mSocksPassword = password;
+ mAuthMethodSelected = METHOD_PASSWORD;
+ mSocksUsername = username;
+ mSocksPassword = password;
- return true;
+ return true;
}
/**
@@ -320,20 +320,20 @@ bool LLProxy::setAuthPassword(const std::string &username, const std::string &pa
*/
bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type)
{
- if (!httpHost.isOk())
- {
- LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL;
- return false;
- }
+ if (!httpHost.isOk())
+ {
+ LL_WARNS("Proxy") << "Invalid SOCKS 5 Server" << LL_ENDL;
+ return false;
+ }
- LLMutexLock lock(&mProxyMutex);
+ LLMutexLock lock(&mProxyMutex);
- mHTTPProxy = httpHost;
- mProxyType = type;
+ mHTTPProxy = httpHost;
+ mProxyType = type;
- mHTTPProxyEnabled = true;
+ mHTTPProxyEnabled = true;
- return true;
+ return true;
}
/**
@@ -345,17 +345,17 @@ bool LLProxy::enableHTTPProxy(LLHost httpHost, LLHttpProxyType type)
*/
bool LLProxy::enableHTTPProxy()
{
- bool ok;
+ bool ok;
- LLMutexLock lock(&mProxyMutex);
+ LLMutexLock lock(&mProxyMutex);
- ok = (mHTTPProxy.isOk());
- if (ok)
- {
- mHTTPProxyEnabled = true;
- }
+ ok = (mHTTPProxy.isOk());
+ if (ok)
+ {
+ mHTTPProxyEnabled = true;
+ }
- return ok;
+ return ok;
}
/**
@@ -363,9 +363,9 @@ bool LLProxy::enableHTTPProxy()
*/
void LLProxy::disableHTTPProxy()
{
- LLMutexLock lock(&mProxyMutex);
+ LLMutexLock lock(&mProxyMutex);
- mHTTPProxyEnabled = false;
+ mHTTPProxyEnabled = false;
}
/**
@@ -373,8 +373,8 @@ void LLProxy::disableHTTPProxy()
*/
LLHttpProxyType LLProxy::getHTTPProxyType() const
{
- LLMutexLock lock(&mProxyMutex);
- return mProxyType;
+ LLMutexLock lock(&mProxyMutex);
+ return mProxyType;
}
/**
@@ -382,8 +382,8 @@ LLHttpProxyType LLProxy::getHTTPProxyType() const
*/
std::string LLProxy::getSocksPwd() const
{
- LLMutexLock lock(&mProxyMutex);
- return mSocksPassword;
+ LLMutexLock lock(&mProxyMutex);
+ return mSocksPassword;
}
/**
@@ -391,8 +391,8 @@ std::string LLProxy::getSocksPwd() const
*/
std::string LLProxy::getSocksUser() const
{
- LLMutexLock lock(&mProxyMutex);
- return mSocksUsername;
+ LLMutexLock lock(&mProxyMutex);
+ return mSocksUsername;
}
/**
@@ -402,8 +402,8 @@ std::string LLProxy::getSocksUser() const
*/
LLSocks5AuthType LLProxy::getSelectedAuthMethod() const
{
- LLMutexLock lock(&mProxyMutex);
- return mAuthMethodSelected;
+ LLMutexLock lock(&mProxyMutex);
+ return mAuthMethodSelected;
}
/**
@@ -434,32 +434,32 @@ void LLProxy::cleanupClass()
*/
void LLProxy::applyProxySettings(CURL* handle)
{
- // Do a faster unlocked check to see if we are supposed to proxy.
- if (sProxyInstance && sProxyInstance->mHTTPProxyEnabled)
- {
- // We think we should proxy, lock the proxy mutex. sProxyInstance is not protected by mutex
- LLMutexLock lock(&sProxyInstance->mProxyMutex);
- // Now test again to verify that the proxy wasn't disabled between the first check and the lock.
- if (sProxyInstance->mHTTPProxyEnabled)
- {
- LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, sProxyInstance->mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY);
- LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, sProxyInstance->mHTTPProxy.getPort()), CURLOPT_PROXYPORT);
-
- if (sProxyInstance->mProxyType == LLPROXY_SOCKS)
- {
- LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);
- if (sProxyInstance->mAuthMethodSelected == METHOD_PASSWORD)
- {
- std::string auth_string = sProxyInstance->mSocksUsername + ":" + sProxyInstance->mSocksPassword;
- LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);
- }
- }
- else
- {
- LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);
- }
- }
- }
+ // Do a faster unlocked check to see if we are supposed to proxy.
+ if (sProxyInstance && sProxyInstance->mHTTPProxyEnabled)
+ {
+ // We think we should proxy, lock the proxy mutex. sProxyInstance is not protected by mutex
+ LLMutexLock lock(&sProxyInstance->mProxyMutex);
+ // Now test again to verify that the proxy wasn't disabled between the first check and the lock.
+ if (sProxyInstance->mHTTPProxyEnabled)
+ {
+ LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, sProxyInstance->mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY);
+ LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, sProxyInstance->mHTTPProxy.getPort()), CURLOPT_PROXYPORT);
+
+ if (sProxyInstance->mProxyType == LLPROXY_SOCKS)
+ {
+ LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);
+ if (sProxyInstance->mAuthMethodSelected == METHOD_PASSWORD)
+ {
+ std::string auth_string = sProxyInstance->mSocksUsername + ":" + sProxyInstance->mSocksPassword;
+ LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);
+ }
+ }
+ else
+ {
+ LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);
+ }
+ }
+ }
}
/**
@@ -468,59 +468,59 @@ void LLProxy::applyProxySettings(CURL* handle)
* This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking
* operation would impact the operation of the viewer.
*
- * @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP.
- * @param dataout Data to send.
- * @param outlen Length of dataout.
- * @param datain Buffer for received data. Undefined if return value is not APR_SUCCESS.
- * @param maxinlen Maximum possible length of received data. Short reads are allowed.
- * @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received.
+ * @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP.
+ * @param dataout Data to send.
+ * @param outlen Length of dataout.
+ * @param datain Buffer for received data. Undefined if return value is not APR_SUCCESS.
+ * @param maxinlen Maximum possible length of received data. Short reads are allowed.
+ * @return Indicates APR status code of exchange. APR_SUCCESS if exchange was successful, -1 if invalid data length was received.
*/
static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen)
{
- apr_socket_t* apr_socket = handle->getSocket();
- apr_status_t rv = APR_SUCCESS;
-
- apr_size_t expected_len = outlen;
-
- handle->setBlocking(1000);
-
- rv = apr_socket_send(apr_socket, dataout, &outlen);
- if (APR_SUCCESS != rv)
- {
- char buf[MAX_STRING];
- LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
- ll_apr_warn_status(rv);
- }
- else if (expected_len != outlen)
- {
- LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len <<
- " Sent: " << outlen << LL_ENDL;
- rv = -1;
- }
-
- ms_sleep(1);
-
- if (APR_SUCCESS == rv)
- {
- expected_len = maxinlen;
- rv = apr_socket_recv(apr_socket, datain, &maxinlen);
- if (rv != APR_SUCCESS)
- {
- char buf[MAX_STRING];
- LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
- ll_apr_warn_status(rv);
- }
- else if (expected_len < maxinlen)
- {
- LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len <<
- " Received: " << maxinlen << LL_ENDL;
- rv = -1;
- }
- }
-
- handle->setNonBlocking();
-
- return rv;
+ apr_socket_t* apr_socket = handle->getSocket();
+ apr_status_t rv = APR_SUCCESS;
+
+ apr_size_t expected_len = outlen;
+
+ handle->setBlocking(1000);
+
+ rv = apr_socket_send(apr_socket, dataout, &outlen);
+ if (APR_SUCCESS != rv)
+ {
+ char buf[MAX_STRING];
+ LL_WARNS("Proxy") << "Error sending data to proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
+ ll_apr_warn_status(rv);
+ }
+ else if (expected_len != outlen)
+ {
+ LL_WARNS("Proxy") << "Incorrect data length sent. Expected: " << expected_len <<
+ " Sent: " << outlen << LL_ENDL;
+ rv = -1;
+ }
+
+ ms_sleep(1);
+
+ if (APR_SUCCESS == rv)
+ {
+ expected_len = maxinlen;
+ rv = apr_socket_recv(apr_socket, datain, &maxinlen);
+ if (rv != APR_SUCCESS)
+ {
+ char buf[MAX_STRING];
+ LL_WARNS("Proxy") << "Error receiving data from proxy control channel, status: " << rv << " " << apr_strerror(rv, buf, MAX_STRING) << LL_ENDL;
+ ll_apr_warn_status(rv);
+ }
+ else if (expected_len < maxinlen)
+ {
+ LL_WARNS("Proxy") << "Incorrect data length received. Expected: " << expected_len <<
+ " Received: " << maxinlen << LL_ENDL;
+ rv = -1;
+ }
+ }
+
+ handle->setNonBlocking();
+
+ return rv;
}
/**
@@ -528,19 +528,19 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou
*
* Checks for a successful connection, and makes sure the connection is closed if it fails.
*
- * @param host The host to open the connection to.
- * @return The created socket. Will evaluate as NULL if the connection is unsuccessful.
+ * @param host The host to open the connection to.
+ * @return The created socket. Will evaluate as NULL if the connection is unsuccessful.
*/
static LLSocket::ptr_t tcp_open_channel(LLHost host)
{
- LLSocket::ptr_t socket = LLSocket::create(NULL, LLSocket::STREAM_TCP);
- bool connected = socket->blockingConnect(host);
- if (!connected)
- {
- tcp_close_channel(&socket);
- }
-
- return socket;
+ LLSocket::ptr_t socket = LLSocket::create(NULL, LLSocket::STREAM_TCP);
+ bool connected = socket->blockingConnect(host);
+ if (!connected)
+ {
+ tcp_close_channel(&socket);
+ }
+
+ return socket;
}
/**
@@ -550,6 +550,6 @@ static LLSocket::ptr_t tcp_open_channel(LLHost host)
*/
static void tcp_close_channel(LLSocket::ptr_t* handle_ptr)
{
- LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL;
- handle_ptr->reset();
+ LL_DEBUGS("Proxy") << "Resetting proxy LLSocket handle, use_count == " << handle_ptr->use_count() << LL_ENDL;
+ handle_ptr->reset();
}
diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h
index 8a64cdbfaa..10d4911c60 100644
--- a/indra/llmessage/llproxy.h
+++ b/indra/llmessage/llproxy.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,7 +47,7 @@
#define SOCKS_INVALID_HOST (-7)
#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
+#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
#endif
#define SOCKSMAXUSERNAMELEN 255
@@ -68,8 +68,8 @@
// Lets just use our own ipv4 struct rather than dragging in system
// specific headers
union ipv4_address_t {
- U8 octets[4];
- U32 addr32;
+ U8 octets[4];
+ U32 addr32;
};
// SOCKS 5 control channel commands
@@ -98,22 +98,22 @@ union ipv4_address_t {
// SOCKS 5 command packet
struct socks_command_request_t {
- U8 version;
- U8 command;
- U8 reserved;
- U8 atype;
- U32 address;
- U16 port;
+ U8 version;
+ U8 command;
+ U8 reserved;
+ U8 atype;
+ U32 address;
+ U16 port;
};
// Standard SOCKS 5 reply packet
struct socks_command_response_t {
- U8 version;
- U8 reply;
- U8 reserved;
- U8 atype;
- U8 add_bytes[4];
- U16 port;
+ U8 version;
+ U8 reply;
+ U8 reserved;
+ U8 atype;
+ U8 add_bytes[4];
+ U16 port;
};
#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available
@@ -121,30 +121,30 @@ struct socks_command_response_t {
// SOCKS 5 authentication request, stating which methods the client supports
struct socks_auth_request_t {
- U8 version;
- U8 num_methods;
- U8 methods; // We are only using a single method currently
+ U8 version;
+ U8 num_methods;
+ U8 methods; // We are only using a single method currently
};
// SOCKS 5 authentication response packet, stating server preferred method
struct socks_auth_response_t {
- U8 version;
- U8 method;
+ U8 version;
+ U8 method;
};
// SOCKS 5 password reply packet
struct authmethod_password_reply_t {
- U8 version;
- U8 status;
+ U8 version;
+ U8 status;
};
// SOCKS 5 UDP packet header
struct proxywrap_t {
- U16 rsv;
- U8 frag;
- U8 atype;
- U32 addr;
- U16 port;
+ U16 rsv;
+ U8 frag;
+ U8 atype;
+ U32 addr;
+ U16 port;
};
#pragma pack(pop) /* restore original alignment from stack */
@@ -153,16 +153,16 @@ struct proxywrap_t {
// Currently selected HTTP proxy type
enum LLHttpProxyType
{
- LLPROXY_SOCKS = 0,
- LLPROXY_HTTP = 1
+ LLPROXY_SOCKS = 0,
+ LLPROXY_HTTP = 1
};
// Auth types
enum LLSocks5AuthType
{
- METHOD_NOAUTH = 0x00, // Client supports no auth
- METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported)
- METHOD_PASSWORD = 0x02 // Client supports username/password
+ METHOD_NOAUTH = 0x00, // Client supports no auth
+ METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported)
+ METHOD_PASSWORD = 0x02 // Client supports username/password
};
/**
@@ -213,139 +213,139 @@ enum LLSocks5AuthType
*
* To ensure thread safety, all LLProxy members that relate to the HTTP
* proxy require the LLProxyMutex to be locked before accessing.
- *
+ *
* *TODO$: This should be moved into the LLCore::Http space.
- *
+ *
*/
class LLProxy: public LLSingleton<LLProxy>
{
- /*###########################################################################################
- METHODS THAT DO NOT LOCK mProxyMutex!
- ###########################################################################################*/
- // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
- LLSINGLETON(LLProxy);
- LOG_CLASS(LLProxy);
+ /*###########################################################################################
+ METHODS THAT DO NOT LOCK mProxyMutex!
+ ###########################################################################################*/
+ // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
+ LLSINGLETON(LLProxy);
+ LOG_CLASS(LLProxy);
/*virtual*/ void initSingleton() override;
public:
- // Static check for enabled status for UDP packets. Call from main thread only.
- static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
+ // Static check for enabled status for UDP packets. Call from main thread only.
+ static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
- // Get the UDP proxy address and port. Call from main thread only.
- LLHost getUDPProxy() const { return mUDPProxy; }
+ // Get the UDP proxy address and port. Call from main thread only.
+ LLHost getUDPProxy() const { return mUDPProxy; }
- /*###########################################################################################
- END OF NON-LOCKING METHODS
- ###########################################################################################*/
+ /*###########################################################################################
+ END OF NON-LOCKING METHODS
+ ###########################################################################################*/
- /*###########################################################################################
- METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
- ###########################################################################################*/
+ /*###########################################################################################
+ METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ ###########################################################################################*/
private:
- // Destructor, closes open connections. Do not call directly, use cleanupClass().
- ~LLProxy();
+ // Destructor, closes open connections. Do not call directly, use cleanupClass().
+ ~LLProxy();
public:
- // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be
- // destroyed before the call to apr_terminate. Call from main thread only.
- static void cleanupClass();
+ // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be
+ // destroyed before the call to apr_terminate. Call from main thread only.
+ static void cleanupClass();
- // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
- // Safe to call from any thread.
- static void applyProxySettings(CURL* handle);
- // Start a connection to the SOCKS 5 proxy. Call from main thread only.
- S32 startSOCKSProxy(LLHost host);
+ // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
+ // Safe to call from any thread.
+ static void applyProxySettings(CURL* handle);
+ // Start a connection to the SOCKS 5 proxy. Call from main thread only.
+ S32 startSOCKSProxy(LLHost host);
- // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only.
- void stopSOCKSProxy();
+ // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only.
+ void stopSOCKSProxy();
- // Use Password auth when connecting to the SOCKS proxy. Call from main thread only.
- bool setAuthPassword(const std::string &username, const std::string &password);
+ // Use Password auth when connecting to the SOCKS proxy. Call from main thread only.
+ bool setAuthPassword(const std::string &username, const std::string &password);
- // Disable authentication when connecting to the SOCKS proxy. Call from main thread only.
- void setAuthNone();
+ // Disable authentication when connecting to the SOCKS proxy. Call from main thread only.
+ void setAuthNone();
- // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy.
- // as specified in type. Call from main thread only.
- bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type);
- bool enableHTTPProxy();
+ // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy.
+ // as specified in type. Call from main thread only.
+ bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type);
+ bool enableHTTPProxy();
- // Stop proxying HTTP packets. Call from main thread only.
- void disableHTTPProxy();
+ // Stop proxying HTTP packets. Call from main thread only.
+ void disableHTTPProxy();
- /*###########################################################################################
- END OF LOCKING METHODS
- ###########################################################################################*/
+ /*###########################################################################################
+ END OF LOCKING METHODS
+ ###########################################################################################*/
private:
- /*###########################################################################################
- METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
- ###########################################################################################*/
+ /*###########################################################################################
+ METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
+ ###########################################################################################*/
- // Perform a SOCKS 5 authentication and UDP association with the proxy server.
- S32 proxyHandshake(LLHost proxy);
+ // Perform a SOCKS 5 authentication and UDP association with the proxy server.
+ S32 proxyHandshake(LLHost proxy);
- // Get the currently selected auth method.
- LLSocks5AuthType getSelectedAuthMethod() const;
+ // Get the currently selected auth method.
+ LLSocks5AuthType getSelectedAuthMethod() const;
- // Get the currently selected HTTP proxy type
- LLHttpProxyType getHTTPProxyType() const;
+ // Get the currently selected HTTP proxy type
+ LLHttpProxyType getHTTPProxyType() const;
- std::string getSocksPwd() const;
- std::string getSocksUser() const;
+ std::string getSocksPwd() const;
+ std::string getSocksUser() const;
- /*###########################################################################################
- END OF LOCKING METHODS
- ###########################################################################################*/
+ /*###########################################################################################
+ END OF LOCKING METHODS
+ ###########################################################################################*/
private:
- // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
- // Instead use enableHTTPProxy() and disableHTTPProxy() instead.
- mutable LLAtomicBool mHTTPProxyEnabled;
+ // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
+ // Instead use enableHTTPProxy() and disableHTTPProxy() instead.
+ mutable LLAtomicBool mHTTPProxyEnabled;
- // Mutex to protect shared members in non-main thread calls to applyProxySettings().
- mutable LLMutex mProxyMutex;
+ // Mutex to protect shared members in non-main thread calls to applyProxySettings().
+ mutable LLMutex mProxyMutex;
- /*###########################################################################################
- MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
- ###########################################################################################*/
+ /*###########################################################################################
+ MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
+ ###########################################################################################*/
- // Is the UDP proxy enabled?
- static bool sUDPProxyEnabled;
+ // Is the UDP proxy enabled?
+ static bool sUDPProxyEnabled;
- // UDP proxy address and port
- LLHost mUDPProxy;
- // TCP proxy control channel address and port
- LLHost mTCPProxy;
+ // UDP proxy address and port
+ LLHost mUDPProxy;
+ // TCP proxy control channel address and port
+ LLHost mTCPProxy;
- // socket handle to proxy TCP control channel
- LLSocket::ptr_t mProxyControlChannel;
+ // socket handle to proxy TCP control channel
+ LLSocket::ptr_t mProxyControlChannel;
- /*###########################################################################################
- END OF UNSHARED MEMBERS
- ###########################################################################################*/
+ /*###########################################################################################
+ END OF UNSHARED MEMBERS
+ ###########################################################################################*/
- /*###########################################################################################
- MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
- ###########################################################################################*/
+ /*###########################################################################################
+ MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
+ ###########################################################################################*/
- // HTTP proxy address and port
- LLHost mHTTPProxy;
+ // HTTP proxy address and port
+ LLHost mHTTPProxy;
- // Currently selected HTTP proxy type. Can be web or socks.
- LLHttpProxyType mProxyType;
+ // Currently selected HTTP proxy type. Can be web or socks.
+ LLHttpProxyType mProxyType;
- // SOCKS 5 selected authentication method.
- LLSocks5AuthType mAuthMethodSelected;
+ // SOCKS 5 selected authentication method.
+ LLSocks5AuthType mAuthMethodSelected;
- // SOCKS 5 username
- std::string mSocksUsername;
- // SOCKS 5 password
- std::string mSocksPassword;
+ // SOCKS 5 username
+ std::string mSocksUsername;
+ // SOCKS 5 password
+ std::string mSocksPassword;
- /*###########################################################################################
- END OF SHARED MEMBERS
- ###########################################################################################*/
+ /*###########################################################################################
+ END OF SHARED MEMBERS
+ ###########################################################################################*/
// A hack to get arround getInstance() and capture_dependency() which are unsafe to use inside threads
// set/reset on init/cleanup, strictly for use in applyProxySettings
diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp
index 52e6be6f98..646f8aa2ca 100644
--- a/indra/llmessage/llpumpio.cpp
+++ b/indra/llmessage/llpumpio.cpp
@@ -1,1150 +1,1150 @@
-/**
- * @file llpumpio.cpp
- * @author Phoenix
- * @date 2004-11-21
- * @brief Implementation of the i/o pump and related functions.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llpumpio.h"
-
-#include <map>
-#include <set>
-#include "apr_poll.h"
-
-#include "llapr.h"
-#include "llfasttimer.h"
-#include "llstl.h"
-
-// These should not be enabled in production, but they can be
-// intensely useful during development for finding certain kinds of
-// bugs.
-#if LL_LINUX
-//#define LL_DEBUG_PIPE_TYPE_IN_PUMP 1
-//#define LL_DEBUG_POLL_FILE_DESCRIPTORS 1
-#if LL_DEBUG_POLL_FILE_DESCRIPTORS
-#include "apr_portable.h"
-#endif
-#endif
-
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
-#include <typeinfo>
-#endif
-
-// constants for poll timeout. if we are threading, we want to have a
-// longer poll timeout.
-static const S32 DEFAULT_POLL_TIMEOUT = 0;
-
-// The default (and fallback) expiration time for chains
-const F32 DEFAULT_CHAIN_EXPIRY_SECS = 30.0f;
-extern const F32 SHORT_CHAIN_EXPIRY_SECS = 1.0f;
-extern const F32 NEVER_CHAIN_EXPIRY_SECS = 0.0f;
-
-// sorta spammy debug modes.
-//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR 1
-//#define LL_DEBUG_PROCESS_LINK 1
-//#define LL_DEBUG_PROCESS_RETURN_VALUE 1
-
-// Super spammy debug mode.
-//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN 1
-//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT 1
-
-//
-// local functions
-//
-void ll_debug_poll_fd(const char* msg, const apr_pollfd_t* poll)
-{
-#if LL_DEBUG_POLL_FILE_DESCRIPTORS
- if(!poll)
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << ": no pollfd." << LL_ENDL;
- return;
- }
- if(poll->desc.s)
- {
- apr_os_sock_t os_sock;
- if(APR_SUCCESS == apr_os_sock_get(&os_sock, poll->desc.s))
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " on fd " << os_sock
- << " at " << poll->desc.s << LL_ENDL;
- }
- else
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " no fd "
- << " at " << poll->desc.s << LL_ENDL;
- }
- }
- else if(poll->desc.f)
- {
- apr_os_file_t os_file;
- if(APR_SUCCESS == apr_os_file_get(&os_file, poll->desc.f))
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " on fd " << os_file
- << " at " << poll->desc.f << LL_ENDL;
- }
- else
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " no fd "
- << " at " << poll->desc.f << LL_ENDL;
- }
- }
- else
- {
- LL_DEBUGS() << "Poll -- " << (msg?msg:"") << ": no descriptor." << LL_ENDL;
- }
-#endif
-}
-
-/**
- * @class
- */
-class LLChainSleeper : public LLRunnable
-{
-public:
- static LLRunner::run_ptr_t build(LLPumpIO* pump, S32 key)
- {
- return LLRunner::run_ptr_t(new LLChainSleeper(pump, key));
- }
-
- virtual void run(LLRunner* runner, S64 handle)
- {
- mPump->clearLock(mKey);
- }
-
-protected:
- LLChainSleeper(LLPumpIO* pump, S32 key) : mPump(pump), mKey(key) {}
- LLPumpIO* mPump;
- S32 mKey;
-};
-
-
-/**
- * @struct ll_delete_apr_pollset_fd_client_data
- * @brief This is a simple helper class to clean up our client data.
- */
-struct ll_delete_apr_pollset_fd_client_data
-{
- typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
- void operator()(const pipe_conditional_t& conditional)
- {
- S32* client_id = (S32*)conditional.second.client_data;
- delete client_id;
- }
-};
-
-/**
- * LLPumpIO
- */
-LLPumpIO::LLPumpIO(apr_pool_t* pool) :
- mState(LLPumpIO::NORMAL),
- mRebuildPollset(false),
- mPollset(NULL),
- mPollsetClientID(0),
- mNextLock(0),
- mPool(NULL),
- mCurrentPool(NULL),
- mCurrentPoolReallocCount(0),
- mCurrentChain(mRunningChains.end())
-{
- mCurrentChain = mRunningChains.end();
-
- initialize(pool);
-}
-
-LLPumpIO::~LLPumpIO()
-{
- cleanup();
-}
-
-bool LLPumpIO::prime(apr_pool_t* pool)
-{
- cleanup();
- initialize(pool);
- return pool != nullptr;
-}
-
-bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)
-{
- if (chain.empty())
- return false;
-
- LLChainInfo info;
- info.mHasCurlRequest = has_curl_request;
- info.setTimeoutSeconds(timeout);
- info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
- info.mData->setThreaded(has_curl_request);
- LLLinkInfo link;
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "LLPumpIO::addChain() " << chain[0] << " '"
- << typeid(*(chain[0])).name() << "'" << LL_ENDL;
-#else
- LL_DEBUGS() << "LLPumpIO::addChain() " << chain[0] <<LL_ENDL;
-#endif
- chain_t::const_iterator it = chain.begin();
- chain_t::const_iterator end = chain.end();
- for(; it != end; ++it)
- {
- link.mPipe = (*it);
- link.mChannels = info.mData->nextChannel();
- info.mChainLinks.push_back(link);
- }
- mPendingChains.push_back(info);
- return true;
-}
-
-bool LLPumpIO::addChain(
- const LLPumpIO::links_t& links,
- LLIOPipe::buffer_ptr_t data,
- LLSD context,
- F32 timeout)
-{
- // remember that if the caller is providing a full link
- // description, we need to have that description matched to a
- // particular buffer.
- if (!data)
- return false;
- if (links.empty())
- return false;
-
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "LLPumpIO::addChain() " << links[0].mPipe << " '"
- << typeid(*(links[0].mPipe)).name() << "'" << LL_ENDL;
-#else
- LL_DEBUGS() << "LLPumpIO::addChain() " << links[0].mPipe << LL_ENDL;
-#endif
- LLChainInfo info;
- info.setTimeoutSeconds(timeout);
- info.mChainLinks = links;
- info.mData = data;
- info.mContext = context;
- mPendingChains.push_back(info);
- return true;
-}
-
-bool LLPumpIO::setTimeoutSeconds(F32 timeout)
-{
- // If no chain is running, return failure.
- if (mRunningChains.end() == mCurrentChain)
- {
- return false;
- }
-
- (*mCurrentChain).setTimeoutSeconds(timeout);
- return true;
-}
-
-void LLPumpIO::adjustTimeoutSeconds(F32 delta)
-{
- // Ensure a chain is running
- if (mRunningChains.end() != mCurrentChain)
- {
- (*mCurrentChain).adjustTimeoutSeconds(delta);
- }
-}
-
-static std::string events_2_string(apr_int16_t events)
-{
- std::ostringstream ostr;
- if (events & APR_POLLIN)
- {
- ostr << "read,";
- }
- if (events & APR_POLLPRI)
- {
- ostr << "priority,";
- }
- if (events & APR_POLLOUT)
- {
- ostr << "write,";
- }
- if (events & APR_POLLERR)
- {
- ostr << "error,";
- }
- if (events & APR_POLLHUP)
- {
- ostr << "hangup,";
- }
- if (events & APR_POLLNVAL)
- {
- ostr << "invalid,";
- }
- return chop_tail_copy(ostr.str(), 1);
-}
-
-bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
-{
- if (!pipe)
- return false;
- ll_debug_poll_fd("Set conditional", poll);
-
- LL_DEBUGS() << "Setting conditionals (" << (poll ? events_2_string(poll->reqevents) :"null")
- << ") "
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- << "on pipe " << typeid(*pipe).name()
-#endif
- << " at " << pipe << LL_ENDL;
-
- // remove any matching poll file descriptors for this pipe.
- LLIOPipe::ptr_t pipe_ptr(pipe);
- LLChainInfo::conditionals_t::iterator it;
- it = (*mCurrentChain).mDescriptors.begin();
- while(it != (*mCurrentChain).mDescriptors.end())
- {
- LLChainInfo::pipe_conditional_t& value = (*it);
- if(pipe_ptr == value.first)
- {
- ll_delete_apr_pollset_fd_client_data()(value);
- it = (*mCurrentChain).mDescriptors.erase(it);
- mRebuildPollset = true;
- }
- else
- {
- ++it;
- }
- }
-
- if(!poll)
- {
- mRebuildPollset = true;
- return true;
- }
- LLChainInfo::pipe_conditional_t value;
- value.first = pipe_ptr;
- value.second = *poll;
- value.second.rtnevents = 0;
- if(!poll->p)
- {
- // each fd needs a pool to work with, so if one was
- // not specified, use this pool.
- // *FIX: Should it always be this pool?
- value.second.p = mPool;
- }
- value.second.client_data = new S32(++mPollsetClientID);
- (*mCurrentChain).mDescriptors.push_back(value);
- mRebuildPollset = true;
- return true;
-}
-
-S32 LLPumpIO::setLock()
-{
- // *NOTE: I do not think it is necessary to acquire a mutex here
- // since this should only be called during the pump(), and should
- // only change the running chain. Any other use of this method is
- // incorrect usage. If it becomes necessary to acquire a lock
- // here, be sure to lock here and call a protected method to get
- // the lock, and sleepChain() should probably acquire the same
- // lock while and calling the same protected implementation to
- // lock the runner at the same time.
-
- // If no chain is running, return failure.
- if(mRunningChains.end() == mCurrentChain)
- {
- return 0;
- }
-
- // deal with wrap.
- if(++mNextLock <= 0)
- {
- mNextLock = 1;
- }
-
- // set the lock
- (*mCurrentChain).mLock = mNextLock;
- return mNextLock;
-}
-
-void LLPumpIO::clearLock(S32 key)
-{
- // We need to lock it here since we do not want to be iterating
- // over the chains twice. We can safely call process() while this
- // is happening since we should not be erasing a locked pipe, and
- // therefore won't be treading into deleted memory. I think we can
- // also clear the lock on the chain safely since the pump only
- // reads that value.
- mClearLocks.insert(key);
-}
-
-bool LLPumpIO::sleepChain(F64 seconds)
-{
- // Much like the call to setLock(), this should only be called
- // from one chain during processing, so there is no need to
- // acquire a mutex.
- if(seconds <= 0.0) return false;
- S32 key = setLock();
- if(!key) return false;
- LLRunner::run_handle_t handle = mRunner.addRunnable(
- LLChainSleeper::build(this, key),
- LLRunner::RUN_IN,
- seconds);
- if(0 == handle) return false;
- return true;
-}
-
-bool LLPumpIO::copyCurrentLinkInfo(links_t& links) const
-{
- if(mRunningChains.end() == mCurrentChain)
- {
- return false;
- }
- std::copy(
- (*mCurrentChain).mChainLinks.begin(),
- (*mCurrentChain).mChainLinks.end(),
- std::back_insert_iterator<links_t>(links));
- return true;
-}
-
-void LLPumpIO::pump()
-{
- pump(DEFAULT_POLL_TIMEOUT);
-}
-
-LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain)
-{
- std::for_each(
- (*run_chain).mDescriptors.begin(),
- (*run_chain).mDescriptors.end(),
- ll_delete_apr_pollset_fd_client_data());
- return mRunningChains.erase(run_chain);
-}
-
-//timeout is in microseconds
-void LLPumpIO::pump(const S32& poll_timeout)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
- //LL_INFOS() << "LLPumpIO::pump()" << LL_ENDL;
-
- // Run any pending runners.
- mRunner.run();
-
- // We need to move all of the pending heads over to the running
- // chains.
- PUMP_DEBUG;
- if(true)
- {
- // bail if this pump is paused.
- if(PAUSING == mState)
- {
- mState = PAUSED;
- }
- if(PAUSED == mState)
- {
- return;
- }
-
- PUMP_DEBUG;
- // Move the pending chains over to the running chaings
- if(!mPendingChains.empty())
- {
- PUMP_DEBUG;
- //LL_DEBUGS() << "Pushing " << mPendingChains.size() << "." << LL_ENDL;
- std::copy(
- mPendingChains.begin(),
- mPendingChains.end(),
- std::back_insert_iterator<running_chains_t>(mRunningChains));
- mPendingChains.clear();
- PUMP_DEBUG;
- }
-
- // Clear any locks. This needs to be done here so that we do
- // not clash during a call to clearLock().
- if(!mClearLocks.empty())
- {
- PUMP_DEBUG;
- running_chains_t::iterator it = mRunningChains.begin();
- running_chains_t::iterator end = mRunningChains.end();
- std::set<S32>::iterator not_cleared = mClearLocks.end();
- for(; it != end; ++it)
- {
- if((*it).mLock && mClearLocks.find((*it).mLock) != not_cleared)
- {
- (*it).mLock = 0;
- }
- }
- PUMP_DEBUG;
- mClearLocks.clear();
- }
- }
-
- PUMP_DEBUG;
- // rebuild the pollset if necessary
- if(mRebuildPollset)
- {
- PUMP_DEBUG;
- rebuildPollset();
- mRebuildPollset = false;
- }
-
- // Poll based on the last known pollset
- // *TODO: may want to pass in a poll timeout so it works correctly
- // in single and multi threaded processes.
- PUMP_DEBUG;
- typedef std::map<S32, S32> signal_client_t;
- signal_client_t signalled_client;
- const apr_pollfd_t* poll_fd = NULL;
- if(mPollset)
- {
- PUMP_DEBUG;
- //LL_INFOS() << "polling" << LL_ENDL;
- S32 count = 0;
- S32 client_id = 0;
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
- apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
- }
- PUMP_DEBUG;
- for(S32 ii = 0; ii < count; ++ii)
- {
- ll_debug_poll_fd("Signalled pipe", &poll_fd[ii]);
- client_id = *((S32*)poll_fd[ii].client_data);
- signalled_client[client_id] = ii;
- }
- PUMP_DEBUG;
- }
-
- PUMP_DEBUG;
- // set up for a check to see if each one was signalled
- signal_client_t::iterator not_signalled = signalled_client.end();
-
- // Process everything as appropriate
- //LL_DEBUGS() << "Running chain count: " << mRunningChains.size() << LL_ENDL;
- running_chains_t::iterator run_chain = mRunningChains.begin();
- bool process_this_chain = false;
- while( run_chain != mRunningChains.end() )
- {
- PUMP_DEBUG;
- if((*run_chain).mInit
- && (*run_chain).mTimer.getStarted()
- && (*run_chain).mTimer.hasExpired())
- {
- PUMP_DEBUG;
- if(handleChainError(*run_chain, LLIOPipe::STATUS_EXPIRED))
- {
- // the pipe probably handled the error. If the handler
- // forgot to reset the expiration then we need to do
- // that here.
- if((*run_chain).mTimer.getStarted()
- && (*run_chain).mTimer.hasExpired())
- {
- PUMP_DEBUG;
- LL_INFOS() << "Error handler forgot to reset timeout. "
- << "Resetting to " << DEFAULT_CHAIN_EXPIRY_SECS
- << " seconds." << LL_ENDL;
- (*run_chain).setTimeoutSeconds(DEFAULT_CHAIN_EXPIRY_SECS);
- }
- }
- else
- {
- PUMP_DEBUG;
- // it timed out and no one handled it, so we need to
- // retire the chain
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "Removing chain "
- << (*run_chain).mChainLinks[0].mPipe
- << " '"
- << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
- << "' because it timed out." << LL_ENDL;
-#else
-// LL_DEBUGS() << "Removing chain "
-// << (*run_chain).mChainLinks[0].mPipe
-// << " because we reached the end." << LL_ENDL;
-#endif
- run_chain = removeRunningChain(run_chain);
- continue;
- }
- }
- else if(isChainExpired(*run_chain))
- {
- run_chain = removeRunningChain(run_chain);
- continue;
- }
-
- PUMP_DEBUG;
- if((*run_chain).mLock)
- {
- ++run_chain;
- continue;
- }
- PUMP_DEBUG;
- mCurrentChain = run_chain;
-
- if((*run_chain).mDescriptors.empty())
- {
- // if there are no conditionals, just process this chain.
- process_this_chain = true;
- //LL_DEBUGS() << "no conditionals - processing" << LL_ENDL;
- }
- else
- {
- PUMP_DEBUG;
- //LL_DEBUGS() << "checking conditionals" << LL_ENDL;
- // Check if this run chain was signalled. If any file
- // descriptor is ready for something, then go ahead and
- // process this chian.
- process_this_chain = false;
- if(!signalled_client.empty())
- {
- PUMP_DEBUG;
- LLChainInfo::conditionals_t::iterator it;
- it = (*run_chain).mDescriptors.begin();
- LLChainInfo::conditionals_t::iterator end;
- end = (*run_chain).mDescriptors.end();
- S32 client_id = 0;
- signal_client_t::iterator signal;
- for(; it != end; ++it)
- {
- PUMP_DEBUG;
- client_id = *((S32*)((*it).second.client_data));
- signal = signalled_client.find(client_id);
- if (signal == not_signalled) continue;
- static const apr_int16_t POLL_CHAIN_ERROR =
- APR_POLLHUP | APR_POLLNVAL | APR_POLLERR;
- const apr_pollfd_t* poll = &(poll_fd[(*signal).second]);
- if(poll->rtnevents & POLL_CHAIN_ERROR)
- {
- // Potential eror condition has been
- // returned. If HUP was one of them, we pass
- // that as the error even though there may be
- // more. If there are in fact more errors,
- // we'll just wait for that detection until
- // the next pump() cycle to catch it so that
- // the logic here gets no more strained than
- // it already is.
- LLIOPipe::EStatus error_status;
- if(poll->rtnevents & APR_POLLHUP)
- error_status = LLIOPipe::STATUS_LOST_CONNECTION;
- else
- error_status = LLIOPipe::STATUS_ERROR;
- if(handleChainError(*run_chain, error_status)) break;
- ll_debug_poll_fd("Removing pipe", poll);
- LL_WARNS() << "Removing pipe "
- << (*run_chain).mChainLinks[0].mPipe
- << " '"
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- << typeid(
- *((*run_chain).mChainLinks[0].mPipe)).name()
-#endif
- << "' because: "
- << events_2_string(poll->rtnevents)
- << LL_ENDL;
- (*run_chain).mHead = (*run_chain).mChainLinks.end();
- break;
- }
-
- // at least 1 fd got signalled, and there were no
- // errors. That means we process this chain.
- process_this_chain = true;
- break;
- }
- }
- }
- if(process_this_chain)
- {
- PUMP_DEBUG;
- if(!((*run_chain).mInit))
- {
- (*run_chain).mHead = (*run_chain).mChainLinks.begin();
- (*run_chain).mInit = true;
- }
- PUMP_DEBUG;
- processChain(*run_chain);
- }
-
- PUMP_DEBUG;
- if((*run_chain).mHead == (*run_chain).mChainLinks.end())
- {
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
- << " '"
- << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
- << "' because we reached the end." << LL_ENDL;
-#else
-// LL_DEBUGS() << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
-// << " because we reached the end." << LL_ENDL;
-#endif
-
- PUMP_DEBUG;
- // This chain is done. Clean up any allocated memory and
- // erase the chain info.
- run_chain = removeRunningChain(run_chain);
-
- // *NOTE: may not always need to rebuild the pollset.
- mRebuildPollset = true;
- }
- else
- {
- PUMP_DEBUG;
- // this chain needs more processing - just go to the next
- // chain.
- ++run_chain;
- }
- }
-
- PUMP_DEBUG;
- // null out the chain
- mCurrentChain = mRunningChains.end();
- END_PUMP_DEBUG;
-}
-
-bool LLPumpIO::respond(LLIOPipe* pipe)
-{
- if(NULL == pipe) return false;
-
- LLChainInfo info;
- LLLinkInfo link;
- link.mPipe = pipe;
- info.mChainLinks.push_back(link);
- mPendingCallbacks.push_back(info);
- return true;
-}
-
-bool LLPumpIO::respond(
- const links_t& links,
- LLIOPipe::buffer_ptr_t data,
- LLSD context)
-{
- // if the caller is providing a full link description, we need to
- // have that description matched to a particular buffer.
- if(!data) return false;
- if(links.empty()) return false;
-
- // Add the callback response
- LLChainInfo info;
- info.mChainLinks = links;
- info.mData = data;
- info.mContext = context;
- mPendingCallbacks.push_back(info);
- return true;
-}
-
-void LLPumpIO::callback()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
- //LL_INFOS() << "LLPumpIO::callback()" << LL_ENDL;
- if(true)
- {
- std::copy(
- mPendingCallbacks.begin(),
- mPendingCallbacks.end(),
- std::back_insert_iterator<callbacks_t>(mCallbacks));
- mPendingCallbacks.clear();
- }
- if(!mCallbacks.empty())
- {
- callbacks_t::iterator it = mCallbacks.begin();
- callbacks_t::iterator end = mCallbacks.end();
- for(; it != end; ++it)
- {
- // it's always the first and last time for respone chains
- (*it).mHead = (*it).mChainLinks.begin();
- (*it).mInit = true;
- (*it).mEOS = true;
- processChain(*it);
- }
- mCallbacks.clear();
- }
-}
-
-void LLPumpIO::control(LLPumpIO::EControl op)
-{
- switch(op)
- {
- case PAUSE:
- mState = PAUSING;
- break;
- case RESUME:
- mState = NORMAL;
- break;
- default:
- // no-op
- break;
- }
-}
-
-void LLPumpIO::initialize(apr_pool_t* pool)
-{
- if(!pool) return;
- mPool = pool;
-}
-
-void LLPumpIO::cleanup()
-{
- if(mPollset)
- {
-// LL_DEBUGS() << "cleaning up pollset" << LL_ENDL;
- apr_pollset_destroy(mPollset);
- mPollset = NULL;
- }
- if(mCurrentPool)
- {
- apr_pool_destroy(mCurrentPool);
- mCurrentPool = NULL;
- }
- mPool = NULL;
-}
-
-void LLPumpIO::rebuildPollset()
-{
-// LL_DEBUGS() << "LLPumpIO::rebuildPollset()" << LL_ENDL;
- if(mPollset)
- {
- //LL_DEBUGS() << "destroying pollset" << LL_ENDL;
- apr_pollset_destroy(mPollset);
- mPollset = NULL;
- }
- U32 size = 0;
- running_chains_t::iterator run_it = mRunningChains.begin();
- running_chains_t::iterator run_end = mRunningChains.end();
- for(; run_it != run_end; ++run_it)
- {
- size += (*run_it).mDescriptors.size();
- }
- //LL_DEBUGS() << "found " << size << " descriptors." << LL_ENDL;
- if(size)
- {
- // Recycle the memory pool
- const S32 POLLSET_POOL_RECYCLE_COUNT = 100;
- if(mCurrentPool
- && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
- {
- apr_pool_destroy(mCurrentPool);
- mCurrentPool = NULL;
- mCurrentPoolReallocCount = 0;
- }
- if(!mCurrentPool)
- {
- apr_status_t status = apr_pool_create(&mCurrentPool, mPool);
- (void)ll_apr_warn_status(status);
- }
-
- // add all of the file descriptors
- run_it = mRunningChains.begin();
- LLChainInfo::conditionals_t::iterator fd_it;
- LLChainInfo::conditionals_t::iterator fd_end;
- apr_pollset_create(&mPollset, size, mCurrentPool, 0);
- for(; run_it != run_end; ++run_it)
- {
- fd_it = (*run_it).mDescriptors.begin();
- fd_end = (*run_it).mDescriptors.end();
- for(; fd_it != fd_end; ++fd_it)
- {
- apr_pollset_add(mPollset, &((*fd_it).second));
- }
- }
- }
-}
-
-void LLPumpIO::processChain(LLChainInfo& chain)
-{
- PUMP_DEBUG;
- LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
- links_t::iterator it = chain.mHead;
- links_t::iterator end = chain.mChainLinks.end();
- bool need_process_signaled = false;
- bool keep_going = true;
- do
- {
-#if LL_DEBUG_PROCESS_LINK
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_INFOS() << "Processing " << typeid(*((*it).mPipe)).name() << "."
- << LL_ENDL;
-#else
- LL_INFOS() << "Processing link " << (*it).mPipe << "." << LL_ENDL;
-#endif
-#endif
-#if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN
- if(chain.mData)
- {
- char* buf = NULL;
- S32 bytes = chain.mData->countAfter((*it).mChannels.in(), NULL);
- if(bytes)
- {
- buf = new char[bytes + 1];
- chain.mData->readAfter(
- (*it).mChannels.in(),
- NULL,
- (U8*)buf,
- bytes);
- buf[bytes] = '\0';
- LL_INFOS() << "CHANNEL IN(" << (*it).mChannels.in() << "): "
- << buf << LL_ENDL;
- delete[] buf;
- buf = NULL;
- }
- else
- {
- LL_INFOS() << "CHANNEL IN(" << (*it).mChannels.in()<< "): (null)"
- << LL_ENDL;
- }
- }
-#endif
- PUMP_DEBUG;
- status = (*it).mPipe->process(
- (*it).mChannels,
- chain.mData,
- chain.mEOS,
- chain.mContext,
- this);
-#if LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT
- if(chain.mData)
- {
- char* buf = NULL;
- S32 bytes = chain.mData->countAfter((*it).mChannels.out(), NULL);
- if(bytes)
- {
- buf = new char[bytes + 1];
- chain.mData->readAfter(
- (*it).mChannels.out(),
- NULL,
- (U8*)buf,
- bytes);
- buf[bytes] = '\0';
- LL_INFOS() << "CHANNEL OUT(" << (*it).mChannels.out()<< "): "
- << buf << LL_ENDL;
- delete[] buf;
- buf = NULL;
- }
- else
- {
- LL_INFOS() << "CHANNEL OUT(" << (*it).mChannels.out()<< "): (null)"
- << LL_ENDL;
- }
- }
-#endif
-
-#if LL_DEBUG_PROCESS_RETURN_VALUE
- // Only bother with the success codes - error codes are logged
- // below.
- if(LLIOPipe::isSuccess(status))
- {
- LL_INFOS() << "Pipe returned: '"
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- << typeid(*((*it).mPipe)).name() << "':'"
-#endif
- << LLIOPipe::lookupStatusString(status) << "'" << LL_ENDL;
- }
-#endif
-
- PUMP_DEBUG;
- switch(status)
- {
- case LLIOPipe::STATUS_OK:
- // no-op
- break;
- case LLIOPipe::STATUS_STOP:
- PUMP_DEBUG;
- status = LLIOPipe::STATUS_OK;
- chain.mHead = end;
- keep_going = false;
- break;
- case LLIOPipe::STATUS_DONE:
- PUMP_DEBUG;
- status = LLIOPipe::STATUS_OK;
- chain.mHead = (it + 1);
- chain.mEOS = true;
- break;
- case LLIOPipe::STATUS_BREAK:
- PUMP_DEBUG;
- status = LLIOPipe::STATUS_OK;
- keep_going = false;
- break;
- case LLIOPipe::STATUS_NEED_PROCESS:
- PUMP_DEBUG;
- status = LLIOPipe::STATUS_OK;
- if(!need_process_signaled)
- {
- need_process_signaled = true;
- chain.mHead = it;
- }
- break;
- default:
- PUMP_DEBUG;
- if(LLIOPipe::isError(status))
- {
- LL_INFOS() << "Pump generated pipe err: '"
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- << typeid(*((*it).mPipe)).name() << "':'"
-#endif
- << LLIOPipe::lookupStatusString(status)
- << "'" << LL_ENDL;
-#if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR
- if(chain.mData)
- {
- char* buf = NULL;
- S32 bytes = chain.mData->countAfter(
- (*it).mChannels.in(),
- NULL);
- if(bytes)
- {
- buf = new char[bytes + 1];
- chain.mData->readAfter(
- (*it).mChannels.in(),
- NULL,
- (U8*)buf,
- bytes);
- buf[bytes] = '\0';
- LL_INFOS() << "Input After Error: " << buf << LL_ENDL;
- delete[] buf;
- buf = NULL;
- }
- else
- {
- LL_INFOS() << "Input After Error: (null)" << LL_ENDL;
- }
- }
- else
- {
- LL_INFOS() << "Input After Error: (null)" << LL_ENDL;
- }
-#endif
- keep_going = false;
- chain.mHead = it;
- if(!handleChainError(chain, status))
- {
- chain.mHead = end;
- }
- }
- else
- {
- LL_INFOS() << "Unhandled status code: " << status << ":"
- << LLIOPipe::lookupStatusString(status) << LL_ENDL;
- }
- break;
- }
- PUMP_DEBUG;
- } while(keep_going && (++it != end));
- PUMP_DEBUG;
-}
-
-bool LLPumpIO::isChainExpired(LLChainInfo& chain)
-{
- if(!chain.mHasCurlRequest)
- {
- return false ;
- }
-
- for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter)
- {
- if(!(*iter).mPipe->isValid())
- {
- return true ;
- }
- }
-
- return false ;
-}
-
-bool LLPumpIO::handleChainError(
- LLChainInfo& chain,
- LLIOPipe::EStatus error)
-{
- links_t::reverse_iterator rit;
- if(chain.mHead == chain.mChainLinks.end())
- {
- rit = links_t::reverse_iterator(chain.mHead);
- }
- else
- {
- rit = links_t::reverse_iterator(chain.mHead + 1);
- }
-
- links_t::reverse_iterator rend = chain.mChainLinks.rend();
- bool handled = false;
- bool keep_going = true;
- do
- {
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "Passing error to " << typeid(*((*rit).mPipe)).name()
- << "." << LL_ENDL;
-#endif
- error = (*rit).mPipe->handleError(error, this);
- switch(error)
- {
- case LLIOPipe::STATUS_OK:
- handled = true;
- chain.mHead = rit.base();
- break;
- case LLIOPipe::STATUS_STOP:
- case LLIOPipe::STATUS_DONE:
- case LLIOPipe::STATUS_BREAK:
- case LLIOPipe::STATUS_NEED_PROCESS:
-#if LL_DEBUG_PIPE_TYPE_IN_PUMP
- LL_DEBUGS() << "Pipe " << typeid(*((*rit).mPipe)).name()
- << " returned code to stop error handler." << LL_ENDL;
-#endif
- keep_going = false;
- break;
- case LLIOPipe::STATUS_EXPIRED:
- keep_going = false;
- break ;
- default:
- if(LLIOPipe::isSuccess(error))
- {
- LL_INFOS() << "Unhandled status code: " << error << ":"
- << LLIOPipe::lookupStatusString(error) << LL_ENDL;
- error = LLIOPipe::STATUS_ERROR;
- keep_going = false;
- }
- break;
- }
- } while(keep_going && !handled && (++rit != rend));
- return handled;
-}
-
-/**
- * LLPumpIO::LLChainInfo
- */
-
-LLPumpIO::LLChainInfo::LLChainInfo() :
- mInit(false),
- mLock(0),
- mEOS(false),
- mHasCurlRequest(false)
-{
- mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
-}
-
-void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout)
-{
- if(timeout > 0.0f)
- {
- mTimer.start();
- mTimer.reset();
- mTimer.setTimerExpirySec(timeout);
- }
- else
- {
- mTimer.stop();
- }
-}
-
-void LLPumpIO::LLChainInfo::adjustTimeoutSeconds(F32 delta)
-{
- if(mTimer.getStarted())
- {
- F64 expiry = mTimer.expiresAt();
- expiry += delta;
- mTimer.setExpiryAt(expiry);
- }
-}
+/**
+ * @file llpumpio.cpp
+ * @author Phoenix
+ * @date 2004-11-21
+ * @brief Implementation of the i/o pump and related functions.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llpumpio.h"
+
+#include <map>
+#include <set>
+#include "apr_poll.h"
+
+#include "llapr.h"
+#include "llfasttimer.h"
+#include "llstl.h"
+
+// These should not be enabled in production, but they can be
+// intensely useful during development for finding certain kinds of
+// bugs.
+#if LL_LINUX
+//#define LL_DEBUG_PIPE_TYPE_IN_PUMP 1
+//#define LL_DEBUG_POLL_FILE_DESCRIPTORS 1
+#if LL_DEBUG_POLL_FILE_DESCRIPTORS
+#include "apr_portable.h"
+#endif
+#endif
+
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+#include <typeinfo>
+#endif
+
+// constants for poll timeout. if we are threading, we want to have a
+// longer poll timeout.
+static const S32 DEFAULT_POLL_TIMEOUT = 0;
+
+// The default (and fallback) expiration time for chains
+const F32 DEFAULT_CHAIN_EXPIRY_SECS = 30.0f;
+extern const F32 SHORT_CHAIN_EXPIRY_SECS = 1.0f;
+extern const F32 NEVER_CHAIN_EXPIRY_SECS = 0.0f;
+
+// sorta spammy debug modes.
+//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR 1
+//#define LL_DEBUG_PROCESS_LINK 1
+//#define LL_DEBUG_PROCESS_RETURN_VALUE 1
+
+// Super spammy debug mode.
+//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_IN 1
+//#define LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT 1
+
+//
+// local functions
+//
+void ll_debug_poll_fd(const char* msg, const apr_pollfd_t* poll)
+{
+#if LL_DEBUG_POLL_FILE_DESCRIPTORS
+ if(!poll)
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << ": no pollfd." << LL_ENDL;
+ return;
+ }
+ if(poll->desc.s)
+ {
+ apr_os_sock_t os_sock;
+ if(APR_SUCCESS == apr_os_sock_get(&os_sock, poll->desc.s))
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " on fd " << os_sock
+ << " at " << poll->desc.s << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " no fd "
+ << " at " << poll->desc.s << LL_ENDL;
+ }
+ }
+ else if(poll->desc.f)
+ {
+ apr_os_file_t os_file;
+ if(APR_SUCCESS == apr_os_file_get(&os_file, poll->desc.f))
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " on fd " << os_file
+ << " at " << poll->desc.f << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << " no fd "
+ << " at " << poll->desc.f << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_DEBUGS() << "Poll -- " << (msg?msg:"") << ": no descriptor." << LL_ENDL;
+ }
+#endif
+}
+
+/**
+ * @class
+ */
+class LLChainSleeper : public LLRunnable
+{
+public:
+ static LLRunner::run_ptr_t build(LLPumpIO* pump, S32 key)
+ {
+ return LLRunner::run_ptr_t(new LLChainSleeper(pump, key));
+ }
+
+ virtual void run(LLRunner* runner, S64 handle)
+ {
+ mPump->clearLock(mKey);
+ }
+
+protected:
+ LLChainSleeper(LLPumpIO* pump, S32 key) : mPump(pump), mKey(key) {}
+ LLPumpIO* mPump;
+ S32 mKey;
+};
+
+
+/**
+ * @struct ll_delete_apr_pollset_fd_client_data
+ * @brief This is a simple helper class to clean up our client data.
+ */
+struct ll_delete_apr_pollset_fd_client_data
+{
+ typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
+ void operator()(const pipe_conditional_t& conditional)
+ {
+ S32* client_id = (S32*)conditional.second.client_data;
+ delete client_id;
+ }
+};
+
+/**
+ * LLPumpIO
+ */
+LLPumpIO::LLPumpIO(apr_pool_t* pool) :
+ mState(LLPumpIO::NORMAL),
+ mRebuildPollset(false),
+ mPollset(NULL),
+ mPollsetClientID(0),
+ mNextLock(0),
+ mPool(NULL),
+ mCurrentPool(NULL),
+ mCurrentPoolReallocCount(0),
+ mCurrentChain(mRunningChains.end())
+{
+ mCurrentChain = mRunningChains.end();
+
+ initialize(pool);
+}
+
+LLPumpIO::~LLPumpIO()
+{
+ cleanup();
+}
+
+bool LLPumpIO::prime(apr_pool_t* pool)
+{
+ cleanup();
+ initialize(pool);
+ return pool != nullptr;
+}
+
+bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)
+{
+ if (chain.empty())
+ return false;
+
+ LLChainInfo info;
+ info.mHasCurlRequest = has_curl_request;
+ info.setTimeoutSeconds(timeout);
+ info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray);
+ info.mData->setThreaded(has_curl_request);
+ LLLinkInfo link;
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "LLPumpIO::addChain() " << chain[0] << " '"
+ << typeid(*(chain[0])).name() << "'" << LL_ENDL;
+#else
+ LL_DEBUGS() << "LLPumpIO::addChain() " << chain[0] <<LL_ENDL;
+#endif
+ chain_t::const_iterator it = chain.begin();
+ chain_t::const_iterator end = chain.end();
+ for(; it != end; ++it)
+ {
+ link.mPipe = (*it);
+ link.mChannels = info.mData->nextChannel();
+ info.mChainLinks.push_back(link);
+ }
+ mPendingChains.push_back(info);
+ return true;
+}
+
+bool LLPumpIO::addChain(
+ const LLPumpIO::links_t& links,
+ LLIOPipe::buffer_ptr_t data,
+ LLSD context,
+ F32 timeout)
+{
+ // remember that if the caller is providing a full link
+ // description, we need to have that description matched to a
+ // particular buffer.
+ if (!data)
+ return false;
+ if (links.empty())
+ return false;
+
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "LLPumpIO::addChain() " << links[0].mPipe << " '"
+ << typeid(*(links[0].mPipe)).name() << "'" << LL_ENDL;
+#else
+ LL_DEBUGS() << "LLPumpIO::addChain() " << links[0].mPipe << LL_ENDL;
+#endif
+ LLChainInfo info;
+ info.setTimeoutSeconds(timeout);
+ info.mChainLinks = links;
+ info.mData = data;
+ info.mContext = context;
+ mPendingChains.push_back(info);
+ return true;
+}
+
+bool LLPumpIO::setTimeoutSeconds(F32 timeout)
+{
+ // If no chain is running, return failure.
+ if (mRunningChains.end() == mCurrentChain)
+ {
+ return false;
+ }
+
+ (*mCurrentChain).setTimeoutSeconds(timeout);
+ return true;
+}
+
+void LLPumpIO::adjustTimeoutSeconds(F32 delta)
+{
+ // Ensure a chain is running
+ if (mRunningChains.end() != mCurrentChain)
+ {
+ (*mCurrentChain).adjustTimeoutSeconds(delta);
+ }
+}
+
+static std::string events_2_string(apr_int16_t events)
+{
+ std::ostringstream ostr;
+ if (events & APR_POLLIN)
+ {
+ ostr << "read,";
+ }
+ if (events & APR_POLLPRI)
+ {
+ ostr << "priority,";
+ }
+ if (events & APR_POLLOUT)
+ {
+ ostr << "write,";
+ }
+ if (events & APR_POLLERR)
+ {
+ ostr << "error,";
+ }
+ if (events & APR_POLLHUP)
+ {
+ ostr << "hangup,";
+ }
+ if (events & APR_POLLNVAL)
+ {
+ ostr << "invalid,";
+ }
+ return chop_tail_copy(ostr.str(), 1);
+}
+
+bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
+{
+ if (!pipe)
+ return false;
+ ll_debug_poll_fd("Set conditional", poll);
+
+ LL_DEBUGS() << "Setting conditionals (" << (poll ? events_2_string(poll->reqevents) :"null")
+ << ") "
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ << "on pipe " << typeid(*pipe).name()
+#endif
+ << " at " << pipe << LL_ENDL;
+
+ // remove any matching poll file descriptors for this pipe.
+ LLIOPipe::ptr_t pipe_ptr(pipe);
+ LLChainInfo::conditionals_t::iterator it;
+ it = (*mCurrentChain).mDescriptors.begin();
+ while(it != (*mCurrentChain).mDescriptors.end())
+ {
+ LLChainInfo::pipe_conditional_t& value = (*it);
+ if(pipe_ptr == value.first)
+ {
+ ll_delete_apr_pollset_fd_client_data()(value);
+ it = (*mCurrentChain).mDescriptors.erase(it);
+ mRebuildPollset = true;
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ if(!poll)
+ {
+ mRebuildPollset = true;
+ return true;
+ }
+ LLChainInfo::pipe_conditional_t value;
+ value.first = pipe_ptr;
+ value.second = *poll;
+ value.second.rtnevents = 0;
+ if(!poll->p)
+ {
+ // each fd needs a pool to work with, so if one was
+ // not specified, use this pool.
+ // *FIX: Should it always be this pool?
+ value.second.p = mPool;
+ }
+ value.second.client_data = new S32(++mPollsetClientID);
+ (*mCurrentChain).mDescriptors.push_back(value);
+ mRebuildPollset = true;
+ return true;
+}
+
+S32 LLPumpIO::setLock()
+{
+ // *NOTE: I do not think it is necessary to acquire a mutex here
+ // since this should only be called during the pump(), and should
+ // only change the running chain. Any other use of this method is
+ // incorrect usage. If it becomes necessary to acquire a lock
+ // here, be sure to lock here and call a protected method to get
+ // the lock, and sleepChain() should probably acquire the same
+ // lock while and calling the same protected implementation to
+ // lock the runner at the same time.
+
+ // If no chain is running, return failure.
+ if(mRunningChains.end() == mCurrentChain)
+ {
+ return 0;
+ }
+
+ // deal with wrap.
+ if(++mNextLock <= 0)
+ {
+ mNextLock = 1;
+ }
+
+ // set the lock
+ (*mCurrentChain).mLock = mNextLock;
+ return mNextLock;
+}
+
+void LLPumpIO::clearLock(S32 key)
+{
+ // We need to lock it here since we do not want to be iterating
+ // over the chains twice. We can safely call process() while this
+ // is happening since we should not be erasing a locked pipe, and
+ // therefore won't be treading into deleted memory. I think we can
+ // also clear the lock on the chain safely since the pump only
+ // reads that value.
+ mClearLocks.insert(key);
+}
+
+bool LLPumpIO::sleepChain(F64 seconds)
+{
+ // Much like the call to setLock(), this should only be called
+ // from one chain during processing, so there is no need to
+ // acquire a mutex.
+ if(seconds <= 0.0) return false;
+ S32 key = setLock();
+ if(!key) return false;
+ LLRunner::run_handle_t handle = mRunner.addRunnable(
+ LLChainSleeper::build(this, key),
+ LLRunner::RUN_IN,
+ seconds);
+ if(0 == handle) return false;
+ return true;
+}
+
+bool LLPumpIO::copyCurrentLinkInfo(links_t& links) const
+{
+ if(mRunningChains.end() == mCurrentChain)
+ {
+ return false;
+ }
+ std::copy(
+ (*mCurrentChain).mChainLinks.begin(),
+ (*mCurrentChain).mChainLinks.end(),
+ std::back_insert_iterator<links_t>(links));
+ return true;
+}
+
+void LLPumpIO::pump()
+{
+ pump(DEFAULT_POLL_TIMEOUT);
+}
+
+LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain)
+{
+ std::for_each(
+ (*run_chain).mDescriptors.begin(),
+ (*run_chain).mDescriptors.end(),
+ ll_delete_apr_pollset_fd_client_data());
+ return mRunningChains.erase(run_chain);
+}
+
+//timeout is in microseconds
+void LLPumpIO::pump(const S32& poll_timeout)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ //LL_INFOS() << "LLPumpIO::pump()" << LL_ENDL;
+
+ // Run any pending runners.
+ mRunner.run();
+
+ // We need to move all of the pending heads over to the running
+ // chains.
+ PUMP_DEBUG;
+ if(true)
+ {
+ // bail if this pump is paused.
+ if(PAUSING == mState)
+ {
+ mState = PAUSED;
+ }
+ if(PAUSED == mState)
+ {
+ return;
+ }
+
+ PUMP_DEBUG;
+ // Move the pending chains over to the running chaings
+ if(!mPendingChains.empty())
+ {
+ PUMP_DEBUG;
+ //LL_DEBUGS() << "Pushing " << mPendingChains.size() << "." << LL_ENDL;
+ std::copy(
+ mPendingChains.begin(),
+ mPendingChains.end(),
+ std::back_insert_iterator<running_chains_t>(mRunningChains));
+ mPendingChains.clear();
+ PUMP_DEBUG;
+ }
+
+ // Clear any locks. This needs to be done here so that we do
+ // not clash during a call to clearLock().
+ if(!mClearLocks.empty())
+ {
+ PUMP_DEBUG;
+ running_chains_t::iterator it = mRunningChains.begin();
+ running_chains_t::iterator end = mRunningChains.end();
+ std::set<S32>::iterator not_cleared = mClearLocks.end();
+ for(; it != end; ++it)
+ {
+ if((*it).mLock && mClearLocks.find((*it).mLock) != not_cleared)
+ {
+ (*it).mLock = 0;
+ }
+ }
+ PUMP_DEBUG;
+ mClearLocks.clear();
+ }
+ }
+
+ PUMP_DEBUG;
+ // rebuild the pollset if necessary
+ if(mRebuildPollset)
+ {
+ PUMP_DEBUG;
+ rebuildPollset();
+ mRebuildPollset = false;
+ }
+
+ // Poll based on the last known pollset
+ // *TODO: may want to pass in a poll timeout so it works correctly
+ // in single and multi threaded processes.
+ PUMP_DEBUG;
+ typedef std::map<S32, S32> signal_client_t;
+ signal_client_t signalled_client;
+ const apr_pollfd_t* poll_fd = NULL;
+ if(mPollset)
+ {
+ PUMP_DEBUG;
+ //LL_INFOS() << "polling" << LL_ENDL;
+ S32 count = 0;
+ S32 client_id = 0;
+ {
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
+ }
+ PUMP_DEBUG;
+ for(S32 ii = 0; ii < count; ++ii)
+ {
+ ll_debug_poll_fd("Signalled pipe", &poll_fd[ii]);
+ client_id = *((S32*)poll_fd[ii].client_data);
+ signalled_client[client_id] = ii;
+ }
+ PUMP_DEBUG;
+ }
+
+ PUMP_DEBUG;
+ // set up for a check to see if each one was signalled
+ signal_client_t::iterator not_signalled = signalled_client.end();
+
+ // Process everything as appropriate
+ //LL_DEBUGS() << "Running chain count: " << mRunningChains.size() << LL_ENDL;
+ running_chains_t::iterator run_chain = mRunningChains.begin();
+ bool process_this_chain = false;
+ while( run_chain != mRunningChains.end() )
+ {
+ PUMP_DEBUG;
+ if((*run_chain).mInit
+ && (*run_chain).mTimer.getStarted()
+ && (*run_chain).mTimer.hasExpired())
+ {
+ PUMP_DEBUG;
+ if(handleChainError(*run_chain, LLIOPipe::STATUS_EXPIRED))
+ {
+ // the pipe probably handled the error. If the handler
+ // forgot to reset the expiration then we need to do
+ // that here.
+ if((*run_chain).mTimer.getStarted()
+ && (*run_chain).mTimer.hasExpired())
+ {
+ PUMP_DEBUG;
+ LL_INFOS() << "Error handler forgot to reset timeout. "
+ << "Resetting to " << DEFAULT_CHAIN_EXPIRY_SECS
+ << " seconds." << LL_ENDL;
+ (*run_chain).setTimeoutSeconds(DEFAULT_CHAIN_EXPIRY_SECS);
+ }
+ }
+ else
+ {
+ PUMP_DEBUG;
+ // it timed out and no one handled it, so we need to
+ // retire the chain
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "Removing chain "
+ << (*run_chain).mChainLinks[0].mPipe
+ << " '"
+ << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
+ << "' because it timed out." << LL_ENDL;
+#else
+// LL_DEBUGS() << "Removing chain "
+// << (*run_chain).mChainLinks[0].mPipe
+// << " because we reached the end." << LL_ENDL;
+#endif
+ run_chain = removeRunningChain(run_chain);
+ continue;
+ }
+ }
+ else if(isChainExpired(*run_chain))
+ {
+ run_chain = removeRunningChain(run_chain);
+ continue;
+ }
+
+ PUMP_DEBUG;
+ if((*run_chain).mLock)
+ {
+ ++run_chain;
+ continue;
+ }
+ PUMP_DEBUG;
+ mCurrentChain = run_chain;
+
+ if((*run_chain).mDescriptors.empty())
+ {
+ // if there are no conditionals, just process this chain.
+ process_this_chain = true;
+ //LL_DEBUGS() << "no conditionals - processing" << LL_ENDL;
+ }
+ else
+ {
+ PUMP_DEBUG;
+ //LL_DEBUGS() << "checking conditionals" << LL_ENDL;
+ // Check if this run chain was signalled. If any file
+ // descriptor is ready for something, then go ahead and
+ // process this chian.
+ process_this_chain = false;
+ if(!signalled_client.empty())
+ {
+ PUMP_DEBUG;
+ LLChainInfo::conditionals_t::iterator it;
+ it = (*run_chain).mDescriptors.begin();
+ LLChainInfo::conditionals_t::iterator end;
+ end = (*run_chain).mDescriptors.end();
+ S32 client_id = 0;
+ signal_client_t::iterator signal;
+ for(; it != end; ++it)
+ {
+ PUMP_DEBUG;
+ client_id = *((S32*)((*it).second.client_data));
+ signal = signalled_client.find(client_id);
+ if (signal == not_signalled) continue;
+ static const apr_int16_t POLL_CHAIN_ERROR =
+ APR_POLLHUP | APR_POLLNVAL | APR_POLLERR;
+ const apr_pollfd_t* poll = &(poll_fd[(*signal).second]);
+ if(poll->rtnevents & POLL_CHAIN_ERROR)
+ {
+ // Potential eror condition has been
+ // returned. If HUP was one of them, we pass
+ // that as the error even though there may be
+ // more. If there are in fact more errors,
+ // we'll just wait for that detection until
+ // the next pump() cycle to catch it so that
+ // the logic here gets no more strained than
+ // it already is.
+ LLIOPipe::EStatus error_status;
+ if(poll->rtnevents & APR_POLLHUP)
+ error_status = LLIOPipe::STATUS_LOST_CONNECTION;
+ else
+ error_status = LLIOPipe::STATUS_ERROR;
+ if(handleChainError(*run_chain, error_status)) break;
+ ll_debug_poll_fd("Removing pipe", poll);
+ LL_WARNS() << "Removing pipe "
+ << (*run_chain).mChainLinks[0].mPipe
+ << " '"
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ << typeid(
+ *((*run_chain).mChainLinks[0].mPipe)).name()
+#endif
+ << "' because: "
+ << events_2_string(poll->rtnevents)
+ << LL_ENDL;
+ (*run_chain).mHead = (*run_chain).mChainLinks.end();
+ break;
+ }
+
+ // at least 1 fd got signalled, and there were no
+ // errors. That means we process this chain.
+ process_this_chain = true;
+ break;
+ }
+ }
+ }
+ if(process_this_chain)
+ {
+ PUMP_DEBUG;
+ if(!((*run_chain).mInit))
+ {
+ (*run_chain).mHead = (*run_chain).mChainLinks.begin();
+ (*run_chain).mInit = true;
+ }
+ PUMP_DEBUG;
+ processChain(*run_chain);
+ }
+
+ PUMP_DEBUG;
+ if((*run_chain).mHead == (*run_chain).mChainLinks.end())
+ {
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
+ << " '"
+ << typeid(*((*run_chain).mChainLinks[0].mPipe)).name()
+ << "' because we reached the end." << LL_ENDL;
+#else
+// LL_DEBUGS() << "Removing chain " << (*run_chain).mChainLinks[0].mPipe
+// << " because we reached the end." << LL_ENDL;
+#endif
+
+ PUMP_DEBUG;
+ // This chain is done. Clean up any allocated memory and
+ // erase the chain info.
+ run_chain = removeRunningChain(run_chain);
+
+ // *NOTE: may not always need to rebuild the pollset.
+ mRebuildPollset = true;
+ }
+ else
+ {
+ PUMP_DEBUG;
+ // this chain needs more processing - just go to the next
+ // chain.
+ ++run_chain;
+ }
+ }
+
+ PUMP_DEBUG;
+ // null out the chain
+ mCurrentChain = mRunningChains.end();
+ END_PUMP_DEBUG;
+}
+
+bool LLPumpIO::respond(LLIOPipe* pipe)
+{
+ if(NULL == pipe) return false;
+
+ LLChainInfo info;
+ LLLinkInfo link;
+ link.mPipe = pipe;
+ info.mChainLinks.push_back(link);
+ mPendingCallbacks.push_back(info);
+ return true;
+}
+
+bool LLPumpIO::respond(
+ const links_t& links,
+ LLIOPipe::buffer_ptr_t data,
+ LLSD context)
+{
+ // if the caller is providing a full link description, we need to
+ // have that description matched to a particular buffer.
+ if(!data) return false;
+ if(links.empty()) return false;
+
+ // Add the callback response
+ LLChainInfo info;
+ info.mChainLinks = links;
+ info.mData = data;
+ info.mContext = context;
+ mPendingCallbacks.push_back(info);
+ return true;
+}
+
+void LLPumpIO::callback()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK;
+ //LL_INFOS() << "LLPumpIO::callback()" << LL_ENDL;
+ if(true)
+ {
+ std::copy(
+ mPendingCallbacks.begin(),
+ mPendingCallbacks.end(),
+ std::back_insert_iterator<callbacks_t>(mCallbacks));
+ mPendingCallbacks.clear();
+ }
+ if(!mCallbacks.empty())
+ {
+ callbacks_t::iterator it = mCallbacks.begin();
+ callbacks_t::iterator end = mCallbacks.end();
+ for(; it != end; ++it)
+ {
+ // it's always the first and last time for respone chains
+ (*it).mHead = (*it).mChainLinks.begin();
+ (*it).mInit = true;
+ (*it).mEOS = true;
+ processChain(*it);
+ }
+ mCallbacks.clear();
+ }
+}
+
+void LLPumpIO::control(LLPumpIO::EControl op)
+{
+ switch(op)
+ {
+ case PAUSE:
+ mState = PAUSING;
+ break;
+ case RESUME:
+ mState = NORMAL;
+ break;
+ default:
+ // no-op
+ break;
+ }
+}
+
+void LLPumpIO::initialize(apr_pool_t* pool)
+{
+ if(!pool) return;
+ mPool = pool;
+}
+
+void LLPumpIO::cleanup()
+{
+ if(mPollset)
+ {
+// LL_DEBUGS() << "cleaning up pollset" << LL_ENDL;
+ apr_pollset_destroy(mPollset);
+ mPollset = NULL;
+ }
+ if(mCurrentPool)
+ {
+ apr_pool_destroy(mCurrentPool);
+ mCurrentPool = NULL;
+ }
+ mPool = NULL;
+}
+
+void LLPumpIO::rebuildPollset()
+{
+// LL_DEBUGS() << "LLPumpIO::rebuildPollset()" << LL_ENDL;
+ if(mPollset)
+ {
+ //LL_DEBUGS() << "destroying pollset" << LL_ENDL;
+ apr_pollset_destroy(mPollset);
+ mPollset = NULL;
+ }
+ U32 size = 0;
+ running_chains_t::iterator run_it = mRunningChains.begin();
+ running_chains_t::iterator run_end = mRunningChains.end();
+ for(; run_it != run_end; ++run_it)
+ {
+ size += (*run_it).mDescriptors.size();
+ }
+ //LL_DEBUGS() << "found " << size << " descriptors." << LL_ENDL;
+ if(size)
+ {
+ // Recycle the memory pool
+ const S32 POLLSET_POOL_RECYCLE_COUNT = 100;
+ if(mCurrentPool
+ && (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
+ {
+ apr_pool_destroy(mCurrentPool);
+ mCurrentPool = NULL;
+ mCurrentPoolReallocCount = 0;
+ }
+ if(!mCurrentPool)
+ {
+ apr_status_t status = apr_pool_create(&mCurrentPool, mPool);
+ (void)ll_apr_warn_status(status);
+ }
+
+ // add all of the file descriptors
+ run_it = mRunningChains.begin();
+ LLChainInfo::conditionals_t::iterator fd_it;
+ LLChainInfo::conditionals_t::iterator fd_end;
+ apr_pollset_create(&mPollset, size, mCurrentPool, 0);
+ for(; run_it != run_end; ++run_it)
+ {
+ fd_it = (*run_it).mDescriptors.begin();
+ fd_end = (*run_it).mDescriptors.end();
+ for(; fd_it != fd_end; ++fd_it)
+ {
+ apr_pollset_add(mPollset, &((*fd_it).second));
+ }
+ }
+ }
+}
+
+void LLPumpIO::processChain(LLChainInfo& chain)
+{
+ PUMP_DEBUG;
+ LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
+ links_t::iterator it = chain.mHead;
+ links_t::iterator end = chain.mChainLinks.end();
+ bool need_process_signaled = false;
+ bool keep_going = true;
+ do
+ {
+#if LL_DEBUG_PROCESS_LINK
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_INFOS() << "Processing " << typeid(*((*it).mPipe)).name() << "."
+ << LL_ENDL;
+#else
+ LL_INFOS() << "Processing link " << (*it).mPipe << "." << LL_ENDL;
+#endif
+#endif
+#if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN
+ if(chain.mData)
+ {
+ char* buf = NULL;
+ S32 bytes = chain.mData->countAfter((*it).mChannels.in(), NULL);
+ if(bytes)
+ {
+ buf = new char[bytes + 1];
+ chain.mData->readAfter(
+ (*it).mChannels.in(),
+ NULL,
+ (U8*)buf,
+ bytes);
+ buf[bytes] = '\0';
+ LL_INFOS() << "CHANNEL IN(" << (*it).mChannels.in() << "): "
+ << buf << LL_ENDL;
+ delete[] buf;
+ buf = NULL;
+ }
+ else
+ {
+ LL_INFOS() << "CHANNEL IN(" << (*it).mChannels.in()<< "): (null)"
+ << LL_ENDL;
+ }
+ }
+#endif
+ PUMP_DEBUG;
+ status = (*it).mPipe->process(
+ (*it).mChannels,
+ chain.mData,
+ chain.mEOS,
+ chain.mContext,
+ this);
+#if LL_DEBUG_SPEW_BUFFER_CHANNEL_OUT
+ if(chain.mData)
+ {
+ char* buf = NULL;
+ S32 bytes = chain.mData->countAfter((*it).mChannels.out(), NULL);
+ if(bytes)
+ {
+ buf = new char[bytes + 1];
+ chain.mData->readAfter(
+ (*it).mChannels.out(),
+ NULL,
+ (U8*)buf,
+ bytes);
+ buf[bytes] = '\0';
+ LL_INFOS() << "CHANNEL OUT(" << (*it).mChannels.out()<< "): "
+ << buf << LL_ENDL;
+ delete[] buf;
+ buf = NULL;
+ }
+ else
+ {
+ LL_INFOS() << "CHANNEL OUT(" << (*it).mChannels.out()<< "): (null)"
+ << LL_ENDL;
+ }
+ }
+#endif
+
+#if LL_DEBUG_PROCESS_RETURN_VALUE
+ // Only bother with the success codes - error codes are logged
+ // below.
+ if(LLIOPipe::isSuccess(status))
+ {
+ LL_INFOS() << "Pipe returned: '"
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ << typeid(*((*it).mPipe)).name() << "':'"
+#endif
+ << LLIOPipe::lookupStatusString(status) << "'" << LL_ENDL;
+ }
+#endif
+
+ PUMP_DEBUG;
+ switch(status)
+ {
+ case LLIOPipe::STATUS_OK:
+ // no-op
+ break;
+ case LLIOPipe::STATUS_STOP:
+ PUMP_DEBUG;
+ status = LLIOPipe::STATUS_OK;
+ chain.mHead = end;
+ keep_going = false;
+ break;
+ case LLIOPipe::STATUS_DONE:
+ PUMP_DEBUG;
+ status = LLIOPipe::STATUS_OK;
+ chain.mHead = (it + 1);
+ chain.mEOS = true;
+ break;
+ case LLIOPipe::STATUS_BREAK:
+ PUMP_DEBUG;
+ status = LLIOPipe::STATUS_OK;
+ keep_going = false;
+ break;
+ case LLIOPipe::STATUS_NEED_PROCESS:
+ PUMP_DEBUG;
+ status = LLIOPipe::STATUS_OK;
+ if(!need_process_signaled)
+ {
+ need_process_signaled = true;
+ chain.mHead = it;
+ }
+ break;
+ default:
+ PUMP_DEBUG;
+ if(LLIOPipe::isError(status))
+ {
+ LL_INFOS() << "Pump generated pipe err: '"
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ << typeid(*((*it).mPipe)).name() << "':'"
+#endif
+ << LLIOPipe::lookupStatusString(status)
+ << "'" << LL_ENDL;
+#if LL_DEBUG_SPEW_BUFFER_CHANNEL_IN_ON_ERROR
+ if(chain.mData)
+ {
+ char* buf = NULL;
+ S32 bytes = chain.mData->countAfter(
+ (*it).mChannels.in(),
+ NULL);
+ if(bytes)
+ {
+ buf = new char[bytes + 1];
+ chain.mData->readAfter(
+ (*it).mChannels.in(),
+ NULL,
+ (U8*)buf,
+ bytes);
+ buf[bytes] = '\0';
+ LL_INFOS() << "Input After Error: " << buf << LL_ENDL;
+ delete[] buf;
+ buf = NULL;
+ }
+ else
+ {
+ LL_INFOS() << "Input After Error: (null)" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_INFOS() << "Input After Error: (null)" << LL_ENDL;
+ }
+#endif
+ keep_going = false;
+ chain.mHead = it;
+ if(!handleChainError(chain, status))
+ {
+ chain.mHead = end;
+ }
+ }
+ else
+ {
+ LL_INFOS() << "Unhandled status code: " << status << ":"
+ << LLIOPipe::lookupStatusString(status) << LL_ENDL;
+ }
+ break;
+ }
+ PUMP_DEBUG;
+ } while(keep_going && (++it != end));
+ PUMP_DEBUG;
+}
+
+bool LLPumpIO::isChainExpired(LLChainInfo& chain)
+{
+ if(!chain.mHasCurlRequest)
+ {
+ return false ;
+ }
+
+ for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter)
+ {
+ if(!(*iter).mPipe->isValid())
+ {
+ return true ;
+ }
+ }
+
+ return false ;
+}
+
+bool LLPumpIO::handleChainError(
+ LLChainInfo& chain,
+ LLIOPipe::EStatus error)
+{
+ links_t::reverse_iterator rit;
+ if(chain.mHead == chain.mChainLinks.end())
+ {
+ rit = links_t::reverse_iterator(chain.mHead);
+ }
+ else
+ {
+ rit = links_t::reverse_iterator(chain.mHead + 1);
+ }
+
+ links_t::reverse_iterator rend = chain.mChainLinks.rend();
+ bool handled = false;
+ bool keep_going = true;
+ do
+ {
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "Passing error to " << typeid(*((*rit).mPipe)).name()
+ << "." << LL_ENDL;
+#endif
+ error = (*rit).mPipe->handleError(error, this);
+ switch(error)
+ {
+ case LLIOPipe::STATUS_OK:
+ handled = true;
+ chain.mHead = rit.base();
+ break;
+ case LLIOPipe::STATUS_STOP:
+ case LLIOPipe::STATUS_DONE:
+ case LLIOPipe::STATUS_BREAK:
+ case LLIOPipe::STATUS_NEED_PROCESS:
+#if LL_DEBUG_PIPE_TYPE_IN_PUMP
+ LL_DEBUGS() << "Pipe " << typeid(*((*rit).mPipe)).name()
+ << " returned code to stop error handler." << LL_ENDL;
+#endif
+ keep_going = false;
+ break;
+ case LLIOPipe::STATUS_EXPIRED:
+ keep_going = false;
+ break ;
+ default:
+ if(LLIOPipe::isSuccess(error))
+ {
+ LL_INFOS() << "Unhandled status code: " << error << ":"
+ << LLIOPipe::lookupStatusString(error) << LL_ENDL;
+ error = LLIOPipe::STATUS_ERROR;
+ keep_going = false;
+ }
+ break;
+ }
+ } while(keep_going && !handled && (++rit != rend));
+ return handled;
+}
+
+/**
+ * LLPumpIO::LLChainInfo
+ */
+
+LLPumpIO::LLChainInfo::LLChainInfo() :
+ mInit(false),
+ mLock(0),
+ mEOS(false),
+ mHasCurlRequest(false)
+{
+ mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
+}
+
+void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout)
+{
+ if(timeout > 0.0f)
+ {
+ mTimer.start();
+ mTimer.reset();
+ mTimer.setTimerExpirySec(timeout);
+ }
+ else
+ {
+ mTimer.stop();
+ }
+}
+
+void LLPumpIO::LLChainInfo::adjustTimeoutSeconds(F32 delta)
+{
+ if(mTimer.getStarted())
+ {
+ F64 expiry = mTimer.expiresAt();
+ expiry += delta;
+ mTimer.setExpiryAt(expiry);
+ }
+}
diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h
index b9eabee710..67e317ed2d 100644
--- a/indra/llmessage/llpumpio.h
+++ b/indra/llmessage/llpumpio.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpumpio.h
* @author Phoenix
* @date 2004-11-19
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,7 +45,7 @@ extern const F32 DEFAULT_CHAIN_EXPIRY_SECS;
extern const F32 SHORT_CHAIN_EXPIRY_SECS;
extern const F32 NEVER_CHAIN_EXPIRY_SECS;
-/**
+/**
* @class LLPumpIO
* @brief Class to manage sets of io chains.
*
@@ -73,367 +73,367 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS;
class LLPumpIO
{
public:
- /**
- * @brief Constructor.
- */
- LLPumpIO(apr_pool_t* pool);
-
- /**
- * @brief Destructor.
- */
- ~LLPumpIO();
-
- /**
- * @brief Prepare this pump for usage.
- *
- * If you fail to call this method prior to use, the pump will
- * try to work, but will not come with any thread locking
- * mechanisms.
- * @param pool The apr pool to use.
- * @return Returns true if the pump is primed.
- */
- bool prime(apr_pool_t* pool);
-
- /**
- * @brief Typedef for having a chain of pipes.
- */
- typedef std::vector<LLIOPipe::ptr_t> chain_t;
-
- /**
- * @brief Add a chain to this pump and process in the next cycle.
- *
- * This method will automatically generate a buffer and assign
- * each link in the chain as if it were the consumer to the
- * previous.
- * @param chain The pipes for the chain
- * @param timeout The number of seconds in the future to
- * expire. Pass in 0.0f to never expire.
- * @param has_curl_request The chain contains LLURLRequest if true.
- * @return Returns true if anything was added to the pump.
- */
- bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);
-
- /**
- * @brief Struct to associate a pipe with it's buffer io indexes.
- */
- struct LLLinkInfo
- {
- LLIOPipe::ptr_t mPipe;
- LLChannelDescriptors mChannels;
- };
-
- /**
- * @brief Typedef for having a chain of <code>LLLinkInfo</code>
- * instances.
- */
- typedef std::vector<LLLinkInfo> links_t;
-
- /**
- * @brief Add a chain to this pump and process in the next cycle.
- *
- * This method provides a slightly more sophisticated method for
- * adding a chain where the caller can specify which link elements
- * are on what channels. This method will fail if no buffer is
- * provided since any calls to generate new channels for the
- * buffers will cause unpredictable interleaving of data.
- * @param links The pipes and io indexes for the chain
- * @param data Shared pointer to data buffer
- * @param context Potentially undefined context meta-data for chain.
- * @param timeout The number of seconds in the future to
- * expire. Pass in 0.0f to never expire.
- * @return Returns true if anything was added to the pump.
- */
- bool addChain(
- const links_t& links,
- LLIOPipe::buffer_ptr_t data,
- LLSD context,
- F32 timeout);
-
- /**
- * @brief Set or clear a timeout for the running chain
- *
- * @param timeout The number of seconds in the future to
- * expire. Pass in 0.0f to never expire.
- * @return Returns true if the timer was set.
- */
- bool setTimeoutSeconds(F32 timeout);
-
- /**
- * @brief Adjust the timeout of the running chain.
- *
- * This method has no effect if there is no timeout on the chain.
- * @param delta The number of seconds to add to/remove from the timeout.
- */
- void adjustTimeoutSeconds(F32 delta);
-
- /**
- * @brief Set up file descriptors for for the running chain.
- * @see rebuildPollset()
- *
- * There is currently a limit of one conditional per pipe.
- * *NOTE: The internal mechanism for building a pollset based on
- * pipe/pollfd/chain generates an epoll error on linux (and
- * probably behaves similarly on other platforms) because the
- * pollset rebuilder will add each apr_pollfd_t serially. This
- * does not matter for pipes on the same chain, since any
- * signalled pipe will eventually invoke a call to process(), but
- * is a problem if the same apr_pollfd_t is on different
- * chains. Once we have more than just network i/o on the pump,
- * this might matter.
- * *FIX: Given the structure of the pump and pipe relationship,
- * this should probably go through a different mechanism than the
- * pump. I think it would be best if the pipe had some kind of
- * controller which was passed into <code>process()</code> rather
- * than the pump which exposed this interface.
- * @param pipe The pipe which is setting a conditional
- * @param poll The entire socket and read/write condition - null to remove
- * @return Returns true if the poll state was set.
- */
- bool setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll);
-
- /**
- * @brief Lock the current chain.
- * @see sleepChain() since it relies on the implementation of this method.
- *
- * This locks the currently running chain so that no more calls to
- * <code>process()</code> until you call <code>clearLock()</code>
- * with the lock identifier.
- * *FIX: Given the structure of the pump and pipe relationship,
- * this should probably go through a different mechanism than the
- * pump. I think it would be best if the pipe had some kind of
- * controller which was passed into <code>process()</code> rather
- * than the pump which exposed this interface.
- * @return Returns the lock identifer to be used in
- * <code>clearLock()</code> or 0 on failure.
- */
- S32 setLock();
-
- /**
- * @brief Clears the identified lock.
- *
- * @param links A container for the links which will be appended
- */
- void clearLock(S32 key);
-
- /**
- * @brief Stop processing a chain for a while.
- * @see setLock()
- *
- * This method will <em>not</em> update the timeout for this
- * chain, so it is possible to sleep the chain until it is
- * collected by the pump during a timeout cleanup.
- * @param seconds The number of seconds in the future to
- * resume processing.
- * @return Returns true if the
- */
- bool sleepChain(F64 seconds);
-
- /**
- * @brief Copy the currently running chain link info
- *
- * *FIX: Given the structure of the pump and pipe relationship,
- * this should probably go through a different mechanism than the
- * pump. I think it would be best if the pipe had some kind of
- * controller which was passed into <code>process()</code> rather
- * than the pump which exposed this interface.
- * @param links A container for the links which will be appended
- * @return Returns true if the currently running chain was copied.
- */
- bool copyCurrentLinkInfo(links_t& links) const;
-
- /**
- * @brief Call this method to call process on all running chains.
- *
- * This method iterates through the running chains, and if all
- * pipe on a chain are unconditionally ready or if any pipe has
- * any conditional processiong condition then process will be
- * called on every chain which has requested processing. that
- * chain has a file descriptor ready, <code>process()</code> will
- * be called for all pipes which have requested it.
- */
- void pump(const S32& poll_timeout);
- void pump();
-
- /**
- * @brief Add a chain to a special queue which will be called
- * during the next call to <code>callback()</code> and then
- * dropped from the queue.
- *
- * @param chain The IO chain that will get one <code>process()</code>.
- */
- //void respond(const chain_t& pipes);
-
- /**
- * @brief Add pipe to a special queue which will be called
- * during the next call to <code>callback()</code> and then dropped
- * from the queue.
- *
- * This call will add a single pipe, with no buffer, context, or
- * channel information to the callback queue. It will be called
- * once, and then dropped.
- * @param pipe A single io pipe which will be called
- * @return Returns true if anything was added to the pump.
- */
- bool respond(LLIOPipe* pipe);
-
- /**
- * @brief Add a chain to a special queue which will be called
- * during the next call to <code>callback()</code> and then
- * dropped from the queue.
- *
- * It is important to remember that you should not add a data
- * buffer or context which may still be in another chain - that
- * will almost certainly lead to a problems. Ensure that you are
- * done reading and writing to those parameters, have new
- * generated, or empty pointers.
- * @param links The pipes and io indexes for the chain
- * @param data Shared pointer to data buffer
- * @param context Potentially undefined context meta-data for chain.
- * @return Returns true if anything was added to the pump.
- */
- bool respond(
- const links_t& links,
- LLIOPipe::buffer_ptr_t data,
- LLSD context);
-
- /**
- * @brief Run through the callback queue and call <code>process()</code>.
- *
- * This call will process all prending responses and call process
- * on each. This method will then drop all processed callback
- * requests which may lead to deleting the referenced objects.
- */
- void callback();
-
- /**
- * @brief Enumeration to send commands to the pump.
- */
- enum EControl
- {
- PAUSE,
- RESUME,
- };
-
- /**
- * @brief Send a command to the pump.
- *
- * @param op What control to send to the pump.
- */
- void control(EControl op);
+ /**
+ * @brief Constructor.
+ */
+ LLPumpIO(apr_pool_t* pool);
+
+ /**
+ * @brief Destructor.
+ */
+ ~LLPumpIO();
+
+ /**
+ * @brief Prepare this pump for usage.
+ *
+ * If you fail to call this method prior to use, the pump will
+ * try to work, but will not come with any thread locking
+ * mechanisms.
+ * @param pool The apr pool to use.
+ * @return Returns true if the pump is primed.
+ */
+ bool prime(apr_pool_t* pool);
+
+ /**
+ * @brief Typedef for having a chain of pipes.
+ */
+ typedef std::vector<LLIOPipe::ptr_t> chain_t;
+
+ /**
+ * @brief Add a chain to this pump and process in the next cycle.
+ *
+ * This method will automatically generate a buffer and assign
+ * each link in the chain as if it were the consumer to the
+ * previous.
+ * @param chain The pipes for the chain
+ * @param timeout The number of seconds in the future to
+ * expire. Pass in 0.0f to never expire.
+ * @param has_curl_request The chain contains LLURLRequest if true.
+ * @return Returns true if anything was added to the pump.
+ */
+ bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);
+
+ /**
+ * @brief Struct to associate a pipe with it's buffer io indexes.
+ */
+ struct LLLinkInfo
+ {
+ LLIOPipe::ptr_t mPipe;
+ LLChannelDescriptors mChannels;
+ };
+
+ /**
+ * @brief Typedef for having a chain of <code>LLLinkInfo</code>
+ * instances.
+ */
+ typedef std::vector<LLLinkInfo> links_t;
+
+ /**
+ * @brief Add a chain to this pump and process in the next cycle.
+ *
+ * This method provides a slightly more sophisticated method for
+ * adding a chain where the caller can specify which link elements
+ * are on what channels. This method will fail if no buffer is
+ * provided since any calls to generate new channels for the
+ * buffers will cause unpredictable interleaving of data.
+ * @param links The pipes and io indexes for the chain
+ * @param data Shared pointer to data buffer
+ * @param context Potentially undefined context meta-data for chain.
+ * @param timeout The number of seconds in the future to
+ * expire. Pass in 0.0f to never expire.
+ * @return Returns true if anything was added to the pump.
+ */
+ bool addChain(
+ const links_t& links,
+ LLIOPipe::buffer_ptr_t data,
+ LLSD context,
+ F32 timeout);
+
+ /**
+ * @brief Set or clear a timeout for the running chain
+ *
+ * @param timeout The number of seconds in the future to
+ * expire. Pass in 0.0f to never expire.
+ * @return Returns true if the timer was set.
+ */
+ bool setTimeoutSeconds(F32 timeout);
+
+ /**
+ * @brief Adjust the timeout of the running chain.
+ *
+ * This method has no effect if there is no timeout on the chain.
+ * @param delta The number of seconds to add to/remove from the timeout.
+ */
+ void adjustTimeoutSeconds(F32 delta);
+
+ /**
+ * @brief Set up file descriptors for for the running chain.
+ * @see rebuildPollset()
+ *
+ * There is currently a limit of one conditional per pipe.
+ * *NOTE: The internal mechanism for building a pollset based on
+ * pipe/pollfd/chain generates an epoll error on linux (and
+ * probably behaves similarly on other platforms) because the
+ * pollset rebuilder will add each apr_pollfd_t serially. This
+ * does not matter for pipes on the same chain, since any
+ * signalled pipe will eventually invoke a call to process(), but
+ * is a problem if the same apr_pollfd_t is on different
+ * chains. Once we have more than just network i/o on the pump,
+ * this might matter.
+ * *FIX: Given the structure of the pump and pipe relationship,
+ * this should probably go through a different mechanism than the
+ * pump. I think it would be best if the pipe had some kind of
+ * controller which was passed into <code>process()</code> rather
+ * than the pump which exposed this interface.
+ * @param pipe The pipe which is setting a conditional
+ * @param poll The entire socket and read/write condition - null to remove
+ * @return Returns true if the poll state was set.
+ */
+ bool setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll);
+
+ /**
+ * @brief Lock the current chain.
+ * @see sleepChain() since it relies on the implementation of this method.
+ *
+ * This locks the currently running chain so that no more calls to
+ * <code>process()</code> until you call <code>clearLock()</code>
+ * with the lock identifier.
+ * *FIX: Given the structure of the pump and pipe relationship,
+ * this should probably go through a different mechanism than the
+ * pump. I think it would be best if the pipe had some kind of
+ * controller which was passed into <code>process()</code> rather
+ * than the pump which exposed this interface.
+ * @return Returns the lock identifer to be used in
+ * <code>clearLock()</code> or 0 on failure.
+ */
+ S32 setLock();
+
+ /**
+ * @brief Clears the identified lock.
+ *
+ * @param links A container for the links which will be appended
+ */
+ void clearLock(S32 key);
+
+ /**
+ * @brief Stop processing a chain for a while.
+ * @see setLock()
+ *
+ * This method will <em>not</em> update the timeout for this
+ * chain, so it is possible to sleep the chain until it is
+ * collected by the pump during a timeout cleanup.
+ * @param seconds The number of seconds in the future to
+ * resume processing.
+ * @return Returns true if the
+ */
+ bool sleepChain(F64 seconds);
+
+ /**
+ * @brief Copy the currently running chain link info
+ *
+ * *FIX: Given the structure of the pump and pipe relationship,
+ * this should probably go through a different mechanism than the
+ * pump. I think it would be best if the pipe had some kind of
+ * controller which was passed into <code>process()</code> rather
+ * than the pump which exposed this interface.
+ * @param links A container for the links which will be appended
+ * @return Returns true if the currently running chain was copied.
+ */
+ bool copyCurrentLinkInfo(links_t& links) const;
+
+ /**
+ * @brief Call this method to call process on all running chains.
+ *
+ * This method iterates through the running chains, and if all
+ * pipe on a chain are unconditionally ready or if any pipe has
+ * any conditional processiong condition then process will be
+ * called on every chain which has requested processing. that
+ * chain has a file descriptor ready, <code>process()</code> will
+ * be called for all pipes which have requested it.
+ */
+ void pump(const S32& poll_timeout);
+ void pump();
+
+ /**
+ * @brief Add a chain to a special queue which will be called
+ * during the next call to <code>callback()</code> and then
+ * dropped from the queue.
+ *
+ * @param chain The IO chain that will get one <code>process()</code>.
+ */
+ //void respond(const chain_t& pipes);
+
+ /**
+ * @brief Add pipe to a special queue which will be called
+ * during the next call to <code>callback()</code> and then dropped
+ * from the queue.
+ *
+ * This call will add a single pipe, with no buffer, context, or
+ * channel information to the callback queue. It will be called
+ * once, and then dropped.
+ * @param pipe A single io pipe which will be called
+ * @return Returns true if anything was added to the pump.
+ */
+ bool respond(LLIOPipe* pipe);
+
+ /**
+ * @brief Add a chain to a special queue which will be called
+ * during the next call to <code>callback()</code> and then
+ * dropped from the queue.
+ *
+ * It is important to remember that you should not add a data
+ * buffer or context which may still be in another chain - that
+ * will almost certainly lead to a problems. Ensure that you are
+ * done reading and writing to those parameters, have new
+ * generated, or empty pointers.
+ * @param links The pipes and io indexes for the chain
+ * @param data Shared pointer to data buffer
+ * @param context Potentially undefined context meta-data for chain.
+ * @return Returns true if anything was added to the pump.
+ */
+ bool respond(
+ const links_t& links,
+ LLIOPipe::buffer_ptr_t data,
+ LLSD context);
+
+ /**
+ * @brief Run through the callback queue and call <code>process()</code>.
+ *
+ * This call will process all prending responses and call process
+ * on each. This method will then drop all processed callback
+ * requests which may lead to deleting the referenced objects.
+ */
+ void callback();
+
+ /**
+ * @brief Enumeration to send commands to the pump.
+ */
+ enum EControl
+ {
+ PAUSE,
+ RESUME,
+ };
+
+ /**
+ * @brief Send a command to the pump.
+ *
+ * @param op What control to send to the pump.
+ */
+ void control(EControl op);
protected:
- /**
- * @brief State of the pump
- */
- enum EState
- {
- NORMAL,
- PAUSING,
- PAUSED
- };
-
- // instance data
- EState mState;
- bool mRebuildPollset;
- apr_pollset_t* mPollset;
- S32 mPollsetClientID;
- S32 mNextLock;
- std::set<S32> mClearLocks;
-
- // This is the pump's runnable scheduler used for handling
- // expiring locks.
- LLRunner mRunner;
-
- // This structure is the stuff we track while running chains.
- struct LLChainInfo
- {
- // methods
- LLChainInfo();
- void setTimeoutSeconds(F32 timeout);
- void adjustTimeoutSeconds(F32 delta);
-
- // basic member data
- bool mInit;
- bool mEOS;
- bool mHasCurlRequest;
- S32 mLock;
- LLFrameTimer mTimer;
- links_t::iterator mHead;
- links_t mChainLinks;
- LLIOPipe::buffer_ptr_t mData;
- LLSD mContext;
-
- // tracking inside the pump
- typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
- typedef std::vector<pipe_conditional_t> conditionals_t;
- conditionals_t mDescriptors;
- };
-
- // All the running chains & info
- typedef std::vector<LLChainInfo> pending_chains_t;
- pending_chains_t mPendingChains;
- typedef std::list<LLChainInfo> running_chains_t;
- running_chains_t mRunningChains;
-
- typedef running_chains_t::iterator current_chain_t;
- current_chain_t mCurrentChain;
-
- // structures necessary for doing callbacks
- // since the callbacks only get one chance to run, we do not have
- // to maintain a list.
- typedef std::vector<LLChainInfo> callbacks_t;
- callbacks_t mPendingCallbacks;
- callbacks_t mCallbacks;
-
- // memory allocator for pollsets & mutexes.
- apr_pool_t* mPool;
- apr_pool_t* mCurrentPool;
- S32 mCurrentPoolReallocCount;
+ /**
+ * @brief State of the pump
+ */
+ enum EState
+ {
+ NORMAL,
+ PAUSING,
+ PAUSED
+ };
+
+ // instance data
+ EState mState;
+ bool mRebuildPollset;
+ apr_pollset_t* mPollset;
+ S32 mPollsetClientID;
+ S32 mNextLock;
+ std::set<S32> mClearLocks;
+
+ // This is the pump's runnable scheduler used for handling
+ // expiring locks.
+ LLRunner mRunner;
+
+ // This structure is the stuff we track while running chains.
+ struct LLChainInfo
+ {
+ // methods
+ LLChainInfo();
+ void setTimeoutSeconds(F32 timeout);
+ void adjustTimeoutSeconds(F32 delta);
+
+ // basic member data
+ bool mInit;
+ bool mEOS;
+ bool mHasCurlRequest;
+ S32 mLock;
+ LLFrameTimer mTimer;
+ links_t::iterator mHead;
+ links_t mChainLinks;
+ LLIOPipe::buffer_ptr_t mData;
+ LLSD mContext;
+
+ // tracking inside the pump
+ typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
+ typedef std::vector<pipe_conditional_t> conditionals_t;
+ conditionals_t mDescriptors;
+ };
+
+ // All the running chains & info
+ typedef std::vector<LLChainInfo> pending_chains_t;
+ pending_chains_t mPendingChains;
+ typedef std::list<LLChainInfo> running_chains_t;
+ running_chains_t mRunningChains;
+
+ typedef running_chains_t::iterator current_chain_t;
+ current_chain_t mCurrentChain;
+
+ // structures necessary for doing callbacks
+ // since the callbacks only get one chance to run, we do not have
+ // to maintain a list.
+ typedef std::vector<LLChainInfo> callbacks_t;
+ callbacks_t mPendingCallbacks;
+ callbacks_t mCallbacks;
+
+ // memory allocator for pollsets & mutexes.
+ apr_pool_t* mPool;
+ apr_pool_t* mCurrentPool;
+ S32 mCurrentPoolReallocCount;
protected:
- void initialize(apr_pool_t* pool);
- void cleanup();
- current_chain_t removeRunningChain(current_chain_t& chain) ;
- /**
- * @brief Given the internal state of the chains, rebuild the pollset
- * @see setConditional()
- */
- void rebuildPollset();
-
- /**
- * @brief Process the chain passed in.
- *
- * This method will potentially modify the internals of the
- * chain. On end, the chain.mHead will equal
- * chain.mChainLinks.end().
- * @param chain The LLChainInfo object to work on.
- */
- void processChain(LLChainInfo& chain);
-
- /**
- * @brief Rewind through the chain to try to recover from an error.
- *
- * This method will potentially modify the internals of the
- * chain.
- * @param chain The LLChainInfo object to work on.
- * @return Retuns true if someone handled the error
- */
- bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error);
-
- //if the chain is expired, remove it
- bool isChainExpired(LLChainInfo& chain) ;
+ void initialize(apr_pool_t* pool);
+ void cleanup();
+ current_chain_t removeRunningChain(current_chain_t& chain) ;
+ /**
+ * @brief Given the internal state of the chains, rebuild the pollset
+ * @see setConditional()
+ */
+ void rebuildPollset();
+
+ /**
+ * @brief Process the chain passed in.
+ *
+ * This method will potentially modify the internals of the
+ * chain. On end, the chain.mHead will equal
+ * chain.mChainLinks.end().
+ * @param chain The LLChainInfo object to work on.
+ */
+ void processChain(LLChainInfo& chain);
+
+ /**
+ * @brief Rewind through the chain to try to recover from an error.
+ *
+ * This method will potentially modify the internals of the
+ * chain.
+ * @param chain The LLChainInfo object to work on.
+ * @return Retuns true if someone handled the error
+ */
+ bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error);
+
+ //if the chain is expired, remove it
+ bool isChainExpired(LLChainInfo& chain) ;
public:
- /**
- * @brief Return number of running chains.
- *
- * *NOTE: This is only used in debugging and not considered
- * efficient or safe enough for production use.
- */
- running_chains_t::size_type runningChains() const
- {
- return mRunningChains.size();
- }
+ /**
+ * @brief Return number of running chains.
+ *
+ * *NOTE: This is only used in debugging and not considered
+ * efficient or safe enough for production use.
+ */
+ running_chains_t::size_type runningChains() const
+ {
+ return mRunningChains.size();
+ }
};
diff --git a/indra/llmessage/llqueryflags.h b/indra/llmessage/llqueryflags.h
index 14a62de04f..227d28ba5c 100644
--- a/indra/llmessage/llqueryflags.h
+++ b/indra/llmessage/llqueryflags.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llqueryflags.h
* @brief Flags for directory queries
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,73 +30,73 @@
// Binary flags used for Find queries, shared between viewer and dataserver.
// DirFindQuery flags
-const U32 DFQ_PEOPLE = 0x1 << 0;
-const U32 DFQ_ONLINE = 0x1 << 1;
-//const U32 DFQ_PLACES = 0x1 << 2;
-const U32 DFQ_EVENTS = 0x1 << 3; // This is not set by the 1.21 viewer, but I don't know about older versions. JC
-const U32 DFQ_GROUPS = 0x1 << 4;
-const U32 DFQ_DATE_EVENTS = 0x1 << 5;
+const U32 DFQ_PEOPLE = 0x1 << 0;
+const U32 DFQ_ONLINE = 0x1 << 1;
+//const U32 DFQ_PLACES = 0x1 << 2;
+const U32 DFQ_EVENTS = 0x1 << 3; // This is not set by the 1.21 viewer, but I don't know about older versions. JC
+const U32 DFQ_GROUPS = 0x1 << 4;
+const U32 DFQ_DATE_EVENTS = 0x1 << 5;
-const U32 DFQ_AGENT_OWNED = 0x1 << 6;
-const U32 DFQ_FOR_SALE = 0x1 << 7;
-const U32 DFQ_GROUP_OWNED = 0x1 << 8;
-//const U32 DFQ_AUCTION = 0x1 << 9;
-const U32 DFQ_DWELL_SORT = 0x1 << 10;
-const U32 DFQ_PG_SIMS_ONLY = 0x1 << 11;
-const U32 DFQ_PICTURES_ONLY = 0x1 << 12;
-const U32 DFQ_PG_EVENTS_ONLY = 0x1 << 13;
+const U32 DFQ_AGENT_OWNED = 0x1 << 6;
+const U32 DFQ_FOR_SALE = 0x1 << 7;
+const U32 DFQ_GROUP_OWNED = 0x1 << 8;
+//const U32 DFQ_AUCTION = 0x1 << 9;
+const U32 DFQ_DWELL_SORT = 0x1 << 10;
+const U32 DFQ_PG_SIMS_ONLY = 0x1 << 11;
+const U32 DFQ_PICTURES_ONLY = 0x1 << 12;
+const U32 DFQ_PG_EVENTS_ONLY = 0x1 << 13;
const U32 DFQ_MATURE_SIMS_ONLY = 0x1 << 14;
-const U32 DFQ_SORT_ASC = 0x1 << 15;
-const U32 DFQ_PRICE_SORT = 0x1 << 16;
-const U32 DFQ_PER_METER_SORT = 0x1 << 17;
-const U32 DFQ_AREA_SORT = 0x1 << 18;
-const U32 DFQ_NAME_SORT = 0x1 << 19;
+const U32 DFQ_SORT_ASC = 0x1 << 15;
+const U32 DFQ_PRICE_SORT = 0x1 << 16;
+const U32 DFQ_PER_METER_SORT = 0x1 << 17;
+const U32 DFQ_AREA_SORT = 0x1 << 18;
+const U32 DFQ_NAME_SORT = 0x1 << 19;
-const U32 DFQ_LIMIT_BY_PRICE = 0x1 << 20;
-const U32 DFQ_LIMIT_BY_AREA = 0x1 << 21;
+const U32 DFQ_LIMIT_BY_PRICE = 0x1 << 20;
+const U32 DFQ_LIMIT_BY_AREA = 0x1 << 21;
-const U32 DFQ_FILTER_MATURE = 0x1 << 22;
-const U32 DFQ_PG_PARCELS_ONLY = 0x1 << 23;
+const U32 DFQ_FILTER_MATURE = 0x1 << 22;
+const U32 DFQ_PG_PARCELS_ONLY = 0x1 << 23;
-const U32 DFQ_INC_PG = 0x1 << 24; // Flags appear in 1.23 viewer or later
-const U32 DFQ_INC_MATURE = 0x1 << 25;
-const U32 DFQ_INC_ADULT = 0x1 << 26;
-const U32 DFQ_INC_NEW_VIEWER = (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT); // Indicates 1.23 viewer or later
+const U32 DFQ_INC_PG = 0x1 << 24; // Flags appear in 1.23 viewer or later
+const U32 DFQ_INC_MATURE = 0x1 << 25;
+const U32 DFQ_INC_ADULT = 0x1 << 26;
+const U32 DFQ_INC_NEW_VIEWER = (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT); // Indicates 1.23 viewer or later
-const U32 DFQ_ADULT_SIMS_ONLY = 0x1 << 27;
+const U32 DFQ_ADULT_SIMS_ONLY = 0x1 << 27;
// Sell Type flags
-const U32 ST_AUCTION = 0x1 << 1;
-const U32 ST_NEWBIE = 0x1 << 2;
-const U32 ST_MAINLAND = 0x1 << 3;
-const U32 ST_ESTATE = 0x1 << 4;
+const U32 ST_AUCTION = 0x1 << 1;
+const U32 ST_NEWBIE = 0x1 << 2;
+const U32 ST_MAINLAND = 0x1 << 3;
+const U32 ST_ESTATE = 0x1 << 4;
-const U32 ST_ALL = 0xFFFFFFFF;
+const U32 ST_ALL = 0xFFFFFFFF;
// status flags embedded in search replay messages of classifieds, events, groups, and places.
// Places
-const U32 STATUS_SEARCH_PLACES_NONE = 0x0;
-const U32 STATUS_SEARCH_PLACES_BANNEDWORD = 0x1 << 0;
-const U32 STATUS_SEARCH_PLACES_SHORTSTRING = 0x1 << 1;
-const U32 STATUS_SEARCH_PLACES_FOUNDNONE = 0x1 << 2;
-const U32 STATUS_SEARCH_PLACES_SEARCHDISABLED = 0x1 << 3;
-const U32 STATUS_SEARCH_PLACES_ESTATEEMPTY = 0x1 << 4;
+const U32 STATUS_SEARCH_PLACES_NONE = 0x0;
+const U32 STATUS_SEARCH_PLACES_BANNEDWORD = 0x1 << 0;
+const U32 STATUS_SEARCH_PLACES_SHORTSTRING = 0x1 << 1;
+const U32 STATUS_SEARCH_PLACES_FOUNDNONE = 0x1 << 2;
+const U32 STATUS_SEARCH_PLACES_SEARCHDISABLED = 0x1 << 3;
+const U32 STATUS_SEARCH_PLACES_ESTATEEMPTY = 0x1 << 4;
// Events
-const U32 STATUS_SEARCH_EVENTS_NONE = 0x0;
-const U32 STATUS_SEARCH_EVENTS_BANNEDWORD = 0x1 << 0;
-const U32 STATUS_SEARCH_EVENTS_SHORTSTRING = 0x1 << 1;
-const U32 STATUS_SEARCH_EVENTS_FOUNDNONE = 0x1 << 2;
-const U32 STATUS_SEARCH_EVENTS_SEARCHDISABLED = 0x1 << 3;
-const U32 STATUS_SEARCH_EVENTS_NODATEOFFSET = 0x1 << 4;
-const U32 STATUS_SEARCH_EVENTS_NOCATEGORY = 0x1 << 5;
-const U32 STATUS_SEARCH_EVENTS_NOQUERY = 0x1 << 6;
+const U32 STATUS_SEARCH_EVENTS_NONE = 0x0;
+const U32 STATUS_SEARCH_EVENTS_BANNEDWORD = 0x1 << 0;
+const U32 STATUS_SEARCH_EVENTS_SHORTSTRING = 0x1 << 1;
+const U32 STATUS_SEARCH_EVENTS_FOUNDNONE = 0x1 << 2;
+const U32 STATUS_SEARCH_EVENTS_SEARCHDISABLED = 0x1 << 3;
+const U32 STATUS_SEARCH_EVENTS_NODATEOFFSET = 0x1 << 4;
+const U32 STATUS_SEARCH_EVENTS_NOCATEGORY = 0x1 << 5;
+const U32 STATUS_SEARCH_EVENTS_NOQUERY = 0x1 << 6;
//Classifieds
-const U32 STATUS_SEARCH_CLASSIFIEDS_NONE = 0x0;
-const U32 STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD = 0x1 << 0;
-const U32 STATUS_SEARCH_CLASSIFIEDS_SHORTSTRING = 0x1 << 1;
-const U32 STATUS_SEARCH_CLASSIFIEDS_FOUNDNONE = 0x1 << 2;
-const U32 STATUS_SEARCH_CLASSIFIEDS_SEARCHDISABLED = 0x1 << 3;
+const U32 STATUS_SEARCH_CLASSIFIEDS_NONE = 0x0;
+const U32 STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD = 0x1 << 0;
+const U32 STATUS_SEARCH_CLASSIFIEDS_SHORTSTRING = 0x1 << 1;
+const U32 STATUS_SEARCH_CLASSIFIEDS_FOUNDNONE = 0x1 << 2;
+const U32 STATUS_SEARCH_CLASSIFIEDS_SEARCHDISABLED = 0x1 << 3;
#endif
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index ab2d127f6e..835bccfb14 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -1,211 +1,211 @@
-/**
- * @file llregionflags.h
- * @brief Flags that are sent in the statistics message region_flags field.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLREGIONFLAGS_H
-#define LL_LLREGIONFLAGS_H
-
-// Can you be hurt here? Should health be on?
-const U64 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0);
-
-// Can you make landmarks here?
-const U64 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1);
-
-// Do we reset the home position when someone teleports away from here?
-const U64 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2);
-
-// Do we reset the home position when someone teleports away from here?
-const U64 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3);
-
-// Does the sun move?
-const U64 REGION_FLAGS_SUN_FIXED = (1 << 4);
-
-// Does the estate owner allow private parcels?
-const U64 REGION_FLAGS_ALLOW_ACCESS_OVERRIDE = (1 << 5);
-
-// Can't change the terrain heightfield, even on owned parcels,
-// but can plant trees and grass.
-const U64 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6);
-
-// Can't release, sell, or buy land.
-const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
-
-// All content wiped once per night
-const U64 REGION_FLAGS_SANDBOX = (1 << 8);
-
-const U64 REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE = (1 << 9);
-
-const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
-const U64 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
-const U64 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
-const U64 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15);
-const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
-const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
-const U64 REGION_FLAGS_BLOCK_DWELL = (1 << 18);
-
-// Is flight allowed?
-const U64 REGION_FLAGS_BLOCK_FLY = (1 << 19);
-
-// Is direct teleport (p2p) allowed?
-const U64 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20);
-
-// Is there an administrative override on scripts in the region at the
-// moment. This is the similar skip scripts, except this flag is
-// presisted in the database on an estate level.
-const U64 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21);
-
-const U64 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22);
-
-const U64 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
-
-const U64 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
-
-const U64 REGION_FLAGS_BLOCK_FLYOVER = (1 << 27);
-
-const U64 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
-
-const U64 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
-const U64 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30);
-
-const U64 REGION_FLAGS_DENY_BOTS = (1 << 31);
-
-const U64 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
- REGION_FLAGS_ALLOW_SET_HOME |
- REGION_FLAGS_ALLOW_PARCEL_CHANGES |
- REGION_FLAGS_ALLOW_VOICE;
-
-
-const U64 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT;
-const U64 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
- | REGION_FLAGS_ALLOW_SET_HOME;
-
-const U64 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
- | REGION_FLAGS_SUN_FIXED
- | REGION_FLAGS_DENY_ANONYMOUS
- | REGION_FLAGS_DENY_AGEUNVERIFIED;
-
-inline bool is_flag_set(U64 flags, U64 flag)
-{
- return (flags & flag) != 0;
-}
-
-inline bool is_prelude( U64 flags )
-{
- // definition of prelude does not depend on fixed-sun
- return !is_flag_set(flags, REGION_FLAGS_PRELUDE_UNSET) &&
- is_flag_set(flags, REGION_FLAGS_PRELUDE_SET);
-}
-
-inline U64 set_prelude_flags(U64 flags)
-{
- // also set the sun-fixed flag
- return ((flags & ~REGION_FLAGS_PRELUDE_UNSET)
- | (REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
-}
-
-inline U64 unset_prelude_flags(U64 flags)
-{
- // also unset the fixed-sun flag
- return ((flags | REGION_FLAGS_PRELUDE_UNSET)
- & ~(REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
-}
-
-// Region protocols
-const U64 REGION_PROTOCOLS_AGENT_APPEARANCE_SERVICE = (1 << 0);
-
-// estate constants. Need to match first few etries in indra.estate table.
-const U32 ESTATE_ALL = 0; // will not match in db, reserved key for logic
-const U32 ESTATE_MAINLAND = 1;
-const U32 ESTATE_ORIENTATION = 2;
-const U32 ESTATE_INTERNAL = 3;
-const U32 ESTATE_SHOWCASE = 4;
-const U32 ESTATE_TEEN = 5;
-const U32 ESTATE_LAST_LINDEN = 5; // last linden owned/managed estate
-
-// for EstateOwnerRequest, setaccess message
-const U32 ESTATE_ACCESS_ALLOWED_AGENTS = 1 << 0;
-const U32 ESTATE_ACCESS_ALLOWED_GROUPS = 1 << 1;
-const U32 ESTATE_ACCESS_BANNED_AGENTS = 1 << 2;
-const U32 ESTATE_ACCESS_MANAGERS = 1 << 3;
-
-//maximum number of access list entries we can fit in one packet
-const S32 ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET = 63;
-
-// for reply to "getinfo", don't need to forward to all sims in estate
-const U32 ESTATE_ACCESS_SEND_TO_AGENT_ONLY = 1 << 4;
-
-const U32 ESTATE_ACCESS_ALL = ESTATE_ACCESS_ALLOWED_AGENTS
- | ESTATE_ACCESS_ALLOWED_GROUPS
- | ESTATE_ACCESS_BANNED_AGENTS
- | ESTATE_ACCESS_MANAGERS;
-
-// for EstateOwnerRequest, estateaccessdelta, estateexperiencedelta messages
-const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1U << 0;
-const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1U << 1;
-
-const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1U << 2;
-const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1U << 3;
-const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1U << 4;
-const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1U << 5;
-const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1U << 6;
-const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1U << 7;
-const U32 ESTATE_ACCESS_MANAGER_ADD = 1U << 8;
-const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
-const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
-const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
-
-const S32 ESTATE_MAX_MANAGERS = 20;
-const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access
-const S32 ESTATE_MAX_BANNED_IDS = 750; // max for banned
-const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET;
-
-// 'Sim Wide Delete' flags
-const U32 SWD_OTHERS_LAND_ONLY = (1 << 0);
-const U32 SWD_ALWAYS_RETURN_OBJECTS = (1 << 1);
-const U32 SWD_SCRIPTED_ONLY = (1 << 2);
-
-// Controls experience key validity in the estate
-const U32 EXPERIENCE_KEY_TYPE_NONE = 0;
-const U32 EXPERIENCE_KEY_TYPE_BLOCKED = 1;
-const U32 EXPERIENCE_KEY_TYPE_ALLOWED = 2;
-const U32 EXPERIENCE_KEY_TYPE_TRUSTED = 3;
-
-const U32 EXPERIENCE_KEY_TYPE_FIRST = EXPERIENCE_KEY_TYPE_BLOCKED;
-const U32 EXPERIENCE_KEY_TYPE_LAST = EXPERIENCE_KEY_TYPE_TRUSTED;
-
-//
-const U32 ESTATE_EXPERIENCE_TRUSTED_ADD = 1U << 2;
-const U32 ESTATE_EXPERIENCE_TRUSTED_REMOVE = 1U << 3;
-const U32 ESTATE_EXPERIENCE_ALLOWED_ADD = 1U << 4;
-const U32 ESTATE_EXPERIENCE_ALLOWED_REMOVE = 1U << 5;
-const U32 ESTATE_EXPERIENCE_BLOCKED_ADD = 1U << 6;
-const U32 ESTATE_EXPERIENCE_BLOCKED_REMOVE = 1U << 7;
-
-const S32 ESTATE_MAX_EXPERIENCE_IDS = 8;
-
-
-#endif
-
-
+/**
+ * @file llregionflags.h
+ * @brief Flags that are sent in the statistics message region_flags field.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLREGIONFLAGS_H
+#define LL_LLREGIONFLAGS_H
+
+// Can you be hurt here? Should health be on?
+const U64 REGION_FLAGS_ALLOW_DAMAGE = (1 << 0);
+
+// Can you make landmarks here?
+const U64 REGION_FLAGS_ALLOW_LANDMARK = (1 << 1);
+
+// Do we reset the home position when someone teleports away from here?
+const U64 REGION_FLAGS_ALLOW_SET_HOME = (1 << 2);
+
+// Do we reset the home position when someone teleports away from here?
+const U64 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3);
+
+// Does the sun move?
+const U64 REGION_FLAGS_SUN_FIXED = (1 << 4);
+
+// Does the estate owner allow private parcels?
+const U64 REGION_FLAGS_ALLOW_ACCESS_OVERRIDE = (1 << 5);
+
+// Can't change the terrain heightfield, even on owned parcels,
+// but can plant trees and grass.
+const U64 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6);
+
+// Can't release, sell, or buy land.
+const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
+
+// All content wiped once per night
+const U64 REGION_FLAGS_SANDBOX = (1 << 8);
+
+const U64 REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE = (1 << 9);
+
+const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
+const U64 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
+const U64 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
+const U64 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15);
+const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16);
+const U64 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17);
+const U64 REGION_FLAGS_BLOCK_DWELL = (1 << 18);
+
+// Is flight allowed?
+const U64 REGION_FLAGS_BLOCK_FLY = (1 << 19);
+
+// Is direct teleport (p2p) allowed?
+const U64 REGION_FLAGS_ALLOW_DIRECT_TELEPORT = (1 << 20);
+
+// Is there an administrative override on scripts in the region at the
+// moment. This is the similar skip scripts, except this flag is
+// presisted in the database on an estate level.
+const U64 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21);
+
+const U64 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22);
+
+const U64 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23);
+
+const U64 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26);
+
+const U64 REGION_FLAGS_BLOCK_FLYOVER = (1 << 27);
+
+const U64 REGION_FLAGS_ALLOW_VOICE = (1 << 28);
+
+const U64 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29);
+const U64 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30);
+
+const U64 REGION_FLAGS_DENY_BOTS = (1 << 31);
+
+const U64 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK |
+ REGION_FLAGS_ALLOW_SET_HOME |
+ REGION_FLAGS_ALLOW_PARCEL_CHANGES |
+ REGION_FLAGS_ALLOW_VOICE;
+
+
+const U64 REGION_FLAGS_PRELUDE_SET = REGION_FLAGS_RESET_HOME_ON_TELEPORT;
+const U64 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK
+ | REGION_FLAGS_ALLOW_SET_HOME;
+
+const U64 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE
+ | REGION_FLAGS_SUN_FIXED
+ | REGION_FLAGS_DENY_ANONYMOUS
+ | REGION_FLAGS_DENY_AGEUNVERIFIED;
+
+inline bool is_flag_set(U64 flags, U64 flag)
+{
+ return (flags & flag) != 0;
+}
+
+inline bool is_prelude( U64 flags )
+{
+ // definition of prelude does not depend on fixed-sun
+ return !is_flag_set(flags, REGION_FLAGS_PRELUDE_UNSET) &&
+ is_flag_set(flags, REGION_FLAGS_PRELUDE_SET);
+}
+
+inline U64 set_prelude_flags(U64 flags)
+{
+ // also set the sun-fixed flag
+ return ((flags & ~REGION_FLAGS_PRELUDE_UNSET)
+ | (REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
+}
+
+inline U64 unset_prelude_flags(U64 flags)
+{
+ // also unset the fixed-sun flag
+ return ((flags | REGION_FLAGS_PRELUDE_UNSET)
+ & ~(REGION_FLAGS_PRELUDE_SET | REGION_FLAGS_SUN_FIXED));
+}
+
+// Region protocols
+const U64 REGION_PROTOCOLS_AGENT_APPEARANCE_SERVICE = (1 << 0);
+
+// estate constants. Need to match first few etries in indra.estate table.
+const U32 ESTATE_ALL = 0; // will not match in db, reserved key for logic
+const U32 ESTATE_MAINLAND = 1;
+const U32 ESTATE_ORIENTATION = 2;
+const U32 ESTATE_INTERNAL = 3;
+const U32 ESTATE_SHOWCASE = 4;
+const U32 ESTATE_TEEN = 5;
+const U32 ESTATE_LAST_LINDEN = 5; // last linden owned/managed estate
+
+// for EstateOwnerRequest, setaccess message
+const U32 ESTATE_ACCESS_ALLOWED_AGENTS = 1 << 0;
+const U32 ESTATE_ACCESS_ALLOWED_GROUPS = 1 << 1;
+const U32 ESTATE_ACCESS_BANNED_AGENTS = 1 << 2;
+const U32 ESTATE_ACCESS_MANAGERS = 1 << 3;
+
+//maximum number of access list entries we can fit in one packet
+const S32 ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET = 63;
+
+// for reply to "getinfo", don't need to forward to all sims in estate
+const U32 ESTATE_ACCESS_SEND_TO_AGENT_ONLY = 1 << 4;
+
+const U32 ESTATE_ACCESS_ALL = ESTATE_ACCESS_ALLOWED_AGENTS
+ | ESTATE_ACCESS_ALLOWED_GROUPS
+ | ESTATE_ACCESS_BANNED_AGENTS
+ | ESTATE_ACCESS_MANAGERS;
+
+// for EstateOwnerRequest, estateaccessdelta, estateexperiencedelta messages
+const U32 ESTATE_ACCESS_APPLY_TO_ALL_ESTATES = 1U << 0;
+const U32 ESTATE_ACCESS_APPLY_TO_MANAGED_ESTATES = 1U << 1;
+
+const U32 ESTATE_ACCESS_ALLOWED_AGENT_ADD = 1U << 2;
+const U32 ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1U << 3;
+const U32 ESTATE_ACCESS_ALLOWED_GROUP_ADD = 1U << 4;
+const U32 ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 1U << 5;
+const U32 ESTATE_ACCESS_BANNED_AGENT_ADD = 1U << 6;
+const U32 ESTATE_ACCESS_BANNED_AGENT_REMOVE = 1U << 7;
+const U32 ESTATE_ACCESS_MANAGER_ADD = 1U << 8;
+const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
+const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
+const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
+
+const S32 ESTATE_MAX_MANAGERS = 20;
+const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access
+const S32 ESTATE_MAX_BANNED_IDS = 750; // max for banned
+const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET;
+
+// 'Sim Wide Delete' flags
+const U32 SWD_OTHERS_LAND_ONLY = (1 << 0);
+const U32 SWD_ALWAYS_RETURN_OBJECTS = (1 << 1);
+const U32 SWD_SCRIPTED_ONLY = (1 << 2);
+
+// Controls experience key validity in the estate
+const U32 EXPERIENCE_KEY_TYPE_NONE = 0;
+const U32 EXPERIENCE_KEY_TYPE_BLOCKED = 1;
+const U32 EXPERIENCE_KEY_TYPE_ALLOWED = 2;
+const U32 EXPERIENCE_KEY_TYPE_TRUSTED = 3;
+
+const U32 EXPERIENCE_KEY_TYPE_FIRST = EXPERIENCE_KEY_TYPE_BLOCKED;
+const U32 EXPERIENCE_KEY_TYPE_LAST = EXPERIENCE_KEY_TYPE_TRUSTED;
+
+//
+const U32 ESTATE_EXPERIENCE_TRUSTED_ADD = 1U << 2;
+const U32 ESTATE_EXPERIENCE_TRUSTED_REMOVE = 1U << 3;
+const U32 ESTATE_EXPERIENCE_ALLOWED_ADD = 1U << 4;
+const U32 ESTATE_EXPERIENCE_ALLOWED_REMOVE = 1U << 5;
+const U32 ESTATE_EXPERIENCE_BLOCKED_ADD = 1U << 6;
+const U32 ESTATE_EXPERIENCE_BLOCKED_REMOVE = 1U << 7;
+
+const S32 ESTATE_MAX_EXPERIENCE_IDS = 8;
+
+
+#endif
+
+
diff --git a/indra/llmessage/llregionhandle.h b/indra/llmessage/llregionhandle.h
index 284426c148..f732cdcce5 100644
--- a/indra/llmessage/llregionhandle.h
+++ b/indra/llmessage/llregionhandle.h
@@ -1,126 +1,126 @@
-/**
- * @file llregionhandle.h
- * @brief Routines for converting positions to/from region handles.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLREGIONHANDLE_H
-#define LL_LLREGIONHANDLE_H
-
-#include "indra_constants.h"
-#include "v3math.h"
-#include "v3dmath.h"
-
-inline U64 to_region_handle(const U32 x_origin, const U32 y_origin)
-{
- U64 region_handle;
- region_handle = ((U64)x_origin) << 32;
- region_handle |= (U64) y_origin;
- return region_handle;
-}
-
-inline U64 to_region_handle(const LLVector3d& pos_global)
-{
- U32 global_x = (U32)pos_global.mdV[VX];
- global_x -= global_x % 256;
-
- U32 global_y = (U32)pos_global.mdV[VY];
- global_y -= global_y % 256;
-
- return to_region_handle(global_x, global_y);
-}
-
-inline U64 to_region_handle_global(const F32 x_global, const F32 y_global)
-{
- // Round down to the nearest origin
- U32 x_origin = (U32)x_global;
- x_origin -= x_origin % REGION_WIDTH_U32;
- U32 y_origin = (U32)y_global;
- y_origin -= y_origin % REGION_WIDTH_U32;
- U64 region_handle;
- region_handle = ((U64)x_origin) << 32;
- region_handle |= (U64) y_origin;
- return region_handle;
-}
-
-inline bool to_region_handle(const F32 x_pos, const F32 y_pos, U64 *region_handle)
-{
- U32 x_int, y_int;
- if (x_pos < 0.f)
- {
-// LL_WARNS() << "to_region_handle:Clamping negative x position " << x_pos << " to zero!" << LL_ENDL;
- return false;
- }
- else
- {
- x_int = (U32)ll_round(x_pos);
- }
- if (y_pos < 0.f)
- {
-// LL_WARNS() << "to_region_handle:Clamping negative y position " << y_pos << " to zero!" << LL_ENDL;
- return false;
- }
- else
- {
- y_int = (U32)ll_round(y_pos);
- }
- *region_handle = to_region_handle(x_int, y_int);
- return true;
-}
-
-// stuff the word-frame XY location of sim's SouthWest corner in x_pos, y_pos
-inline void from_region_handle(const U64 &region_handle, F32 *x_pos, F32 *y_pos)
-{
- *x_pos = (F32)((U32)(region_handle >> 32));
- *y_pos = (F32)((U32)(region_handle & 0xFFFFFFFF));
-}
-
-// stuff the word-frame XY location of sim's SouthWest corner in x_pos, y_pos
-inline void from_region_handle(const U64 &region_handle, U32 *x_pos, U32 *y_pos)
-{
- *x_pos = ((U32)(region_handle >> 32));
- *y_pos = ((U32)(region_handle & 0xFFFFFFFF));
-}
-
-// return the word-frame XY location of sim's SouthWest corner in LLVector3d
-inline LLVector3d from_region_handle(const U64 &region_handle)
-{
- return LLVector3d(((U32)(region_handle >> 32)), (U32)(region_handle & 0xFFFFFFFF), 0.f);
-}
-
-// grid-based region handle encoding. pass in a grid position
-// (eg: 1000,1000) and this will return the region handle.
-inline U64 grid_to_region_handle(const U32 grid_x, const U32 grid_y)
-{
- return to_region_handle(grid_x * REGION_WIDTH_UNITS,
- grid_y * REGION_WIDTH_UNITS);
-}
-
-inline void grid_from_region_handle(const U64& region_handle, U32* grid_x, U32* grid_y)
-{
- from_region_handle(region_handle, grid_x, grid_y);
- *grid_x /= REGION_WIDTH_UNITS;
- *grid_y /= REGION_WIDTH_UNITS;
-}
-
-#endif
+/**
+ * @file llregionhandle.h
+ * @brief Routines for converting positions to/from region handles.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLREGIONHANDLE_H
+#define LL_LLREGIONHANDLE_H
+
+#include "indra_constants.h"
+#include "v3math.h"
+#include "v3dmath.h"
+
+inline U64 to_region_handle(const U32 x_origin, const U32 y_origin)
+{
+ U64 region_handle;
+ region_handle = ((U64)x_origin) << 32;
+ region_handle |= (U64) y_origin;
+ return region_handle;
+}
+
+inline U64 to_region_handle(const LLVector3d& pos_global)
+{
+ U32 global_x = (U32)pos_global.mdV[VX];
+ global_x -= global_x % 256;
+
+ U32 global_y = (U32)pos_global.mdV[VY];
+ global_y -= global_y % 256;
+
+ return to_region_handle(global_x, global_y);
+}
+
+inline U64 to_region_handle_global(const F32 x_global, const F32 y_global)
+{
+ // Round down to the nearest origin
+ U32 x_origin = (U32)x_global;
+ x_origin -= x_origin % REGION_WIDTH_U32;
+ U32 y_origin = (U32)y_global;
+ y_origin -= y_origin % REGION_WIDTH_U32;
+ U64 region_handle;
+ region_handle = ((U64)x_origin) << 32;
+ region_handle |= (U64) y_origin;
+ return region_handle;
+}
+
+inline bool to_region_handle(const F32 x_pos, const F32 y_pos, U64 *region_handle)
+{
+ U32 x_int, y_int;
+ if (x_pos < 0.f)
+ {
+// LL_WARNS() << "to_region_handle:Clamping negative x position " << x_pos << " to zero!" << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ x_int = (U32)ll_round(x_pos);
+ }
+ if (y_pos < 0.f)
+ {
+// LL_WARNS() << "to_region_handle:Clamping negative y position " << y_pos << " to zero!" << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ y_int = (U32)ll_round(y_pos);
+ }
+ *region_handle = to_region_handle(x_int, y_int);
+ return true;
+}
+
+// stuff the word-frame XY location of sim's SouthWest corner in x_pos, y_pos
+inline void from_region_handle(const U64 &region_handle, F32 *x_pos, F32 *y_pos)
+{
+ *x_pos = (F32)((U32)(region_handle >> 32));
+ *y_pos = (F32)((U32)(region_handle & 0xFFFFFFFF));
+}
+
+// stuff the word-frame XY location of sim's SouthWest corner in x_pos, y_pos
+inline void from_region_handle(const U64 &region_handle, U32 *x_pos, U32 *y_pos)
+{
+ *x_pos = ((U32)(region_handle >> 32));
+ *y_pos = ((U32)(region_handle & 0xFFFFFFFF));
+}
+
+// return the word-frame XY location of sim's SouthWest corner in LLVector3d
+inline LLVector3d from_region_handle(const U64 &region_handle)
+{
+ return LLVector3d(((U32)(region_handle >> 32)), (U32)(region_handle & 0xFFFFFFFF), 0.f);
+}
+
+// grid-based region handle encoding. pass in a grid position
+// (eg: 1000,1000) and this will return the region handle.
+inline U64 grid_to_region_handle(const U32 grid_x, const U32 grid_y)
+{
+ return to_region_handle(grid_x * REGION_WIDTH_UNITS,
+ grid_y * REGION_WIDTH_UNITS);
+}
+
+inline void grid_from_region_handle(const U64& region_handle, U32* grid_x, U32* grid_y)
+{
+ from_region_handle(region_handle, grid_x, grid_y);
+ *grid_x /= REGION_WIDTH_UNITS;
+ *grid_y /= REGION_WIDTH_UNITS;
+}
+
+#endif
diff --git a/indra/llmessage/llsdappservices.cpp b/indra/llmessage/llsdappservices.cpp
index 4ca45267bd..065bc5196e 100644
--- a/indra/llmessage/llsdappservices.cpp
+++ b/indra/llmessage/llsdappservices.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdappservices.cpp
* @author Phoenix
* @date 2006-09-12
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,244 +34,244 @@
void LLSDAppServices::useServices()
{
- /*
- Having this function body here, causes the classes and globals in this
- file to be linked into any program that uses the llmessage library.
- */
+ /*
+ Having this function body here, causes the classes and globals in this
+ file to be linked into any program that uses the llmessage library.
+ */
}
class LLHTTPConfigService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("GET an array of all the options in priority order.");
- desc.getAPI();
- desc.source(__FILE__, __LINE__);
- }
-
- virtual LLSD simpleGet() const
- {
- LLSD result;
- LLApp* app = LLApp::instance();
- for(int ii = 0; ii < LLApp::PRIORITY_COUNT; ++ii)
- {
- result.append(app->getOptionData((LLApp::OptionPriority)ii));
- }
- return result;
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("GET an array of all the options in priority order.");
+ desc.getAPI();
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual LLSD simpleGet() const
+ {
+ LLSD result;
+ LLApp* app = LLApp::instance();
+ for(int ii = 0; ii < LLApp::PRIORITY_COUNT; ++ii)
+ {
+ result.append(app->getOptionData((LLApp::OptionPriority)ii));
+ }
+ return result;
+ }
};
LLHTTPRegistration<LLHTTPConfigService>
- gHTTPRegistratiAppConfig("/app/config");
+ gHTTPRegistratiAppConfig("/app/config");
class LLHTTPConfigRuntimeService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("Manipulate a map of runtime-override options.");
- desc.getAPI();
- desc.postAPI();
- desc.source(__FILE__, __LINE__);
- }
-
- virtual LLSD simpleGet() const
- {
- return LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("Manipulate a map of runtime-override options.");
+ desc.getAPI();
+ desc.postAPI();
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual LLSD simpleGet() const
+ {
+ return LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ }
- virtual void post(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context,
- const LLSD& input) const
- {
- LLSD result = LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- LLSD::map_const_iterator iter = input.beginMap();
- LLSD::map_const_iterator end = input.endMap();
- for(; iter != end; ++iter)
- {
- result[(*iter).first] = (*iter).second;
- }
- LLApp::instance()->setOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE,
- result);
- response->result(result);
- }
+ virtual void post(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ LLSD result = LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ LLSD::map_const_iterator iter = input.beginMap();
+ LLSD::map_const_iterator end = input.endMap();
+ for(; iter != end; ++iter)
+ {
+ result[(*iter).first] = (*iter).second;
+ }
+ LLApp::instance()->setOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE,
+ result);
+ response->result(result);
+ }
};
LLHTTPRegistration<LLHTTPConfigRuntimeService>
- gHTTPRegistrationRuntimeConfig("/app/config/runtime-override");
+ gHTTPRegistrationRuntimeConfig("/app/config/runtime-override");
class LLHTTPConfigRuntimeSingleService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("Manipulate a single runtime-override option.");
- desc.getAPI();
- desc.putAPI();
- desc.delAPI();
- desc.source(__FILE__, __LINE__);
- }
-
- virtual bool validate(const std::string& name, LLSD& context) const
- {
- //LL_INFOS() << "validate: " << name << ", "
- // << LLSDOStreamer<LLSDNotationFormatter>(context) << LL_ENDL;
- if((std::string("PUT") == context[CONTEXT_REQUEST][CONTEXT_VERB].asString()) && !name.empty())
- {
- return true;
- }
- else
- {
- // This is for GET and DELETE
- LLSD options = LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- if(options.has(name)) return true;
- else return false;
- }
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("Manipulate a single runtime-override option.");
+ desc.getAPI();
+ desc.putAPI();
+ desc.delAPI();
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual bool validate(const std::string& name, LLSD& context) const
+ {
+ //LL_INFOS() << "validate: " << name << ", "
+ // << LLSDOStreamer<LLSDNotationFormatter>(context) << LL_ENDL;
+ if((std::string("PUT") == context[CONTEXT_REQUEST][CONTEXT_VERB].asString()) && !name.empty())
+ {
+ return true;
+ }
+ else
+ {
+ // This is for GET and DELETE
+ LLSD options = LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ if(options.has(name)) return true;
+ else return false;
+ }
+ }
- virtual void get(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context) const
- {
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
- LLSD options = LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- response->result(options[name]);
- }
+ virtual void get(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context) const
+ {
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
+ LLSD options = LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ response->result(options[name]);
+ }
- virtual void put(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context,
- const LLSD& input) const
- {
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
- LLSD options = LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- options[name] = input;
- LLApp::instance()->setOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE,
- options);
- response->result(input);
- }
+ virtual void put(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
+ LLSD options = LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ options[name] = input;
+ LLApp::instance()->setOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE,
+ options);
+ response->result(input);
+ }
- virtual void del(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context) const
- {
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
- LLSD options = LLApp::instance()->getOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE);
- options.erase(name);
- LLApp::instance()->setOptionData(
- LLApp::PRIORITY_RUNTIME_OVERRIDE,
- options);
- response->result(LLSD());
- }
+ virtual void del(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context) const
+ {
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
+ LLSD options = LLApp::instance()->getOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE);
+ options.erase(name);
+ LLApp::instance()->setOptionData(
+ LLApp::PRIORITY_RUNTIME_OVERRIDE,
+ options);
+ response->result(LLSD());
+ }
};
LLHTTPRegistration<LLHTTPConfigRuntimeSingleService>
- gHTTPRegistrationRuntimeSingleConfig(
- "/app/config/runtime-override/<option-name>");
+ gHTTPRegistrationRuntimeSingleConfig(
+ "/app/config/runtime-override/<option-name>");
template<int PRIORITY>
class LLHTTPConfigPriorityService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("Get a map of the options at this priority.");
- desc.getAPI();
- desc.source(__FILE__, __LINE__);
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("Get a map of the options at this priority.");
+ desc.getAPI();
+ desc.source(__FILE__, __LINE__);
+ }
- virtual void get(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context) const
- {
- response->result(LLApp::instance()->getOptionData(
- (LLApp::OptionPriority)PRIORITY));
- }
+ virtual void get(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context) const
+ {
+ response->result(LLApp::instance()->getOptionData(
+ (LLApp::OptionPriority)PRIORITY));
+ }
};
LLHTTPRegistration< LLHTTPConfigPriorityService<LLApp::PRIORITY_COMMAND_LINE> >
- gHTTPRegistrationCommandLineConfig("/app/config/command-line");
+ gHTTPRegistrationCommandLineConfig("/app/config/command-line");
LLHTTPRegistration<
- LLHTTPConfigPriorityService<LLApp::PRIORITY_SPECIFIC_CONFIGURATION> >
- gHTTPRegistrationSpecificConfig("/app/config/specific");
+ LLHTTPConfigPriorityService<LLApp::PRIORITY_SPECIFIC_CONFIGURATION> >
+ gHTTPRegistrationSpecificConfig("/app/config/specific");
LLHTTPRegistration<
- LLHTTPConfigPriorityService<LLApp::PRIORITY_GENERAL_CONFIGURATION> >
- gHTTPRegistrationGeneralConfig("/app/config/general");
+ LLHTTPConfigPriorityService<LLApp::PRIORITY_GENERAL_CONFIGURATION> >
+ gHTTPRegistrationGeneralConfig("/app/config/general");
LLHTTPRegistration< LLHTTPConfigPriorityService<LLApp::PRIORITY_DEFAULT> >
- gHTTPRegistrationDefaultConfig("/app/config/default");
+ gHTTPRegistrationDefaultConfig("/app/config/default");
class LLHTTPLiveConfigService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("Get a map of the currently live options.");
- desc.getAPI();
- desc.source(__FILE__, __LINE__);
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("Get a map of the currently live options.");
+ desc.getAPI();
+ desc.source(__FILE__, __LINE__);
+ }
- virtual void get(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context) const
- {
- LLSD result;
- LLApp* app = LLApp::instance();
- LLSD::map_const_iterator iter;
- LLSD::map_const_iterator end;
- for(int ii = LLApp::PRIORITY_COUNT - 1; ii >= 0; --ii)
- {
- LLSD options = app->getOptionData((LLApp::OptionPriority)ii);
- iter = options.beginMap();
- end = options.endMap();
- for(; iter != end; ++iter)
- {
- result[(*iter).first] = (*iter).second;
- }
- }
- response->result(result);
- }
+ virtual void get(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context) const
+ {
+ LLSD result;
+ LLApp* app = LLApp::instance();
+ LLSD::map_const_iterator iter;
+ LLSD::map_const_iterator end;
+ for(int ii = LLApp::PRIORITY_COUNT - 1; ii >= 0; --ii)
+ {
+ LLSD options = app->getOptionData((LLApp::OptionPriority)ii);
+ iter = options.beginMap();
+ end = options.endMap();
+ for(; iter != end; ++iter)
+ {
+ result[(*iter).first] = (*iter).second;
+ }
+ }
+ response->result(result);
+ }
};
LLHTTPRegistration<LLHTTPLiveConfigService>
- gHTTPRegistrationLiveConfig("/app/config/live");
+ gHTTPRegistrationLiveConfig("/app/config/live");
class LLHTTPLiveConfigSingleService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("Get the named live option.");
- desc.getAPI();
- desc.source(__FILE__, __LINE__);
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("Get the named live option.");
+ desc.getAPI();
+ desc.source(__FILE__, __LINE__);
+ }
- virtual bool validate(const std::string& name, LLSD& context) const
- {
- LL_INFOS() << "LLHTTPLiveConfigSingleService::validate(" << name
- << ")" << LL_ENDL;
- LLSD option = LLApp::instance()->getOption(name);
- if(option.isDefined()) return true;
- else return false;
- }
+ virtual bool validate(const std::string& name, LLSD& context) const
+ {
+ LL_INFOS() << "LLHTTPLiveConfigSingleService::validate(" << name
+ << ")" << LL_ENDL;
+ LLSD option = LLApp::instance()->getOption(name);
+ if(option.isDefined()) return true;
+ else return false;
+ }
- virtual void get(
- LLHTTPNode::ResponsePtr response,
- const LLSD& context) const
- {
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
- response->result(LLApp::instance()->getOption(name));
- }
+ virtual void get(
+ LLHTTPNode::ResponsePtr response,
+ const LLSD& context) const
+ {
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["option-name"];
+ response->result(LLApp::instance()->getOption(name));
+ }
};
LLHTTPRegistration<LLHTTPLiveConfigSingleService>
- gHTTPRegistrationLiveSingleConfig("/app/config/live/<option-name>");
+ gHTTPRegistrationLiveSingleConfig("/app/config/live/<option-name>");
diff --git a/indra/llmessage/llsdappservices.h b/indra/llmessage/llsdappservices.h
index e76e20cea9..6b3b7c0da3 100644
--- a/indra/llmessage/llsdappservices.h
+++ b/indra/llmessage/llsdappservices.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llsdappservices.h
* @author Phoenix
* @date 2006-09-12
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,7 +29,7 @@
#ifndef LL_LLSDAPPSERVICES_H
#define LL_LLSDAPPSERVICES_H
-/**
+/**
* @class LLSDAppServices
* @brief This class forces a link to llsdappservices if the static
* method is called which declares the /app web services.
@@ -37,21 +37,21 @@
class LLSDAppServices
{
public:
- /**
- * @brief Call this method to declare the /app common web services.
- *
- * This will register:
- * /app/config
- * /app/config/runtime-override
- * /app/config/runtime-override/<option-name>
- * /app/config/command-line
- * /app/config/specific
- * /app/config/general
- * /app/config/default
- * /app/config/live
- * /app/config/live/<option-name>
- */
- static void useServices();
+ /**
+ * @brief Call this method to declare the /app common web services.
+ *
+ * This will register:
+ * /app/config
+ * /app/config/runtime-override
+ * /app/config/runtime-override/<option-name>
+ * /app/config/command-line
+ * /app/config/specific
+ * /app/config/general
+ * /app/config/default
+ * /app/config/live
+ * /app/config/live/<option-name>
+ */
+ static void useServices();
};
diff --git a/indra/llmessage/llsdhttpserver.cpp b/indra/llmessage/llsdhttpserver.cpp
index 8ac6b3cb12..35f3a45ed6 100644
--- a/indra/llmessage/llsdhttpserver.cpp
+++ b/indra/llmessage/llsdhttpserver.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdhttpserver.cpp
* @brief Standard LLSD services
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,7 +29,7 @@
#include "llhttpnode.h"
-/**
+/**
* This module implements common services that should be included
* in all server URL trees. These services facilitate debugging and
* introsepction.
@@ -37,10 +37,10 @@
void LLHTTPStandardServices::useServices()
{
- /*
- Having this function body here, causes the classes and globals in this
- file to be linked into any program that uses the llmessage library.
- */
+ /*
+ Having this function body here, causes the classes and globals in this
+ file to be linked into any program that uses the llmessage library.
+ */
}
@@ -48,103 +48,103 @@ void LLHTTPStandardServices::useServices()
class LLHTTPHelloService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("says hello");
- desc.getAPI();
- desc.output("\"hello\"");
- desc.source(__FILE__, __LINE__);
- }
-
- virtual LLSD simpleGet() const
- {
- LLSD result = "hello";
- return result;
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("says hello");
+ desc.getAPI();
+ desc.output("\"hello\"");
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual LLSD simpleGet() const
+ {
+ LLSD result = "hello";
+ return result;
+ }
};
LLHTTPRegistration<LLHTTPHelloService>
- gHTTPRegistrationWebHello("/web/hello");
+ gHTTPRegistrationWebHello("/web/hello");
class LLHTTPEchoService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("echo input");
- desc.postAPI();
- desc.input("<any>");
- desc.output("<the input>");
- desc.source(__FILE__, __LINE__);
- }
-
- virtual LLSD simplePost(const LLSD& params) const
- {
- return params;
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("echo input");
+ desc.postAPI();
+ desc.input("<any>");
+ desc.output("<the input>");
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual LLSD simplePost(const LLSD& params) const
+ {
+ return params;
+ }
};
LLHTTPRegistration<LLHTTPEchoService>
- gHTTPRegistrationWebEcho("/web/echo");
+ gHTTPRegistrationWebEcho("/web/echo");
class LLAPIService : public LLHTTPNode
{
public:
- virtual void describe(Description& desc) const
- {
- desc.shortInfo("information about the URLs this server supports");
- desc.getAPI();
- desc.output("a list of URLs supported");
- desc.source(__FILE__, __LINE__);
- }
-
- virtual bool handles(const LLSD& remainder, LLSD& context) const
- {
- return followRemainder(remainder) != NULL;
- }
+ virtual void describe(Description& desc) const
+ {
+ desc.shortInfo("information about the URLs this server supports");
+ desc.getAPI();
+ desc.output("a list of URLs supported");
+ desc.source(__FILE__, __LINE__);
+ }
+
+ virtual bool handles(const LLSD& remainder, LLSD& context) const
+ {
+ return followRemainder(remainder) != NULL;
+ }
virtual void get(ResponsePtr response, const LLSD& context) const
- {
- const LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
-
- if (remainder.size() > 0)
- {
- const LLHTTPNode* node = followRemainder(remainder);
- if (!node)
- {
- response->notFound();
- return;
- }
-
- Description desc;
- node->describe(desc);
- response->result(desc.getInfo());
- return;
- }
-
- response->result(rootNode()->allNodePaths());
- }
+ {
+ const LLSD& remainder = context[CONTEXT_REQUEST]["remainder"];
+
+ if (remainder.size() > 0)
+ {
+ const LLHTTPNode* node = followRemainder(remainder);
+ if (!node)
+ {
+ response->notFound();
+ return;
+ }
+
+ Description desc;
+ node->describe(desc);
+ response->result(desc.getInfo());
+ return;
+ }
+
+ response->result(rootNode()->allNodePaths());
+ }
private:
- const LLHTTPNode* followRemainder(const LLSD& remainder) const
- {
- const LLHTTPNode* node = rootNode();
-
- LLSD::array_const_iterator i = remainder.beginArray();
- LLSD::array_const_iterator end = remainder.endArray();
- for (; node && i != end; ++i)
- {
- node = node->findNode(*i);
- }
-
- return node;
- }
+ const LLHTTPNode* followRemainder(const LLSD& remainder) const
+ {
+ const LLHTTPNode* node = rootNode();
+
+ LLSD::array_const_iterator i = remainder.beginArray();
+ LLSD::array_const_iterator end = remainder.endArray();
+ for (; node && i != end; ++i)
+ {
+ node = node->findNode(*i);
+ }
+
+ return node;
+ }
};
LLHTTPRegistration<LLAPIService>
- gHTTPRegistrationWebServerApi("/web/server/api");
+ gHTTPRegistrationWebServerApi("/web/server/api");
diff --git a/indra/llmessage/llsdhttpserver.h b/indra/llmessage/llsdhttpserver.h
index 39f9204604..5d748ec73c 100644
--- a/indra/llmessage/llsdhttpserver.h
+++ b/indra/llmessage/llsdhttpserver.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsdhttpserver.h
* @brief Standard LLSD services
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -27,7 +27,7 @@
#ifndef LL_LLSDHTTPSERVER_H
#define LL_LLSDHTTPSERVER_H
-/**
+/**
* This module implements and defines common services that should be included
* in all server URL trees. These services facilitate debugging and
* introsepction.
@@ -36,16 +36,16 @@
class LLHTTPStandardServices
{
public:
- static void useServices();
- /**<
- Having a call to this function causes the following services to be
- registered:
- /web/echo -- echo input
- /web/hello -- return "hello"
- /web/server/api -- return a list of url paths on the server
- /web/server/api/<..path..>
- -- return description of the path
- */
+ static void useServices();
+ /**<
+ Having a call to this function causes the following services to be
+ registered:
+ /web/echo -- echo input
+ /web/hello -- return "hello"
+ /web/server/api -- return a list of url paths on the server
+ /web/server/api/<..path..>
+ -- return description of the path
+ */
};
#endif // LL_LLSDHTTPSERVER_H
diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp
index 309cf53bef..3f4553fcee 100644
--- a/indra/llmessage/llsdmessagebuilder.cpp
+++ b/indra/llmessage/llsdmessagebuilder.cpp
@@ -1,424 +1,424 @@
-/**
- * @file llsdmessagebuilder.cpp
- * @brief LLSDMessageBuilder class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llsdmessagebuilder.h"
-
-#include "llmessagetemplate.h"
-#include "llmath.h"
-#include "llquaternion.h"
-#include "llsdutil.h"
-#include "llsdutil_math.h"
-#include "llsdserialize.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-
-LLSDMessageBuilder::LLSDMessageBuilder() :
- mCurrentMessage(LLSD::emptyMap()),
- mCurrentBlock(NULL),
- mCurrentMessageName(""),
- mCurrentBlockName(""),
- mbSBuilt(false),
- mbSClear(true)
-{
-}
-
-//virtual
-LLSDMessageBuilder::~LLSDMessageBuilder()
-{
-}
-
-
-// virtual
-void LLSDMessageBuilder::newMessage(const char* name)
-{
- mbSBuilt = false;
- mbSClear = false;
-
- mCurrentMessage = LLSD::emptyMap();
- mCurrentMessageName = (char*)name;
-}
-
-// virtual
-void LLSDMessageBuilder::clearMessage()
-{
- mbSBuilt = false;
- mbSClear = true;
-
- mCurrentMessage = LLSD::emptyMap();
- mCurrentMessageName = "";
-}
-
-// virtual
-void LLSDMessageBuilder::nextBlock(const char* blockname)
-{
- LLSD& block = mCurrentMessage[blockname];
- if(block.isUndefined())
- {
- block[0] = LLSD::emptyMap();
- mCurrentBlock = &(block[0]);
- }
- else if(block.isArray())
- {
- block[block.size()] = LLSD::emptyMap();
- mCurrentBlock = &(block[block.size() - 1]);
- }
- else
- {
- LL_ERRS() << "existing block not array" << LL_ENDL;
- }
-}
-
-// TODO: Remove this horror...
-bool LLSDMessageBuilder::removeLastBlock()
-{
- /* TODO: finish implementing this */
- return false;
-}
-
-void LLSDMessageBuilder::addBinaryData(
- const char* varname,
- const void* data,
- S32 size)
-{
- std::vector<U8> v;
- v.resize(size);
- memcpy(&(v[0]), reinterpret_cast<const U8*>(data), size);
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addS8(const char* varname, S8 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addU8(const char* varname, U8 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addS16(const char* varname, S16 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addU16(const char* varname, U16 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addF32(const char* varname, F32 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addS32(const char* varname, S32 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addU32(const char* varname, U32 v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_U32(v);
-}
-
-void LLSDMessageBuilder::addU64(const char* varname, U64 v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_U64(v);
-}
-
-void LLSDMessageBuilder::addF64(const char* varname, F64 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addIPAddr(const char* varname, U32 v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_ipaddr(v);
-}
-
-void LLSDMessageBuilder::addIPPort(const char* varname, U16 v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addBOOL(const char* varname, bool v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::addString(const char* varname, const char* v)
-{
- if (v)
- (*mCurrentBlock)[varname] = v; /* Flawfinder: ignore */
- else
- (*mCurrentBlock)[varname] = "";
-}
-
-void LLSDMessageBuilder::addString(const char* varname, const std::string& v)
-{
- if (v.size())
- (*mCurrentBlock)[varname] = v;
- else
- (*mCurrentBlock)[varname] = "";
-}
-
-void LLSDMessageBuilder::addVector3(const char* varname, const LLVector3& v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_vector3(v);
-}
-
-void LLSDMessageBuilder::addVector4(const char* varname, const LLVector4& v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_vector4(v);
-}
-
-void LLSDMessageBuilder::addVector3d(const char* varname, const LLVector3d& v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_vector3d(v);
-}
-
-void LLSDMessageBuilder::addQuat(const char* varname, const LLQuaternion& v)
-{
- (*mCurrentBlock)[varname] = ll_sd_from_quaternion(v);
-}
-
-void LLSDMessageBuilder::addUUID(const char* varname, const LLUUID& v)
-{
- (*mCurrentBlock)[varname] = v;
-}
-
-void LLSDMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
-{
-}
-
-bool LLSDMessageBuilder::isMessageFull(const char* blockname) const
-{
- return false;
-}
-
-U32 LLSDMessageBuilder::buildMessage(U8*, U32, U8)
-{
- return 0;
-}
-
-void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
-{
- // copy the blocks
- // counting variables used to encode multiple block info
- S32 block_count = 0;
- char* block_name = NULL;
-
- // loop through msg blocks to loop through variables, totalling up size
- // data and filling the new (send) message
- LLMsgData::msg_blk_data_map_t::const_iterator iter =
- data.mMemberBlocks.begin();
- LLMsgData::msg_blk_data_map_t::const_iterator end =
- data.mMemberBlocks.end();
- for(; iter != end; ++iter)
- {
- const LLMsgBlkData* mbci = iter->second;
- if(!mbci) continue;
-
- // do we need to encode a block code?
- if (block_count == 0)
- {
- block_count = mbci->mBlockNumber;
- block_name = (char*)mbci->mName;
- }
-
- // counting down mutliple blocks
- block_count--;
-
- nextBlock(block_name);
-
- // now loop through the variables
- LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
- LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
-
- for(; dit != dend; ++dit)
- {
- const LLMsgVarData& mvci = *dit;
- const char* varname = mvci.getName();
-
- switch(mvci.getType())
- {
- case MVT_FIXED:
- addBinaryData(varname, mvci.getData(), mvci.getSize());
- break;
-
- case MVT_VARIABLE:
- {
- const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated
- if (mvci.getDataSize() == 1 && end == 0)
- {
- addString(varname, (const char*)mvci.getData());
- }
- else
- {
- addBinaryData(varname, mvci.getData(), mvci.getSize());
- }
- break;
- }
-
- case MVT_U8:
- addU8(varname, *(U8*)mvci.getData());
- break;
-
- case MVT_U16:
- addU16(varname, *(U16*)mvci.getData());
- break;
-
- case MVT_U32:
- addU32(varname, *(U32*)mvci.getData());
- break;
-
- case MVT_U64:
- addU64(varname, *(U64*)mvci.getData());
- break;
-
- case MVT_S8:
- addS8(varname, *(S8*)mvci.getData());
- break;
-
- case MVT_S16:
- addS16(varname, *(S16*)mvci.getData());
- break;
-
- case MVT_S32:
- addS32(varname, *(S32*)mvci.getData());
- break;
-
- // S64 not supported in LLSD so we just truncate it
- case MVT_S64:
- addS32(varname, (S32)*(S64*)mvci.getData());
- break;
-
- case MVT_F32:
- addF32(varname, *(F32*)mvci.getData());
- break;
-
- case MVT_F64:
- addF64(varname, *(F64*)mvci.getData());
- break;
-
- case MVT_LLVector3:
- addVector3(varname, *(LLVector3*)mvci.getData());
- break;
-
- case MVT_LLVector3d:
- addVector3d(varname, *(LLVector3d*)mvci.getData());
- break;
-
- case MVT_LLVector4:
- addVector4(varname, *(LLVector4*)mvci.getData());
- break;
-
- case MVT_LLQuaternion:
- {
- LLVector3 v = *(LLVector3*)mvci.getData();
- LLQuaternion q;
- q.unpackFromVector3(v);
- addQuat(varname, q);
- break;
- }
-
- case MVT_LLUUID:
- addUUID(varname, *(LLUUID*)mvci.getData());
- break;
-
- case MVT_BOOL:
- addBOOL(varname, *(bool*)mvci.getData());
- break;
-
- case MVT_IP_ADDR:
- addIPAddr(varname, *(U32*)mvci.getData());
- break;
-
- case MVT_IP_PORT:
- addIPPort(varname, *(U16*)mvci.getData());
- break;
-
- case MVT_U16Vec3:
- //treated as an array of 6 bytes
- addBinaryData(varname, mvci.getData(), 6);
- break;
-
- case MVT_U16Quat:
- //treated as an array of 8 bytes
- addBinaryData(varname, mvci.getData(), 8);
- break;
-
- case MVT_S16Array:
- addBinaryData(varname, mvci.getData(), mvci.getSize());
- break;
-
- default:
- LL_WARNS() << "Unknown type in conversion of message to LLSD" << LL_ENDL;
- break;
- }
- }
- }
-}
-
-//virtual
-void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg)
-{
- mCurrentMessage = msg;
- LL_DEBUGS() << LLSDNotationStreamer(mCurrentMessage) << LL_ENDL;
-}
-
-const LLSD& LLSDMessageBuilder::getMessage() const
-{
- return mCurrentMessage;
-}
-
-//virtual
-void LLSDMessageBuilder::setBuilt(bool b) { mbSBuilt = b; }
-
-//virtual
-bool LLSDMessageBuilder::isBuilt() const {return mbSBuilt;}
-
-//virtual
-bool LLSDMessageBuilder::isClear() const {return mbSClear;}
-
-//virtual
-S32 LLSDMessageBuilder::getMessageSize()
-{
- // babbage: size is unknown as message stored as LLSD.
- // return non-zero if pending data, as send can be skipped for 0 size.
- // return 1 to encourage senders checking size against splitting message.
- return mCurrentMessage.size()? 1 : 0;
-}
-
-//virtual
-const char* LLSDMessageBuilder::getMessageName() const
-{
- return mCurrentMessageName.c_str();
-}
+/**
+ * @file llsdmessagebuilder.cpp
+ * @brief LLSDMessageBuilder class implementation.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsdmessagebuilder.h"
+
+#include "llmessagetemplate.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "llsdserialize.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLSDMessageBuilder::LLSDMessageBuilder() :
+ mCurrentMessage(LLSD::emptyMap()),
+ mCurrentBlock(NULL),
+ mCurrentMessageName(""),
+ mCurrentBlockName(""),
+ mbSBuilt(false),
+ mbSClear(true)
+{
+}
+
+//virtual
+LLSDMessageBuilder::~LLSDMessageBuilder()
+{
+}
+
+
+// virtual
+void LLSDMessageBuilder::newMessage(const char* name)
+{
+ mbSBuilt = false;
+ mbSClear = false;
+
+ mCurrentMessage = LLSD::emptyMap();
+ mCurrentMessageName = (char*)name;
+}
+
+// virtual
+void LLSDMessageBuilder::clearMessage()
+{
+ mbSBuilt = false;
+ mbSClear = true;
+
+ mCurrentMessage = LLSD::emptyMap();
+ mCurrentMessageName = "";
+}
+
+// virtual
+void LLSDMessageBuilder::nextBlock(const char* blockname)
+{
+ LLSD& block = mCurrentMessage[blockname];
+ if(block.isUndefined())
+ {
+ block[0] = LLSD::emptyMap();
+ mCurrentBlock = &(block[0]);
+ }
+ else if(block.isArray())
+ {
+ block[block.size()] = LLSD::emptyMap();
+ mCurrentBlock = &(block[block.size() - 1]);
+ }
+ else
+ {
+ LL_ERRS() << "existing block not array" << LL_ENDL;
+ }
+}
+
+// TODO: Remove this horror...
+bool LLSDMessageBuilder::removeLastBlock()
+{
+ /* TODO: finish implementing this */
+ return false;
+}
+
+void LLSDMessageBuilder::addBinaryData(
+ const char* varname,
+ const void* data,
+ S32 size)
+{
+ std::vector<U8> v;
+ v.resize(size);
+ memcpy(&(v[0]), reinterpret_cast<const U8*>(data), size);
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS8(const char* varname, S8 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU8(const char* varname, U8 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS16(const char* varname, S16 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU16(const char* varname, U16 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addF32(const char* varname, F32 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addS32(const char* varname, S32 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addU32(const char* varname, U32 v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_U32(v);
+}
+
+void LLSDMessageBuilder::addU64(const char* varname, U64 v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_U64(v);
+}
+
+void LLSDMessageBuilder::addF64(const char* varname, F64 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addIPAddr(const char* varname, U32 v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_ipaddr(v);
+}
+
+void LLSDMessageBuilder::addIPPort(const char* varname, U16 v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addBOOL(const char* varname, bool v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::addString(const char* varname, const char* v)
+{
+ if (v)
+ (*mCurrentBlock)[varname] = v; /* Flawfinder: ignore */
+ else
+ (*mCurrentBlock)[varname] = "";
+}
+
+void LLSDMessageBuilder::addString(const char* varname, const std::string& v)
+{
+ if (v.size())
+ (*mCurrentBlock)[varname] = v;
+ else
+ (*mCurrentBlock)[varname] = "";
+}
+
+void LLSDMessageBuilder::addVector3(const char* varname, const LLVector3& v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_vector3(v);
+}
+
+void LLSDMessageBuilder::addVector4(const char* varname, const LLVector4& v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_vector4(v);
+}
+
+void LLSDMessageBuilder::addVector3d(const char* varname, const LLVector3d& v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_vector3d(v);
+}
+
+void LLSDMessageBuilder::addQuat(const char* varname, const LLQuaternion& v)
+{
+ (*mCurrentBlock)[varname] = ll_sd_from_quaternion(v);
+}
+
+void LLSDMessageBuilder::addUUID(const char* varname, const LLUUID& v)
+{
+ (*mCurrentBlock)[varname] = v;
+}
+
+void LLSDMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
+{
+}
+
+bool LLSDMessageBuilder::isMessageFull(const char* blockname) const
+{
+ return false;
+}
+
+U32 LLSDMessageBuilder::buildMessage(U8*, U32, U8)
+{
+ return 0;
+}
+
+void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)
+{
+ // copy the blocks
+ // counting variables used to encode multiple block info
+ S32 block_count = 0;
+ char* block_name = NULL;
+
+ // loop through msg blocks to loop through variables, totalling up size
+ // data and filling the new (send) message
+ LLMsgData::msg_blk_data_map_t::const_iterator iter =
+ data.mMemberBlocks.begin();
+ LLMsgData::msg_blk_data_map_t::const_iterator end =
+ data.mMemberBlocks.end();
+ for(; iter != end; ++iter)
+ {
+ const LLMsgBlkData* mbci = iter->second;
+ if(!mbci) continue;
+
+ // do we need to encode a block code?
+ if (block_count == 0)
+ {
+ block_count = mbci->mBlockNumber;
+ block_name = (char*)mbci->mName;
+ }
+
+ // counting down mutliple blocks
+ block_count--;
+
+ nextBlock(block_name);
+
+ // now loop through the variables
+ LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
+ LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
+
+ for(; dit != dend; ++dit)
+ {
+ const LLMsgVarData& mvci = *dit;
+ const char* varname = mvci.getName();
+
+ switch(mvci.getType())
+ {
+ case MVT_FIXED:
+ addBinaryData(varname, mvci.getData(), mvci.getSize());
+ break;
+
+ case MVT_VARIABLE:
+ {
+ const char end = ((const char*)mvci.getData())[mvci.getSize()-1]; // Ensure null terminated
+ if (mvci.getDataSize() == 1 && end == 0)
+ {
+ addString(varname, (const char*)mvci.getData());
+ }
+ else
+ {
+ addBinaryData(varname, mvci.getData(), mvci.getSize());
+ }
+ break;
+ }
+
+ case MVT_U8:
+ addU8(varname, *(U8*)mvci.getData());
+ break;
+
+ case MVT_U16:
+ addU16(varname, *(U16*)mvci.getData());
+ break;
+
+ case MVT_U32:
+ addU32(varname, *(U32*)mvci.getData());
+ break;
+
+ case MVT_U64:
+ addU64(varname, *(U64*)mvci.getData());
+ break;
+
+ case MVT_S8:
+ addS8(varname, *(S8*)mvci.getData());
+ break;
+
+ case MVT_S16:
+ addS16(varname, *(S16*)mvci.getData());
+ break;
+
+ case MVT_S32:
+ addS32(varname, *(S32*)mvci.getData());
+ break;
+
+ // S64 not supported in LLSD so we just truncate it
+ case MVT_S64:
+ addS32(varname, (S32)*(S64*)mvci.getData());
+ break;
+
+ case MVT_F32:
+ addF32(varname, *(F32*)mvci.getData());
+ break;
+
+ case MVT_F64:
+ addF64(varname, *(F64*)mvci.getData());
+ break;
+
+ case MVT_LLVector3:
+ addVector3(varname, *(LLVector3*)mvci.getData());
+ break;
+
+ case MVT_LLVector3d:
+ addVector3d(varname, *(LLVector3d*)mvci.getData());
+ break;
+
+ case MVT_LLVector4:
+ addVector4(varname, *(LLVector4*)mvci.getData());
+ break;
+
+ case MVT_LLQuaternion:
+ {
+ LLVector3 v = *(LLVector3*)mvci.getData();
+ LLQuaternion q;
+ q.unpackFromVector3(v);
+ addQuat(varname, q);
+ break;
+ }
+
+ case MVT_LLUUID:
+ addUUID(varname, *(LLUUID*)mvci.getData());
+ break;
+
+ case MVT_BOOL:
+ addBOOL(varname, *(bool*)mvci.getData());
+ break;
+
+ case MVT_IP_ADDR:
+ addIPAddr(varname, *(U32*)mvci.getData());
+ break;
+
+ case MVT_IP_PORT:
+ addIPPort(varname, *(U16*)mvci.getData());
+ break;
+
+ case MVT_U16Vec3:
+ //treated as an array of 6 bytes
+ addBinaryData(varname, mvci.getData(), 6);
+ break;
+
+ case MVT_U16Quat:
+ //treated as an array of 8 bytes
+ addBinaryData(varname, mvci.getData(), 8);
+ break;
+
+ case MVT_S16Array:
+ addBinaryData(varname, mvci.getData(), mvci.getSize());
+ break;
+
+ default:
+ LL_WARNS() << "Unknown type in conversion of message to LLSD" << LL_ENDL;
+ break;
+ }
+ }
+ }
+}
+
+//virtual
+void LLSDMessageBuilder::copyFromLLSD(const LLSD& msg)
+{
+ mCurrentMessage = msg;
+ LL_DEBUGS() << LLSDNotationStreamer(mCurrentMessage) << LL_ENDL;
+}
+
+const LLSD& LLSDMessageBuilder::getMessage() const
+{
+ return mCurrentMessage;
+}
+
+//virtual
+void LLSDMessageBuilder::setBuilt(bool b) { mbSBuilt = b; }
+
+//virtual
+bool LLSDMessageBuilder::isBuilt() const {return mbSBuilt;}
+
+//virtual
+bool LLSDMessageBuilder::isClear() const {return mbSClear;}
+
+//virtual
+S32 LLSDMessageBuilder::getMessageSize()
+{
+ // babbage: size is unknown as message stored as LLSD.
+ // return non-zero if pending data, as send can be skipped for 0 size.
+ // return 1 to encourage senders checking size against splitting message.
+ return mCurrentMessage.size()? 1 : 0;
+}
+
+//virtual
+const char* LLSDMessageBuilder::getMessageName() const
+{
+ return mCurrentMessageName.c_str();
+}
diff --git a/indra/llmessage/llsdmessagebuilder.h b/indra/llmessage/llsdmessagebuilder.h
index 2c728977ca..8eac962ba0 100644
--- a/indra/llmessage/llsdmessagebuilder.h
+++ b/indra/llmessage/llsdmessagebuilder.h
@@ -1,126 +1,126 @@
-/**
- * @file llsdmessagebuilder.h
- * @brief Declaration of LLSDMessageBuilder class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSDMESSAGEBUILDER_H
-#define LL_LLSDMESSAGEBUILDER_H
-
-#include <map>
-
-#include "llmessagebuilder.h"
-#include "llmsgvariabletype.h"
-#include "llsd.h"
-
-class LLMessageTemplate;
-class LLMsgData;
-
-class LLSDMessageBuilder : public LLMessageBuilder
-{
-public:
-
- //CLASS_LOG_TYPE(LLSDMessageBuilder);
-
- LLSDMessageBuilder();
- virtual ~LLSDMessageBuilder();
-
- virtual void newMessage(const char* name);
-
- virtual void nextBlock(const char* blockname);
- virtual bool removeLastBlock(); // TODO: babbage: remove this horror...
-
- /** All add* methods expect pointers to canonical varname strings. */
- virtual void addBinaryData(
- const char* varname,
- const void* data,
- S32 size);
- virtual void addBOOL(const char* varname, bool b);
- virtual void addS8(const char* varname, S8 s);
- virtual void addU8(const char* varname, U8 u);
- virtual void addS16(const char* varname, S16 i);
- virtual void addU16(const char* varname, U16 i);
- virtual void addF32(const char* varname, F32 f);
- virtual void addS32(const char* varname, S32 s);
- virtual void addU32(const char* varname, U32 u);
- virtual void addU64(const char* varname, U64 lu);
- virtual void addF64(const char* varname, F64 d);
- virtual void addVector3(const char* varname, const LLVector3& vec);
- virtual void addVector4(const char* varname, const LLVector4& vec);
- virtual void addVector3d(const char* varname, const LLVector3d& vec);
- virtual void addQuat(const char* varname, const LLQuaternion& quat);
- virtual void addUUID(const char* varname, const LLUUID& uuid);
- virtual void addIPAddr(const char* varname, const U32 ip);
- virtual void addIPPort(const char* varname, const U16 port);
- virtual void addString(const char* varname, const char* s);
- virtual void addString(const char* varname, const std::string& s);
-
- virtual bool isMessageFull(const char* blockname) const;
- virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
-
- virtual bool isBuilt() const;
- virtual bool isClear() const;
- virtual U32 buildMessage(U8* buffer, U32 buffer_size, U8 offset_to_data);
- /**< Null implementation which returns 0. */
-
- virtual void clearMessage();
-
- // TODO: babbage: remove this horror.
- virtual void setBuilt(bool b);
-
- virtual S32 getMessageSize();
- virtual const char* getMessageName() const;
-
- virtual void copyFromMessageData(const LLMsgData& data);
-
- virtual void copyFromLLSD(const LLSD& msg);
-
- const LLSD& getMessage() const;
-private:
-
- /* mCurrentMessage is of the following format:
- mCurrentMessage = { 'block_name1' : [ { 'block1_field1' : 'b1f1_data',
- 'block1_field2' : 'b1f2_data',
- ...
- 'block1_fieldn' : 'b1fn_data'},
- { 'block2_field1' : 'b2f1_data',
- 'block2_field2' : 'b2f2_data',
- ...
- 'block2_fieldn' : 'b2fn_data'},
- ...
- { 'blockm_field1' : 'bmf1_data',
- 'blockm_field2' : 'bmf2_data',
- ...
- 'blockm_fieldn' : 'bmfn_data'} ],
- 'block_name2' : ...,
- ...
- 'block_namem' } */
- LLSD mCurrentMessage;
- LLSD* mCurrentBlock;
- std::string mCurrentMessageName;
- std::string mCurrentBlockName;
- bool mbSBuilt;
- bool mbSClear;
-};
-
-#endif // LL_LLSDMESSAGEBUILDER_H
+/**
+ * @file llsdmessagebuilder.h
+ * @brief Declaration of LLSDMessageBuilder class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDMESSAGEBUILDER_H
+#define LL_LLSDMESSAGEBUILDER_H
+
+#include <map>
+
+#include "llmessagebuilder.h"
+#include "llmsgvariabletype.h"
+#include "llsd.h"
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLSDMessageBuilder : public LLMessageBuilder
+{
+public:
+
+ //CLASS_LOG_TYPE(LLSDMessageBuilder);
+
+ LLSDMessageBuilder();
+ virtual ~LLSDMessageBuilder();
+
+ virtual void newMessage(const char* name);
+
+ virtual void nextBlock(const char* blockname);
+ virtual bool removeLastBlock(); // TODO: babbage: remove this horror...
+
+ /** All add* methods expect pointers to canonical varname strings. */
+ virtual void addBinaryData(
+ const char* varname,
+ const void* data,
+ S32 size);
+ virtual void addBOOL(const char* varname, bool b);
+ virtual void addS8(const char* varname, S8 s);
+ virtual void addU8(const char* varname, U8 u);
+ virtual void addS16(const char* varname, S16 i);
+ virtual void addU16(const char* varname, U16 i);
+ virtual void addF32(const char* varname, F32 f);
+ virtual void addS32(const char* varname, S32 s);
+ virtual void addU32(const char* varname, U32 u);
+ virtual void addU64(const char* varname, U64 lu);
+ virtual void addF64(const char* varname, F64 d);
+ virtual void addVector3(const char* varname, const LLVector3& vec);
+ virtual void addVector4(const char* varname, const LLVector4& vec);
+ virtual void addVector3d(const char* varname, const LLVector3d& vec);
+ virtual void addQuat(const char* varname, const LLQuaternion& quat);
+ virtual void addUUID(const char* varname, const LLUUID& uuid);
+ virtual void addIPAddr(const char* varname, const U32 ip);
+ virtual void addIPPort(const char* varname, const U16 port);
+ virtual void addString(const char* varname, const char* s);
+ virtual void addString(const char* varname, const std::string& s);
+
+ virtual bool isMessageFull(const char* blockname) const;
+ virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
+
+ virtual bool isBuilt() const;
+ virtual bool isClear() const;
+ virtual U32 buildMessage(U8* buffer, U32 buffer_size, U8 offset_to_data);
+ /**< Null implementation which returns 0. */
+
+ virtual void clearMessage();
+
+ // TODO: babbage: remove this horror.
+ virtual void setBuilt(bool b);
+
+ virtual S32 getMessageSize();
+ virtual const char* getMessageName() const;
+
+ virtual void copyFromMessageData(const LLMsgData& data);
+
+ virtual void copyFromLLSD(const LLSD& msg);
+
+ const LLSD& getMessage() const;
+private:
+
+ /* mCurrentMessage is of the following format:
+ mCurrentMessage = { 'block_name1' : [ { 'block1_field1' : 'b1f1_data',
+ 'block1_field2' : 'b1f2_data',
+ ...
+ 'block1_fieldn' : 'b1fn_data'},
+ { 'block2_field1' : 'b2f1_data',
+ 'block2_field2' : 'b2f2_data',
+ ...
+ 'block2_fieldn' : 'b2fn_data'},
+ ...
+ { 'blockm_field1' : 'bmf1_data',
+ 'blockm_field2' : 'bmf2_data',
+ ...
+ 'blockm_fieldn' : 'bmfn_data'} ],
+ 'block_name2' : ...,
+ ...
+ 'block_namem' } */
+ LLSD mCurrentMessage;
+ LLSD* mCurrentBlock;
+ std::string mCurrentMessageName;
+ std::string mCurrentBlockName;
+ bool mbSBuilt;
+ bool mbSClear;
+};
+
+#endif // LL_LLSDMESSAGEBUILDER_H
diff --git a/indra/llmessage/llsdmessagereader.cpp b/indra/llmessage/llsdmessagereader.cpp
index d533d6535b..c0e8f634b2 100644
--- a/indra/llmessage/llsdmessagereader.cpp
+++ b/indra/llmessage/llsdmessagereader.cpp
@@ -1,344 +1,344 @@
-/**
- * @file llsdmessagereader.cpp
- * @brief LLSDMessageReader class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llsdmessagereader.h"
-
-#include "llmessagebuilder.h"
-#include "llsdmessagebuilder.h"
-#include "llsdutil.h"
-
-#include "llsdutil_math.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "v3dmath.h"
-#include "v2math.h"
-#include "llquaternion.h"
-#include "v4color.h"
-
-LLSDMessageReader::LLSDMessageReader() :
- mMessageName(NULL)
-{
-}
-
-//virtual
-LLSDMessageReader::~LLSDMessageReader()
-{
-}
-
-
-LLSD getLLSD(const LLSD& input, const char* block, const char* var, S32 blocknum)
-{
- // babbage: log error to LL_ERRS() if variable not found to mimic
- // LLTemplateMessageReader::getData behaviour
- if(NULL == block)
- {
- LL_ERRS() << "NULL block name" << LL_ENDL;
- return LLSD();
- }
- if(NULL == var)
- {
- LL_ERRS() << "NULL var name" << LL_ENDL;
- return LLSD();
- }
- if(! input[block].isArray())
- {
- // NOTE: babbage: need to return default for missing blocks to allow
- // backwards/forwards compatibility - handlers must cope with default
- // values.
- LL_WARNS() << "block " << block << " not found" << LL_ENDL;
- return LLSD();
- }
-
- LLSD result = input[block][blocknum][var];
- if(result.isUndefined())
- {
- // NOTE: babbage: need to return default for missing vars to allow
- // backwards/forwards compatibility - handlers must cope with default
- // values.
- LL_WARNS() << "var " << var << " not found" << LL_ENDL;
- }
- return result;
-}
-
-//virtual
-void LLSDMessageReader::getBinaryData(const char *block, const char *var,
- void *datap, S32 size, S32 blocknum,
- S32 max_size)
-{
- std::vector<U8> data = getLLSD(mMessage, block, var, blocknum);
- S32 data_size = (S32)data.size();
-
- if (size && data_size != size)
- {
- return;
- }
-
- if (max_size < data_size)
- {
- data_size = max_size;
- }
-
- // Calls to memcpy will fail if data_size is not positive.
- // Phoenix 2009-02-27
- if(data_size <= 0)
- {
- return;
- }
- memcpy(datap, &(data[0]), data_size);
-}
-
-//virtual
-void LLSDMessageReader::getBOOL(const char *block, const char *var,
- bool &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum);
-}
-
-//virtual
-void LLSDMessageReader::getS8(const char *block, const char *var, S8 &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum).asInteger();
-}
-
-//virtual
-void LLSDMessageReader::getU8(const char *block, const char *var, U8 &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum).asInteger();
-}
-
-//virtual
-void LLSDMessageReader::getS16(const char *block, const char *var, S16 &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum).asInteger();
-}
-
-//virtual
-void LLSDMessageReader::getU16(const char *block, const char *var, U16 &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum).asInteger();
-}
-
-//virtual
-void LLSDMessageReader::getS32(const char *block, const char *var, S32 &data,
- S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum);
-}
-
-//virtual
-void LLSDMessageReader::getF32(const char *block, const char *var, F32 &data,
- S32 blocknum)
-{
- data = (F32)getLLSD(mMessage, block, var, blocknum).asReal();
-}
-
-//virtual
-void LLSDMessageReader::getU32(const char *block, const char *var, U32 &data,
- S32 blocknum)
-{
- data = ll_U32_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getU64(const char *block, const char *var,
- U64 &data, S32 blocknum)
-{
- data = ll_U64_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getF64(const char *block, const char *var,
- F64 &data, S32 blocknum)
-{
- data = getLLSD(mMessage, block, var, blocknum);
-}
-
-//virtual
-void LLSDMessageReader::getVector3(const char *block, const char *var,
- LLVector3 &vec, S32 blocknum)
-{
- vec = ll_vector3_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getVector4(const char *block, const char *var,
- LLVector4 &vec, S32 blocknum)
-{
- vec = ll_vector4_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getVector3d(const char *block, const char *var,
- LLVector3d &vec, S32 blocknum)
-{
- vec = ll_vector3d_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getQuat(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum)
-{
- q = ll_quaternion_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getUUID(const char *block, const char *var,
- LLUUID &uuid, S32 blocknum)
-{
- uuid = getLLSD(mMessage, block, var, blocknum);
-}
-
-//virtual
-void LLSDMessageReader::getIPAddr(const char *block, const char *var,
- U32 &ip, S32 blocknum)
-{
- ip = ll_ipaddr_from_sd(getLLSD(mMessage, block, var, blocknum));
-}
-
-//virtual
-void LLSDMessageReader::getIPPort(const char *block, const char *var,
- U16 &port, S32 blocknum)
-{
- port = getLLSD(mMessage, block, var, blocknum).asInteger();
-}
-
-//virtual
-void LLSDMessageReader::getString(const char *block, const char *var,
- S32 buffer_size, char *buffer, S32 blocknum)
-{
- if(buffer_size <= 0)
- {
- LL_WARNS() << "buffer_size <= 0" << LL_ENDL;
- return;
- }
- std::string data = getLLSD(mMessage, block, var, blocknum);
- S32 data_size = data.size();
- if (data_size >= buffer_size)
- {
- data_size = buffer_size - 1;
- }
- memcpy(buffer, data.data(), data_size);
- buffer[data_size] = '\0';
-}
-
-//virtual
-void LLSDMessageReader::getString(const char *block, const char *var,
- std::string& outstr, S32 blocknum)
-{
- outstr = getLLSD(mMessage, block, var, blocknum).asString();
-}
-
-//virtual
-S32 LLSDMessageReader::getNumberOfBlocks(const char *blockname)
-{
- return mMessage[blockname].size();
-}
-
-S32 getElementSize(const LLSD& llsd)
-{
- LLSD::Type type = llsd.type();
- switch(type)
- {
- case LLSD::TypeBoolean:
- return sizeof(bool);
- case LLSD::TypeInteger:
- return sizeof(S32);
- case LLSD::TypeReal:
- return sizeof(F64);
- case LLSD::TypeString:
- return llsd.size();
- case LLSD::TypeUUID:
- return sizeof(LLUUID);
- case LLSD::TypeDate:
- return sizeof(LLDate);
- case LLSD::TypeURI:
- return sizeof(LLURI);
- case LLSD::TypeBinary:
- {
- std::vector<U8> data = llsd;
- return data.size() * sizeof(U8);
- }
- case LLSD::TypeMap:
- case LLSD::TypeArray:
- case LLSD::TypeUndefined:
- default: // TypeLLSDTypeEnd, TypeLLSDNumTypes, etc.
- return 0;
- }
- //return 0;
-}
-
-//virtual
-//Mainly used to find size of binary block of data
-S32 LLSDMessageReader::getSize(const char *blockname, const char *varname)
-{
- return getElementSize(mMessage[blockname][0][varname]);
-}
-
-
-//virtual
-S32 LLSDMessageReader::getSize(const char *blockname, S32 blocknum,
- const char *varname)
-{
- return getElementSize(mMessage[blockname][blocknum][varname]);
-}
-
-//virtual
-void LLSDMessageReader::clearMessage()
-{
- mMessage = LLSD();
-}
-
-//virtual
-const char* LLSDMessageReader::getMessageName() const
-{
- return mMessageName;
-}
-
-// virtual
-S32 LLSDMessageReader::getMessageSize() const
-{
- return 0;
-}
-
-//virtual
-void LLSDMessageReader::copyToBuilder(LLMessageBuilder& builder) const
-{
- builder.copyFromLLSD(mMessage);
-}
-
-void LLSDMessageReader::setMessage(const char* name, const LLSD& message)
-{
- mMessageName = name;
- // TODO: Validate
- mMessage = message;
-}
+/**
+ * @file llsdmessagereader.cpp
+ * @brief LLSDMessageReader class implementation.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llsdmessagereader.h"
+
+#include "llmessagebuilder.h"
+#include "llsdmessagebuilder.h"
+#include "llsdutil.h"
+
+#include "llsdutil_math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "v3dmath.h"
+#include "v2math.h"
+#include "llquaternion.h"
+#include "v4color.h"
+
+LLSDMessageReader::LLSDMessageReader() :
+ mMessageName(NULL)
+{
+}
+
+//virtual
+LLSDMessageReader::~LLSDMessageReader()
+{
+}
+
+
+LLSD getLLSD(const LLSD& input, const char* block, const char* var, S32 blocknum)
+{
+ // babbage: log error to LL_ERRS() if variable not found to mimic
+ // LLTemplateMessageReader::getData behaviour
+ if(NULL == block)
+ {
+ LL_ERRS() << "NULL block name" << LL_ENDL;
+ return LLSD();
+ }
+ if(NULL == var)
+ {
+ LL_ERRS() << "NULL var name" << LL_ENDL;
+ return LLSD();
+ }
+ if(! input[block].isArray())
+ {
+ // NOTE: babbage: need to return default for missing blocks to allow
+ // backwards/forwards compatibility - handlers must cope with default
+ // values.
+ LL_WARNS() << "block " << block << " not found" << LL_ENDL;
+ return LLSD();
+ }
+
+ LLSD result = input[block][blocknum][var];
+ if(result.isUndefined())
+ {
+ // NOTE: babbage: need to return default for missing vars to allow
+ // backwards/forwards compatibility - handlers must cope with default
+ // values.
+ LL_WARNS() << "var " << var << " not found" << LL_ENDL;
+ }
+ return result;
+}
+
+//virtual
+void LLSDMessageReader::getBinaryData(const char *block, const char *var,
+ void *datap, S32 size, S32 blocknum,
+ S32 max_size)
+{
+ std::vector<U8> data = getLLSD(mMessage, block, var, blocknum);
+ S32 data_size = (S32)data.size();
+
+ if (size && data_size != size)
+ {
+ return;
+ }
+
+ if (max_size < data_size)
+ {
+ data_size = max_size;
+ }
+
+ // Calls to memcpy will fail if data_size is not positive.
+ // Phoenix 2009-02-27
+ if(data_size <= 0)
+ {
+ return;
+ }
+ memcpy(datap, &(data[0]), data_size);
+}
+
+//virtual
+void LLSDMessageReader::getBOOL(const char *block, const char *var,
+ bool &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual
+void LLSDMessageReader::getS8(const char *block, const char *var, S8 &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual
+void LLSDMessageReader::getU8(const char *block, const char *var, U8 &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual
+void LLSDMessageReader::getS16(const char *block, const char *var, S16 &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual
+void LLSDMessageReader::getU16(const char *block, const char *var, U16 &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual
+void LLSDMessageReader::getS32(const char *block, const char *var, S32 &data,
+ S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual
+void LLSDMessageReader::getF32(const char *block, const char *var, F32 &data,
+ S32 blocknum)
+{
+ data = (F32)getLLSD(mMessage, block, var, blocknum).asReal();
+}
+
+//virtual
+void LLSDMessageReader::getU32(const char *block, const char *var, U32 &data,
+ S32 blocknum)
+{
+ data = ll_U32_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getU64(const char *block, const char *var,
+ U64 &data, S32 blocknum)
+{
+ data = ll_U64_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getF64(const char *block, const char *var,
+ F64 &data, S32 blocknum)
+{
+ data = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual
+void LLSDMessageReader::getVector3(const char *block, const char *var,
+ LLVector3 &vec, S32 blocknum)
+{
+ vec = ll_vector3_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getVector4(const char *block, const char *var,
+ LLVector4 &vec, S32 blocknum)
+{
+ vec = ll_vector4_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getVector3d(const char *block, const char *var,
+ LLVector3d &vec, S32 blocknum)
+{
+ vec = ll_vector3d_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getQuat(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum)
+{
+ q = ll_quaternion_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getUUID(const char *block, const char *var,
+ LLUUID &uuid, S32 blocknum)
+{
+ uuid = getLLSD(mMessage, block, var, blocknum);
+}
+
+//virtual
+void LLSDMessageReader::getIPAddr(const char *block, const char *var,
+ U32 &ip, S32 blocknum)
+{
+ ip = ll_ipaddr_from_sd(getLLSD(mMessage, block, var, blocknum));
+}
+
+//virtual
+void LLSDMessageReader::getIPPort(const char *block, const char *var,
+ U16 &port, S32 blocknum)
+{
+ port = getLLSD(mMessage, block, var, blocknum).asInteger();
+}
+
+//virtual
+void LLSDMessageReader::getString(const char *block, const char *var,
+ S32 buffer_size, char *buffer, S32 blocknum)
+{
+ if(buffer_size <= 0)
+ {
+ LL_WARNS() << "buffer_size <= 0" << LL_ENDL;
+ return;
+ }
+ std::string data = getLLSD(mMessage, block, var, blocknum);
+ S32 data_size = data.size();
+ if (data_size >= buffer_size)
+ {
+ data_size = buffer_size - 1;
+ }
+ memcpy(buffer, data.data(), data_size);
+ buffer[data_size] = '\0';
+}
+
+//virtual
+void LLSDMessageReader::getString(const char *block, const char *var,
+ std::string& outstr, S32 blocknum)
+{
+ outstr = getLLSD(mMessage, block, var, blocknum).asString();
+}
+
+//virtual
+S32 LLSDMessageReader::getNumberOfBlocks(const char *blockname)
+{
+ return mMessage[blockname].size();
+}
+
+S32 getElementSize(const LLSD& llsd)
+{
+ LLSD::Type type = llsd.type();
+ switch(type)
+ {
+ case LLSD::TypeBoolean:
+ return sizeof(bool);
+ case LLSD::TypeInteger:
+ return sizeof(S32);
+ case LLSD::TypeReal:
+ return sizeof(F64);
+ case LLSD::TypeString:
+ return llsd.size();
+ case LLSD::TypeUUID:
+ return sizeof(LLUUID);
+ case LLSD::TypeDate:
+ return sizeof(LLDate);
+ case LLSD::TypeURI:
+ return sizeof(LLURI);
+ case LLSD::TypeBinary:
+ {
+ std::vector<U8> data = llsd;
+ return data.size() * sizeof(U8);
+ }
+ case LLSD::TypeMap:
+ case LLSD::TypeArray:
+ case LLSD::TypeUndefined:
+ default: // TypeLLSDTypeEnd, TypeLLSDNumTypes, etc.
+ return 0;
+ }
+ //return 0;
+}
+
+//virtual
+//Mainly used to find size of binary block of data
+S32 LLSDMessageReader::getSize(const char *blockname, const char *varname)
+{
+ return getElementSize(mMessage[blockname][0][varname]);
+}
+
+
+//virtual
+S32 LLSDMessageReader::getSize(const char *blockname, S32 blocknum,
+ const char *varname)
+{
+ return getElementSize(mMessage[blockname][blocknum][varname]);
+}
+
+//virtual
+void LLSDMessageReader::clearMessage()
+{
+ mMessage = LLSD();
+}
+
+//virtual
+const char* LLSDMessageReader::getMessageName() const
+{
+ return mMessageName;
+}
+
+// virtual
+S32 LLSDMessageReader::getMessageSize() const
+{
+ return 0;
+}
+
+//virtual
+void LLSDMessageReader::copyToBuilder(LLMessageBuilder& builder) const
+{
+ builder.copyFromLLSD(mMessage);
+}
+
+void LLSDMessageReader::setMessage(const char* name, const LLSD& message)
+{
+ mMessageName = name;
+ // TODO: Validate
+ mMessage = message;
+}
diff --git a/indra/llmessage/llsdmessagereader.h b/indra/llmessage/llsdmessagereader.h
index 4119de6009..510730c115 100644
--- a/indra/llmessage/llsdmessagereader.h
+++ b/indra/llmessage/llsdmessagereader.h
@@ -1,108 +1,108 @@
-/**
- * @file llsdmessagereader.h
- * @brief LLSDMessageReader class Declaration
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSDMESSAGEREADER_H
-#define LL_LLSDMESSAGEREADER_H
-
-#include "llmessagereader.h"
-#include "llsd.h"
-
-#include <map>
-
-class LLMessageTemplate;
-class LLMsgData;
-
-class LLSDMessageReader : public LLMessageReader
-{
-public:
-
- LLSDMessageReader();
- virtual ~LLSDMessageReader();
-
- /** All get* methods expect pointers to canonical strings. */
- virtual void getBinaryData(const char *block, const char *var,
- void *datap, S32 size, S32 blocknum = 0,
- S32 max_size = S32_MAX);
- virtual void getBOOL(const char *block, const char *var, bool &data,
- S32 blocknum = 0);
- virtual void getS8(const char *block, const char *var, S8 &data,
- S32 blocknum = 0);
- virtual void getU8(const char *block, const char *var, U8 &data,
- S32 blocknum = 0);
- virtual void getS16(const char *block, const char *var, S16 &data,
- S32 blocknum = 0);
- virtual void getU16(const char *block, const char *var, U16 &data,
- S32 blocknum = 0);
- virtual void getS32(const char *block, const char *var, S32 &data,
- S32 blocknum = 0);
- virtual void getF32(const char *block, const char *var, F32 &data,
- S32 blocknum = 0);
- virtual void getU32(const char *block, const char *var, U32 &data,
- S32 blocknum = 0);
- virtual void getU64(const char *block, const char *var, U64 &data,
- S32 blocknum = 0);
- virtual void getF64(const char *block, const char *var, F64 &data,
- S32 blocknum = 0);
- virtual void getVector3(const char *block, const char *var,
- LLVector3 &vec, S32 blocknum = 0);
- virtual void getVector4(const char *block, const char *var,
- LLVector4 &vec, S32 blocknum = 0);
- virtual void getVector3d(const char *block, const char *var,
- LLVector3d &vec, S32 blocknum = 0);
- virtual void getQuat(const char *block, const char *var, LLQuaternion &q,
- S32 blocknum = 0);
- virtual void getUUID(const char *block, const char *var, LLUUID &uuid,
- S32 blocknum = 0);
- virtual void getIPAddr(const char *block, const char *var, U32 &ip,
- S32 blocknum = 0);
- virtual void getIPPort(const char *block, const char *var, U16 &port,
- S32 blocknum = 0);
- virtual void getString(const char *block, const char *var,
- S32 buffer_size, char *buffer, S32 blocknum = 0);
- virtual void getString(const char *block, const char *var, std::string& outstr,
- S32 blocknum = 0);
-
- virtual S32 getNumberOfBlocks(const char *blockname);
- virtual S32 getSize(const char *blockname, const char *varname);
- virtual S32 getSize(const char *blockname, S32 blocknum,
- const char *varname);
-
- virtual void clearMessage();
-
- virtual const char* getMessageName() const;
- virtual S32 getMessageSize() const;
-
- virtual void copyToBuilder(LLMessageBuilder&) const;
-
- /** Expects a pointer to a canonical name string */
- void setMessage(const char* name, const LLSD& msg);
-
-private:
- const char* mMessageName; // Canonical (prehashed) string.
- LLSD mMessage;
-};
-
-#endif // LL_LLSDMESSAGEREADER_H
+/**
+ * @file llsdmessagereader.h
+ * @brief LLSDMessageReader class Declaration
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSDMESSAGEREADER_H
+#define LL_LLSDMESSAGEREADER_H
+
+#include "llmessagereader.h"
+#include "llsd.h"
+
+#include <map>
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLSDMessageReader : public LLMessageReader
+{
+public:
+
+ LLSDMessageReader();
+ virtual ~LLSDMessageReader();
+
+ /** All get* methods expect pointers to canonical strings. */
+ virtual void getBinaryData(const char *block, const char *var,
+ void *datap, S32 size, S32 blocknum = 0,
+ S32 max_size = S32_MAX);
+ virtual void getBOOL(const char *block, const char *var, bool &data,
+ S32 blocknum = 0);
+ virtual void getS8(const char *block, const char *var, S8 &data,
+ S32 blocknum = 0);
+ virtual void getU8(const char *block, const char *var, U8 &data,
+ S32 blocknum = 0);
+ virtual void getS16(const char *block, const char *var, S16 &data,
+ S32 blocknum = 0);
+ virtual void getU16(const char *block, const char *var, U16 &data,
+ S32 blocknum = 0);
+ virtual void getS32(const char *block, const char *var, S32 &data,
+ S32 blocknum = 0);
+ virtual void getF32(const char *block, const char *var, F32 &data,
+ S32 blocknum = 0);
+ virtual void getU32(const char *block, const char *var, U32 &data,
+ S32 blocknum = 0);
+ virtual void getU64(const char *block, const char *var, U64 &data,
+ S32 blocknum = 0);
+ virtual void getF64(const char *block, const char *var, F64 &data,
+ S32 blocknum = 0);
+ virtual void getVector3(const char *block, const char *var,
+ LLVector3 &vec, S32 blocknum = 0);
+ virtual void getVector4(const char *block, const char *var,
+ LLVector4 &vec, S32 blocknum = 0);
+ virtual void getVector3d(const char *block, const char *var,
+ LLVector3d &vec, S32 blocknum = 0);
+ virtual void getQuat(const char *block, const char *var, LLQuaternion &q,
+ S32 blocknum = 0);
+ virtual void getUUID(const char *block, const char *var, LLUUID &uuid,
+ S32 blocknum = 0);
+ virtual void getIPAddr(const char *block, const char *var, U32 &ip,
+ S32 blocknum = 0);
+ virtual void getIPPort(const char *block, const char *var, U16 &port,
+ S32 blocknum = 0);
+ virtual void getString(const char *block, const char *var,
+ S32 buffer_size, char *buffer, S32 blocknum = 0);
+ virtual void getString(const char *block, const char *var, std::string& outstr,
+ S32 blocknum = 0);
+
+ virtual S32 getNumberOfBlocks(const char *blockname);
+ virtual S32 getSize(const char *blockname, const char *varname);
+ virtual S32 getSize(const char *blockname, S32 blocknum,
+ const char *varname);
+
+ virtual void clearMessage();
+
+ virtual const char* getMessageName() const;
+ virtual S32 getMessageSize() const;
+
+ virtual void copyToBuilder(LLMessageBuilder&) const;
+
+ /** Expects a pointer to a canonical name string */
+ void setMessage(const char* name, const LLSD& msg);
+
+private:
+ const char* mMessageName; // Canonical (prehashed) string.
+ LLSD mMessage;
+};
+
+#endif // LL_LLSDMESSAGEREADER_H
diff --git a/indra/llmessage/llservice.cpp b/indra/llmessage/llservice.cpp
index ddcc13d969..47027dcfce 100644
--- a/indra/llmessage/llservice.cpp
+++ b/indra/llmessage/llservice.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llservice.cpp
* @author Phoenix
* @date 2005-04-20
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,71 +41,71 @@ LLService::~LLService()
// static
bool LLService::registerCreator(const std::string& name, creator_t fn)
{
- LL_INFOS() << "LLService::registerCreator(" << name << ")" << LL_ENDL;
- if(name.empty())
- {
- return false;
- }
+ LL_INFOS() << "LLService::registerCreator(" << name << ")" << LL_ENDL;
+ if(name.empty())
+ {
+ return false;
+ }
- creators_t::value_type vt(name, fn);
- std::pair<creators_t::iterator, bool> rv = sCreatorFunctors.insert(vt);
- return rv.second;
+ creators_t::value_type vt(name, fn);
+ std::pair<creators_t::iterator, bool> rv = sCreatorFunctors.insert(vt);
+ return rv.second;
- // alternately...
- //std::string name_str(name);
- //sCreatorFunctors[name_str] = fn;
+ // alternately...
+ //std::string name_str(name);
+ //sCreatorFunctors[name_str] = fn;
}
// static
LLIOPipe* LLService::activate(
- const std::string& name,
- LLPumpIO::chain_t& chain,
- LLSD context)
+ const std::string& name,
+ LLPumpIO::chain_t& chain,
+ LLSD context)
{
- if(name.empty())
- {
- LL_INFOS() << "LLService::activate - no service specified." << LL_ENDL;
- return NULL;
- }
- creators_t::iterator it = sCreatorFunctors.find(name);
- LLIOPipe* rv = NULL;
- if(it != sCreatorFunctors.end())
- {
- if((*it).second->build(chain, context))
- {
- rv = chain[0].get();
- }
- else
- {
- // empty out the chain, because failed service creation
- // should just discard this stuff.
- LL_WARNS() << "LLService::activate - unable to build chain: " << name
- << LL_ENDL;
- chain.clear();
- }
- }
- else
- {
- LL_WARNS() << "LLService::activate - unable find factory: " << name
- << LL_ENDL;
- }
- return rv;
+ if(name.empty())
+ {
+ LL_INFOS() << "LLService::activate - no service specified." << LL_ENDL;
+ return NULL;
+ }
+ creators_t::iterator it = sCreatorFunctors.find(name);
+ LLIOPipe* rv = NULL;
+ if(it != sCreatorFunctors.end())
+ {
+ if((*it).second->build(chain, context))
+ {
+ rv = chain[0].get();
+ }
+ else
+ {
+ // empty out the chain, because failed service creation
+ // should just discard this stuff.
+ LL_WARNS() << "LLService::activate - unable to build chain: " << name
+ << LL_ENDL;
+ chain.clear();
+ }
+ }
+ else
+ {
+ LL_WARNS() << "LLService::activate - unable find factory: " << name
+ << LL_ENDL;
+ }
+ return rv;
}
// static
bool LLService::discard(const std::string& name)
{
- if(name.empty())
- {
- return false;
- }
- creators_t::iterator it = sCreatorFunctors.find(name);
- if(it != sCreatorFunctors.end())
- {
- //(*it).second->discard();
- sCreatorFunctors.erase(it);
- return true;
- }
- return false;
+ if(name.empty())
+ {
+ return false;
+ }
+ creators_t::iterator it = sCreatorFunctors.find(name);
+ if(it != sCreatorFunctors.end())
+ {
+ //(*it).second->discard();
+ sCreatorFunctors.erase(it);
+ return true;
+ }
+ return false;
}
diff --git a/indra/llmessage/llservice.h b/indra/llmessage/llservice.h
index f215acab56..6c32fa8102 100644
--- a/indra/llmessage/llservice.h
+++ b/indra/llmessage/llservice.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llservice.h
* @author Phoenix
* @date 2004-11-21
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -45,12 +45,12 @@ class LLServiceCreator;
*/
namespace boost
{
- void intrusive_ptr_add_ref(LLServiceCreator* p);
- void intrusive_ptr_release(LLServiceCreator* p);
+ void intrusive_ptr_add_ref(LLServiceCreator* p);
+ void intrusive_ptr_release(LLServiceCreator* p);
};
#endif
-/**
+/**
* @class LLServiceCreator
* @brief This class is an abstract base class for classes which create
* new <code>LLService</code> instances.
@@ -63,41 +63,41 @@ namespace boost
class LLServiceCreator
{
public:
- typedef boost::intrusive_ptr<LLService> service_t;
- virtual ~LLServiceCreator() {}
- virtual service_t activate() = 0;
- virtual void discard() = 0;
+ typedef boost::intrusive_ptr<LLService> service_t;
+ virtual ~LLServiceCreator() {}
+ virtual service_t activate() = 0;
+ virtual void discard() = 0;
protected:
- LLServiceCreator() : mReferenceCount(0)
- {
- }
+ LLServiceCreator() : mReferenceCount(0)
+ {
+ }
private:
- friend void boost::intrusive_ptr_add_ref(LLServiceCreator* p);
- friend void boost::intrusive_ptr_release(LLServiceCreator* p);
- U32 mReferenceCount;
+ friend void boost::intrusive_ptr_add_ref(LLServiceCreator* p);
+ friend void boost::intrusive_ptr_release(LLServiceCreator* p);
+ U32 mReferenceCount;
};
#endif
#if 0
namespace boost
{
- inline void intrusive_ptr_add_ref(LLServiceCreator* p)
- {
- ++p->mReferenceCount;
- }
- inline void intrusive_ptr_release(LLServiceCreator* p)
- {
- if(p && 0 == --p->mReferenceCount)
- {
- delete p;
- }
- }
+ inline void intrusive_ptr_add_ref(LLServiceCreator* p)
+ {
+ ++p->mReferenceCount;
+ }
+ inline void intrusive_ptr_release(LLServiceCreator* p)
+ {
+ if(p && 0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
};
#endif
-/**
+/**
* @class LLService
* @brief This class is the base class for the service classes.
* @see LLIOPipe
@@ -114,71 +114,71 @@ namespace boost
class LLService : public LLIOPipe
{
public:
- //typedef boost::intrusive_ptr<LLServiceCreator> creator_t;
- //typedef boost::intrusive_ptr<LLService> service_t;
- typedef std::shared_ptr<LLChainIOFactory> creator_t;
-
- /**
- * @brief This method is used to register a protocol name with a
- * a functor that creates the service.
- *
- * THOROUGH_DESCRIPTION
- * @param aParameter A brief description of aParameter.
- * @return Returns true if a service was successfully registered.
- */
- static bool registerCreator(const std::string& name, creator_t fn);
-
- /**
- * @brief This method connects to a service by name.
- *
- * @param name The name of the service to connect to.
- * @param chain The constructed chain including the service instance.
- * @param context Context for the activation.
- * @return An instance of the service for use or NULL on failure.
- */
- static LLIOPipe* activate(
- const std::string& name,
- LLPumpIO::chain_t& chain,
- LLSD context);
-
- /**
- * @brief
- *
- * @param name The name of the service to discard.
- * @return true if service creator was found and discarded.
- */
- static bool discard(const std::string& name);
+ //typedef boost::intrusive_ptr<LLServiceCreator> creator_t;
+ //typedef boost::intrusive_ptr<LLService> service_t;
+ typedef std::shared_ptr<LLChainIOFactory> creator_t;
+
+ /**
+ * @brief This method is used to register a protocol name with a
+ * a functor that creates the service.
+ *
+ * THOROUGH_DESCRIPTION
+ * @param aParameter A brief description of aParameter.
+ * @return Returns true if a service was successfully registered.
+ */
+ static bool registerCreator(const std::string& name, creator_t fn);
+
+ /**
+ * @brief This method connects to a service by name.
+ *
+ * @param name The name of the service to connect to.
+ * @param chain The constructed chain including the service instance.
+ * @param context Context for the activation.
+ * @return An instance of the service for use or NULL on failure.
+ */
+ static LLIOPipe* activate(
+ const std::string& name,
+ LLPumpIO::chain_t& chain,
+ LLSD context);
+
+ /**
+ * @brief
+ *
+ * @param name The name of the service to discard.
+ * @return true if service creator was found and discarded.
+ */
+ static bool discard(const std::string& name);
protected:
- // The creation factory static data.
- typedef std::map<std::string, creator_t> creators_t;
- static creators_t sCreatorFunctors;
+ // The creation factory static data.
+ typedef std::map<std::string, creator_t> creators_t;
+ static creators_t sCreatorFunctors;
protected:
- // construction & destruction. since this class is an abstract
- // base class, it is up to Service implementations to actually
- // deal with construction and not a public method. How that
- // construction takes place will be handled by the service
- // creators.
- LLService();
- virtual ~LLService();
+ // construction & destruction. since this class is an abstract
+ // base class, it is up to Service implementations to actually
+ // deal with construction and not a public method. How that
+ // construction takes place will be handled by the service
+ // creators.
+ LLService();
+ virtual ~LLService();
protected:
- // This frame timer records how long this service has
- // existed. Useful for derived services to give themselves a
- // lifetime and expiration.
- // *NOTE: Phoenix - This functionaity has been moved to the
- // pump. 2005-12-13
- //LLFrameTimer mTimer;
-
- // Since services are designed in an 'ask now, respond later'
- // idiom which probably crosses thread boundaries, almost all
- // services will need a handle to a response pipe. It will usually
- // be the job of the service author to derive a useful
- // implementation of response, and up to the service subscriber to
- // further derive that class to do something useful when the
- // response comes in.
- LLIOPipe::ptr_t mResponse;
+ // This frame timer records how long this service has
+ // existed. Useful for derived services to give themselves a
+ // lifetime and expiration.
+ // *NOTE: Phoenix - This functionaity has been moved to the
+ // pump. 2005-12-13
+ //LLFrameTimer mTimer;
+
+ // Since services are designed in an 'ask now, respond later'
+ // idiom which probably crosses thread boundaries, almost all
+ // services will need a handle to a response pipe. It will usually
+ // be the job of the service author to derive a useful
+ // implementation of response, and up to the service subscriber to
+ // further derive that class to do something useful when the
+ // response comes in.
+ LLIOPipe::ptr_t mResponse;
};
diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp
index cf2e42f95c..7dc49d5455 100644
--- a/indra/llmessage/llservicebuilder.cpp
+++ b/indra/llmessage/llservicebuilder.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llservicebuilder.cpp
* @brief Implementation of the LLServiceBuilder class.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,205 +32,205 @@
#include "llsdserialize.h"
void LLServiceBuilder::loadServiceDefinitionsFromFile(
- const std::string& service_filename)
+ const std::string& service_filename)
{
- llifstream service_file(service_filename.c_str(), std::ios::binary);
- if(service_file.is_open())
- {
- LLSD service_data;
- LLSDSerialize::fromXMLDocument(service_data, service_file);
- service_file.close();
- // Load service
- LLSD service_map = service_data["services"];
- for(LLSD::array_iterator array_itr = service_map.beginArray();
- array_itr != service_map.endArray();
- ++array_itr)
- {
- LLSD service_llsd = (*array_itr)["service-builder"];
- std::string service_name = (*array_itr)["name"].asString();
- createServiceDefinition(service_name, service_llsd);
- }
- LL_INFOS() << "loaded config file: " << service_filename << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "unable to find config file: " << service_filename << LL_ENDL;
- }
+ llifstream service_file(service_filename.c_str(), std::ios::binary);
+ if(service_file.is_open())
+ {
+ LLSD service_data;
+ LLSDSerialize::fromXMLDocument(service_data, service_file);
+ service_file.close();
+ // Load service
+ LLSD service_map = service_data["services"];
+ for(LLSD::array_iterator array_itr = service_map.beginArray();
+ array_itr != service_map.endArray();
+ ++array_itr)
+ {
+ LLSD service_llsd = (*array_itr)["service-builder"];
+ std::string service_name = (*array_itr)["name"].asString();
+ createServiceDefinition(service_name, service_llsd);
+ }
+ LL_INFOS() << "loaded config file: " << service_filename << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "unable to find config file: " << service_filename << LL_ENDL;
+ }
}
void LLServiceBuilder::createServiceDefinition(
- const std::string& service_name,
- LLSD& service_llsd)
+ const std::string& service_name,
+ LLSD& service_llsd)
{
- if(service_llsd.isString())
- {
- mServiceMap[ service_name ] = service_llsd.asString();
- }
- else if(service_llsd.isMap())
- {
- for(LLSD::map_iterator map_itr = service_llsd.beginMap();
- map_itr != service_llsd.endMap();
- ++map_itr)
- {
- std::string compound_builder_name = service_name;
- compound_builder_name.append("-");
- compound_builder_name.append((*map_itr).first);
- mServiceMap[ compound_builder_name ] = (*map_itr).second.asString();
- }
- }
+ if(service_llsd.isString())
+ {
+ mServiceMap[ service_name ] = service_llsd.asString();
+ }
+ else if(service_llsd.isMap())
+ {
+ for(LLSD::map_iterator map_itr = service_llsd.beginMap();
+ map_itr != service_llsd.endMap();
+ ++map_itr)
+ {
+ std::string compound_builder_name = service_name;
+ compound_builder_name.append("-");
+ compound_builder_name.append((*map_itr).first);
+ mServiceMap[ compound_builder_name ] = (*map_itr).second.asString();
+ }
+ }
}
static
bool starts_with(const std::string& text, const char* prefix)
{
- return text.substr(0, strlen(prefix)) == prefix;
+ return text.substr(0, strlen(prefix)) == prefix;
}
// TODO: Build a real services.xml for windows development.
// and remove the base_url logic below.
std::string LLServiceBuilder::buildServiceURI(const std::string& service_name) const
{
- std::ostringstream service_url;
- // Find the service builder
- std::map<std::string, std::string>::const_iterator it =
- mServiceMap.find(service_name);
- if(it != mServiceMap.end())
- {
- // construct the service builder url
- LLApp* app = LLApp::instance();
- if(app)
- {
- // We define a base-url for some development configurations
- // In production neither of these are defined and all services have full urls
- LLSD base_url;
+ std::ostringstream service_url;
+ // Find the service builder
+ std::map<std::string, std::string>::const_iterator it =
+ mServiceMap.find(service_name);
+ if(it != mServiceMap.end())
+ {
+ // construct the service builder url
+ LLApp* app = LLApp::instance();
+ if(app)
+ {
+ // We define a base-url for some development configurations
+ // In production neither of these are defined and all services have full urls
+ LLSD base_url;
- if (starts_with(service_name,"cap"))
- {
- base_url = app->getOption("cap-base-url");
- }
+ if (starts_with(service_name,"cap"))
+ {
+ base_url = app->getOption("cap-base-url");
+ }
- if (base_url.asString().empty())
- {
- base_url = app->getOption("services-base-url");
- }
- service_url << base_url.asString();
- }
- service_url << it->second;
- }
- else
- {
- LL_WARNS() << "Cannot find service " << service_name << LL_ENDL;
- }
- return service_url.str();
+ if (base_url.asString().empty())
+ {
+ base_url = app->getOption("services-base-url");
+ }
+ service_url << base_url.asString();
+ }
+ service_url << it->second;
+ }
+ else
+ {
+ LL_WARNS() << "Cannot find service " << service_name << LL_ENDL;
+ }
+ return service_url.str();
}
std::string LLServiceBuilder::buildServiceURI(
- const std::string& service_name,
- const LLSD& option_map) const
+ const std::string& service_name,
+ const LLSD& option_map) const
{
- return russ_format(buildServiceURI(service_name), option_map);
+ return russ_format(buildServiceURI(service_name), option_map);
}
std::string russ_format(const std::string& format_str, const LLSD& context)
{
- std::string service_url(format_str);
- if(!service_url.empty() && context.isMap())
- {
- // throw in a ridiculously large limiter to make sure we don't
- // loop forever with bad input.
- int iterations = 100;
- bool keep_looping = true;
- while(keep_looping)
- {
- if(0 == --iterations)
- {
- keep_looping = false;
- }
+ std::string service_url(format_str);
+ if(!service_url.empty() && context.isMap())
+ {
+ // throw in a ridiculously large limiter to make sure we don't
+ // loop forever with bad input.
+ int iterations = 100;
+ bool keep_looping = true;
+ while(keep_looping)
+ {
+ if(0 == --iterations)
+ {
+ keep_looping = false;
+ }
- int depth = 0;
- int deepest = 0;
- bool find_match = false;
- std::string::iterator iter(service_url.begin());
- std::string::iterator end(service_url.end());
- std::string::iterator deepest_node(service_url.end());
- std::string::iterator deepest_node_end(service_url.end());
- // parse out the variables to replace by going through {}s
- // one at a time, starting with the "deepest" in series
- // {{}}, and otherwise replacing right-to-left
- for(; iter != end; ++iter)
- {
- switch(*iter)
- {
- case '{':
- ++depth;
- if(depth > deepest)
- {
- deepest = depth;
- deepest_node = iter;
- find_match = true;
- }
- break;
- case '}':
- --depth;
- if(find_match)
- {
- deepest_node_end = iter;
- find_match = false;
- }
- break;
- default:
- break;
- }
- }
- if((deepest_node == end) || (deepest_node_end == end))
- {
- break;
- }
- //replace the variable we found in the {} above.
- // *NOTE: since the c++ implementation only understands
- // params and straight string substitution, so it's a
- // known distance of 2 to skip the directive.
- std::string key(deepest_node + 2, deepest_node_end);
- LLSD value = context[key];
- switch(*(deepest_node + 1))
- {
- case '$':
- if(value.isDefined())
- {
- service_url.replace(
- deepest_node,
- deepest_node_end + 1,
- value.asString());
- }
- else
- {
- LL_WARNS() << "Unknown key: " << key << " in option map: "
- << LLSDOStreamer<LLSDNotationFormatter>(context)
- << LL_ENDL;
- keep_looping = false;
- }
- break;
- case '%':
- {
- std::string query_str = LLURI::mapToQueryString(value);
- service_url.replace(
- deepest_node,
- deepest_node_end + 1,
- query_str);
- }
- break;
- default:
- LL_INFOS() << "Unknown directive: " << *(deepest_node + 1)
- << LL_ENDL;
- keep_looping = false;
- break;
- }
- }
- }
- if (service_url.find('{') != std::string::npos)
- {
- LL_WARNS() << "Constructed a likely bogus service URL: " << service_url
- << LL_ENDL;
- }
- return service_url;
+ int depth = 0;
+ int deepest = 0;
+ bool find_match = false;
+ std::string::iterator iter(service_url.begin());
+ std::string::iterator end(service_url.end());
+ std::string::iterator deepest_node(service_url.end());
+ std::string::iterator deepest_node_end(service_url.end());
+ // parse out the variables to replace by going through {}s
+ // one at a time, starting with the "deepest" in series
+ // {{}}, and otherwise replacing right-to-left
+ for(; iter != end; ++iter)
+ {
+ switch(*iter)
+ {
+ case '{':
+ ++depth;
+ if(depth > deepest)
+ {
+ deepest = depth;
+ deepest_node = iter;
+ find_match = true;
+ }
+ break;
+ case '}':
+ --depth;
+ if(find_match)
+ {
+ deepest_node_end = iter;
+ find_match = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if((deepest_node == end) || (deepest_node_end == end))
+ {
+ break;
+ }
+ //replace the variable we found in the {} above.
+ // *NOTE: since the c++ implementation only understands
+ // params and straight string substitution, so it's a
+ // known distance of 2 to skip the directive.
+ std::string key(deepest_node + 2, deepest_node_end);
+ LLSD value = context[key];
+ switch(*(deepest_node + 1))
+ {
+ case '$':
+ if(value.isDefined())
+ {
+ service_url.replace(
+ deepest_node,
+ deepest_node_end + 1,
+ value.asString());
+ }
+ else
+ {
+ LL_WARNS() << "Unknown key: " << key << " in option map: "
+ << LLSDOStreamer<LLSDNotationFormatter>(context)
+ << LL_ENDL;
+ keep_looping = false;
+ }
+ break;
+ case '%':
+ {
+ std::string query_str = LLURI::mapToQueryString(value);
+ service_url.replace(
+ deepest_node,
+ deepest_node_end + 1,
+ query_str);
+ }
+ break;
+ default:
+ LL_INFOS() << "Unknown directive: " << *(deepest_node + 1)
+ << LL_ENDL;
+ keep_looping = false;
+ break;
+ }
+ }
+ }
+ if (service_url.find('{') != std::string::npos)
+ {
+ LL_WARNS() << "Constructed a likely bogus service URL: " << service_url
+ << LL_ENDL;
+ }
+ return service_url;
}
diff --git a/indra/llmessage/llservicebuilder.h b/indra/llmessage/llservicebuilder.h
index 968995edf2..be03534514 100644
--- a/indra/llmessage/llservicebuilder.h
+++ b/indra/llmessage/llservicebuilder.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llservicebuilder.h
* @brief Declaration of the LLServiceBuilder class.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
-*
+*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
-*
+*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
-*
+*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*
+*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,56 +47,56 @@ class LLSD;
*/
std::string russ_format(const std::string& format_str, const LLSD& context);
-/**
+/**
* @class LLServiceBuilder
* @brief This class builds urls for us to use when making web service calls.
*/
class LLServiceBuilder
{
- LOG_CLASS(LLServiceBuilder);
+ LOG_CLASS(LLServiceBuilder);
public:
- LLServiceBuilder(void) {}
- ~LLServiceBuilder(void) {}
+ LLServiceBuilder(void) {}
+ ~LLServiceBuilder(void) {}
- /**
- * @brief Initialize this object with the service definitions.
- *
- * @param service_filename The services definition files -- services.xml.
- */
- void loadServiceDefinitionsFromFile(const std::string& service_filename);
+ /**
+ * @brief Initialize this object with the service definitions.
+ *
+ * @param service_filename The services definition files -- services.xml.
+ */
+ void loadServiceDefinitionsFromFile(const std::string& service_filename);
- /**
- * @brief Build a service url if the url needs no construction parameters.
- *
- * @param service_name The name of the service you want to call.
- */
- std::string buildServiceURI(const std::string& service_name) const;
+ /**
+ * @brief Build a service url if the url needs no construction parameters.
+ *
+ * @param service_name The name of the service you want to call.
+ */
+ std::string buildServiceURI(const std::string& service_name) const;
- /**
- * @brief Build a service url if the url with construction parameters.
- *
- * The parameter substitution supports string substituition from RUSS:
- * [[Recursive_URL_Substitution_Syntax]]
- * @param service_name The name of the service you want to call.
- * @param option_map The parameters in a map of name:value for the service.
- */
- std::string buildServiceURI(
- const std::string& service_name,
- const LLSD& option_map) const;
+ /**
+ * @brief Build a service url if the url with construction parameters.
+ *
+ * The parameter substitution supports string substituition from RUSS:
+ * [[Recursive_URL_Substitution_Syntax]]
+ * @param service_name The name of the service you want to call.
+ * @param option_map The parameters in a map of name:value for the service.
+ */
+ std::string buildServiceURI(
+ const std::string& service_name,
+ const LLSD& option_map) const;
public:
- /**
- * @brief Helper method which builds construction state for a service
- *
- * This method should probably be protected, but we need to test this
- * method.
- */
- void createServiceDefinition(
- const std::string& service_name,
- LLSD& service_url);
+ /**
+ * @brief Helper method which builds construction state for a service
+ *
+ * This method should probably be protected, but we need to test this
+ * method.
+ */
+ void createServiceDefinition(
+ const std::string& service_name,
+ LLSD& service_url);
protected:
- std::map<std::string, std::string> mServiceMap;
+ std::map<std::string, std::string> mServiceMap;
};
diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp
index 9f2f2bcda7..39696ea235 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstoredmessage.cpp
- * @brief
+ * @brief
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 6ea150fda3..178b75ab04 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llstoredmessage.h
- * @brief
+ * @brief
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,12 +38,12 @@ class LLMessageSystem;
class LLStoredMessage
{
public:
- LLStoredMessage(const std::string& name, const LLSD& message);
+ LLStoredMessage(const std::string& name, const LLSD& message);
private:
- friend class LLMessageSystem;
+ friend class LLMessageSystem;
- LLSD mMessage;
- std::string mName;
+ LLSD mMessage;
+ std::string mName;
};
typedef std::shared_ptr<LLStoredMessage> LLStoredMessagePtr;
diff --git a/indra/llmessage/lltaskname.h b/indra/llmessage/lltaskname.h
index 5dbd9c6223..413242dc05 100644
--- a/indra/llmessage/lltaskname.h
+++ b/indra/llmessage/lltaskname.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file lltaskname.h
* @brief This contains the current list of valid tasks and is inluded
* into both simulator and viewer
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,7 +29,7 @@
#define LL_LLTASKNAME_H
// Current valid tasks
-// If you add a taskname here you will have to
+// If you add a taskname here you will have to
// 1) Add an initializer to init_object() in llscript.cpp
// 1.1) Add to object_type_to_task_name() in llregion.cpp
// 2) Add display code to LLStupidObject::render2(LLAgent* agentp) in llstupidobject.cpp
@@ -37,24 +37,24 @@
typedef enum e_lltask_name
{
- LLTASK_NULL = 0, // Not a valid task
- LLTASK_AGENT = 1, // The player's agent in Linden World
- LLTASK_CHILD_AGENT = 2, // Child agents sent to adjacent regions
-// LLTASK_BASIC_SHOT, // Simple shot that moves in a straight line
-// LLTASK_BIG_SHOT, // Big shot that uses gravity
- LLTASK_TREE = 5, // A tree
-// LLTASK_BIRD, // a bird
-// LLTASK_ATOR, // a predator
-// LLTASK_SMOKE, // Smoke poof
-// LLTASK_SPARK, // Little spark
-// LLTASK_ROCK, // Rock
- LLTASK_GRASS = 11, // Grass
- LLTASK_PSYS = 12, // particle system test example
-// LLTASK_ORACLE,
-// LLTASK_DEMON, // Maxwell's demon
-// LLTASK_LSL_TEST, // Linden Scripting Language Test Object
- LLTASK_PRIMITIVE = 16,
-// LLTASK_GHOST = 17, // a ghost (Boo!)
- LLTASK_TREE_NEW = 18
+ LLTASK_NULL = 0, // Not a valid task
+ LLTASK_AGENT = 1, // The player's agent in Linden World
+ LLTASK_CHILD_AGENT = 2, // Child agents sent to adjacent regions
+// LLTASK_BASIC_SHOT, // Simple shot that moves in a straight line
+// LLTASK_BIG_SHOT, // Big shot that uses gravity
+ LLTASK_TREE = 5, // A tree
+// LLTASK_BIRD, // a bird
+// LLTASK_ATOR, // a predator
+// LLTASK_SMOKE, // Smoke poof
+// LLTASK_SPARK, // Little spark
+// LLTASK_ROCK, // Rock
+ LLTASK_GRASS = 11, // Grass
+ LLTASK_PSYS = 12, // particle system test example
+// LLTASK_ORACLE,
+// LLTASK_DEMON, // Maxwell's demon
+// LLTASK_LSL_TEST, // Linden Scripting Language Test Object
+ LLTASK_PRIMITIVE = 16,
+// LLTASK_GHOST = 17, // a ghost (Boo!)
+ LLTASK_TREE_NEW = 18
} ELLTaskName;
#endif
diff --git a/indra/llmessage/llteleportflags.h b/indra/llmessage/llteleportflags.h
index fd1e702832..36f9e8e2c8 100644
--- a/indra/llmessage/llteleportflags.h
+++ b/indra/llmessage/llteleportflags.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llteleportflags.h
* @brief Teleport flags
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -27,39 +27,39 @@
#ifndef LL_LLTELEPORTFLAGS_H
#define LL_LLTELEPORTFLAGS_H
-const U32 TELEPORT_FLAGS_DEFAULT = 0;
-const U32 TELEPORT_FLAGS_SET_HOME_TO_TARGET = 1 << 0; // newbie leaving prelude
-const U32 TELEPORT_FLAGS_SET_LAST_TO_TARGET = 1 << 1;
-const U32 TELEPORT_FLAGS_VIA_LURE = 1 << 2;
-const U32 TELEPORT_FLAGS_VIA_LANDMARK = 1 << 3;
-const U32 TELEPORT_FLAGS_VIA_LOCATION = 1 << 4;
-const U32 TELEPORT_FLAGS_VIA_HOME = 1 << 5;
-const U32 TELEPORT_FLAGS_VIA_TELEHUB = 1 << 6;
-const U32 TELEPORT_FLAGS_VIA_LOGIN = 1 << 7;
-const U32 TELEPORT_FLAGS_VIA_GODLIKE_LURE = 1 << 8;
-const U32 TELEPORT_FLAGS_GODLIKE = 1 << 9;
-const U32 TELEPORT_FLAGS_911 = 1 << 10;
-const U32 TELEPORT_FLAGS_DISABLE_CANCEL = 1 << 11; // Used for llTeleportAgentHome()
-const U32 TELEPORT_FLAGS_VIA_REGION_ID = 1 << 12;
-const U32 TELEPORT_FLAGS_IS_FLYING = 1 << 13;
-const U32 TELEPORT_FLAGS_SHOW_RESET_HOME = 1 << 14;
-const U32 TELEPORT_FLAGS_FORCE_REDIRECT = 1 << 15; // used to force a redirect to some random location - used when kicking someone from land.
-const U32 TELEPORT_FLAGS_VIA_GLOBAL_COORDS = 1 << 16;
-const U32 TELEPORT_FLAGS_WITHIN_REGION = 1 << 17;
+const U32 TELEPORT_FLAGS_DEFAULT = 0;
+const U32 TELEPORT_FLAGS_SET_HOME_TO_TARGET = 1 << 0; // newbie leaving prelude
+const U32 TELEPORT_FLAGS_SET_LAST_TO_TARGET = 1 << 1;
+const U32 TELEPORT_FLAGS_VIA_LURE = 1 << 2;
+const U32 TELEPORT_FLAGS_VIA_LANDMARK = 1 << 3;
+const U32 TELEPORT_FLAGS_VIA_LOCATION = 1 << 4;
+const U32 TELEPORT_FLAGS_VIA_HOME = 1 << 5;
+const U32 TELEPORT_FLAGS_VIA_TELEHUB = 1 << 6;
+const U32 TELEPORT_FLAGS_VIA_LOGIN = 1 << 7;
+const U32 TELEPORT_FLAGS_VIA_GODLIKE_LURE = 1 << 8;
+const U32 TELEPORT_FLAGS_GODLIKE = 1 << 9;
+const U32 TELEPORT_FLAGS_911 = 1 << 10;
+const U32 TELEPORT_FLAGS_DISABLE_CANCEL = 1 << 11; // Used for llTeleportAgentHome()
+const U32 TELEPORT_FLAGS_VIA_REGION_ID = 1 << 12;
+const U32 TELEPORT_FLAGS_IS_FLYING = 1 << 13;
+const U32 TELEPORT_FLAGS_SHOW_RESET_HOME = 1 << 14;
+const U32 TELEPORT_FLAGS_FORCE_REDIRECT = 1 << 15; // used to force a redirect to some random location - used when kicking someone from land.
+const U32 TELEPORT_FLAGS_VIA_GLOBAL_COORDS = 1 << 16;
+const U32 TELEPORT_FLAGS_WITHIN_REGION = 1 << 17;
+
+const U32 TELEPORT_FLAGS_MASK_VIA = TELEPORT_FLAGS_VIA_LURE
+ | TELEPORT_FLAGS_VIA_LANDMARK
+ | TELEPORT_FLAGS_VIA_LOCATION
+ | TELEPORT_FLAGS_VIA_HOME
+ | TELEPORT_FLAGS_VIA_TELEHUB
+ | TELEPORT_FLAGS_VIA_LOGIN
+ | TELEPORT_FLAGS_VIA_REGION_ID;
-const U32 TELEPORT_FLAGS_MASK_VIA = TELEPORT_FLAGS_VIA_LURE
- | TELEPORT_FLAGS_VIA_LANDMARK
- | TELEPORT_FLAGS_VIA_LOCATION
- | TELEPORT_FLAGS_VIA_HOME
- | TELEPORT_FLAGS_VIA_TELEHUB
- | TELEPORT_FLAGS_VIA_LOGIN
- | TELEPORT_FLAGS_VIA_REGION_ID;
-
-const U32 LURE_FLAG_NORMAL_LURE = 1 << 0;
-const U32 LURE_FLAG_GODLIKE_LURE = 1 << 1;
+const U32 LURE_FLAG_NORMAL_LURE = 1 << 0;
+const U32 LURE_FLAG_GODLIKE_LURE = 1 << 1;
const U32 LURE_FLAG_GODLIKE_PURSUIT = 1 << 2;
#endif
diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp
index 62c53dbe55..57ffba9705 100644
--- a/indra/llmessage/lltemplatemessagebuilder.cpp
+++ b/indra/llmessage/lltemplatemessagebuilder.cpp
@@ -1,893 +1,893 @@
-/**
- * @file lltemplatemessagebuilder.cpp
- * @brief LLTemplateMessageBuilder class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltemplatemessagebuilder.h"
-
-#include "llmessagetemplate.h"
-#include "llmath.h"
-#include "llquaternion.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-
-LLTemplateMessageBuilder::LLTemplateMessageBuilder(const message_template_name_map_t& name_template_map) :
- mCurrentSMessageData(NULL),
- mCurrentSMessageTemplate(NULL),
- mCurrentSDataBlock(NULL),
- mCurrentSMessageName(NULL),
- mCurrentSBlockName(NULL),
- mbSBuilt(false),
- mbSClear(true),
- mCurrentSendTotal(0),
- mMessageTemplates(name_template_map)
-{
-}
-
-//virtual
-LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
-{
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
-}
-
-// virtual
-void LLTemplateMessageBuilder::newMessage(const char *name)
-{
- mbSBuilt = false;
- mbSClear = false;
-
- mCurrentSendTotal = 0;
-
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
-
- char* namep = (char*)name;
- if (mMessageTemplates.count(namep) > 0)
- {
- mCurrentSMessageTemplate = mMessageTemplates.find(name)->second;
- mCurrentSMessageData = new LLMsgData(namep);
- mCurrentSMessageName = namep;
- mCurrentSDataBlock = NULL;
- mCurrentSBlockName = NULL;
-
- // add at one of each block
- const LLMessageTemplate* msg_template = mMessageTemplates.find(name)->second;
-
- if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
- {
- LL_WARNS() << "Sending deprecated message " << namep << LL_ENDL;
- }
-
- LLMessageTemplate::message_block_map_t::const_iterator iter;
- for(iter = msg_template->mMemberBlocks.begin();
- iter != msg_template->mMemberBlocks.end();
- ++iter)
- {
- LLMessageBlock* ci = *iter;
- LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0);
- mCurrentSMessageData->addBlock(tblockp);
- }
- }
- else
- {
- LL_ERRS() << "newMessage - Message " << name << " not registered" << LL_ENDL;
- }
-}
-
-// virtual
-void LLTemplateMessageBuilder::clearMessage()
-{
- mbSBuilt = false;
- mbSClear = true;
-
- mCurrentSendTotal = 0;
-
- mCurrentSMessageTemplate = NULL;
-
- delete mCurrentSMessageData;
- mCurrentSMessageData = NULL;
-
- mCurrentSMessageName = NULL;
- mCurrentSDataBlock = NULL;
- mCurrentSBlockName = NULL;
-}
-
-// virtual
-void LLTemplateMessageBuilder::nextBlock(const char* blockname)
-{
- char *bnamep = (char *)blockname;
-
- if (!mCurrentSMessageTemplate)
- {
- LL_ERRS() << "newMessage not called prior to setBlock" << LL_ENDL;
- return;
- }
-
- // now, does this block exist?
- const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
- if (!template_data)
- {
- LL_ERRS() << "LLTemplateMessageBuilder::nextBlock " << bnamep
- << " not a block in " << mCurrentSMessageTemplate->mName << LL_ENDL;
- return;
- }
-
- // ok, have we already set this block?
- LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
- if (block_data->mBlockNumber == 0)
- {
- // nope! set this as the current block
- block_data->mBlockNumber = 1;
- mCurrentSDataBlock = block_data;
- mCurrentSBlockName = bnamep;
-
- // add placeholders for each of the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
- iter != template_data->mMemberVariables.end(); iter++)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
- }
- return;
- }
- else
- {
- // already have this block. . .
- // are we supposed to have a new one?
-
- // if the block is type MBT_SINGLE this is bad!
- if (template_data->mType == MBT_SINGLE)
- {
- LL_ERRS() << "LLTemplateMessageBuilder::nextBlock called multiple times"
- << " for " << bnamep << " but is type MBT_SINGLE" << LL_ENDL;
- return;
- }
-
-
- // if the block is type MBT_MULTIPLE then we need a known number,
- // make sure that we're not exceeding it
- if ( (template_data->mType == MBT_MULTIPLE)
- &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
- {
- LL_ERRS() << "LLTemplateMessageBuilder::nextBlock called "
- << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
- << " exceeding " << template_data->mNumber
- << " specified in type MBT_MULTIPLE." << LL_ENDL;
- return;
- }
-
- // ok, we can make a new one
- // modify the name to avoid name collision by adding number to end
- S32 count = block_data->mBlockNumber;
-
- // incrememt base name's count
- block_data->mBlockNumber++;
-
- if (block_data->mBlockNumber > MAX_BLOCKS)
- {
- LL_ERRS() << "Trying to pack too many blocks into MBT_VARIABLE type "
- << "(limited to " << MAX_BLOCKS << ")" << LL_ENDL;
- }
-
- // create new name
- // Nota Bene: if things are working correctly,
- // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber ==
- // mCurrentDataBlock->mBlockNumber + 1
-
- char *nbnamep = bnamep + count;
-
- mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
- mCurrentSDataBlock->mName = nbnamep;
- mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
-
- // add placeholders for each of the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator
- iter = template_data->mMemberVariables.begin(),
- end = template_data->mMemberVariables.end();
- iter != end; iter++)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
- }
- return;
- }
-}
-
-// TODO: Remove this horror...
-bool LLTemplateMessageBuilder::removeLastBlock()
-{
- if (mCurrentSBlockName)
- {
- if ( (mCurrentSMessageData)
- &&(mCurrentSMessageTemplate))
- {
- if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
- {
- // At least one block for the current block name.
-
- // Store the current block name for future reference.
- char *block_name = mCurrentSBlockName;
-
- // Decrement the sent total by the size of the
- // data in the message block that we're currently building.
-
- const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
-
- for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
- iter != template_data->mMemberVariables.end(); iter++)
- {
- LLMessageVariable& ci = **iter;
- mCurrentSendTotal -= ci.getSize();
- }
-
-
- // Now we want to find the block that we're blowing away.
-
- // Get the number of blocks.
- LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
- S32 num_blocks = block_data->mBlockNumber;
-
- // Use the same (suspect?) algorithm that's used to generate
- // the names in the nextBlock method to find it.
- char *block_getting_whacked = block_name + num_blocks - 1;
- LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
- delete whacked_data;
- mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
-
- if (num_blocks <= 1)
- {
- // we just blew away the last one, so return false
- LL_WARNS() << "not blowing away the only block of message "
- << mCurrentSMessageName
- << ". Block: " << block_name
- << ". Number: " << num_blocks
- << LL_ENDL;
- return false;
- }
- else
- {
- // Decrement the counter.
- block_data->mBlockNumber--;
- return true;
- }
- }
- }
- }
- return false;
-}
-
-// add data to variable in current block
-void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
-{
- char *vnamep = (char *)varname;
-
- // do we have a current message?
- if (!mCurrentSMessageTemplate)
- {
- LL_ERRS() << "newMessage not called prior to addData" << LL_ENDL;
- return;
- }
-
- // do we have a current block?
- if (!mCurrentSDataBlock)
- {
- LL_ERRS() << "setBlock not called prior to addData" << LL_ENDL;
- return;
- }
-
- // kewl, add the data if it exists
- const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
- if (!var_data || !var_data->getName())
- {
- LL_ERRS() << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << LL_ENDL;
- return;
- }
-
- // ok, it seems ok. . . are we the correct size?
- if (var_data->getType() == MVT_VARIABLE)
- {
- // Variable 1 can only store 255 bytes, make sure our data is smaller
- if ((var_data->getSize() == 1) &&
- (size > 255))
- {
- LL_WARNS() << "Field " << varname << " is a Variable 1 but program "
- << "attempted to stuff more than 255 bytes in "
- << "(" << size << "). Clamping size and truncating data." << LL_ENDL;
- size = 255;
- char *truncate = (char *)data;
- truncate[254] = 0; // array size is 255 but the last element index is 254
- }
-
- // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
- mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
- mCurrentSendTotal += size;
- }
- else
- {
- if (size != var_data->getSize())
- {
- LL_ERRS() << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
- << var_data->getSize() << LL_ENDL;
- return;
- }
- // alright, smash it in
- mCurrentSDataBlock->addData(vnamep, data, size, type);
- mCurrentSendTotal += size;
- }
-}
-
-// add data to variable in current block - fails if variable isn't MVT_FIXED
-void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
-{
- char *vnamep = (char *)varname;
-
- // do we have a current message?
- if (!mCurrentSMessageTemplate)
- {
- LL_ERRS() << "newMessage not called prior to addData" << LL_ENDL;
- return;
- }
-
- // do we have a current block?
- if (!mCurrentSDataBlock)
- {
- LL_ERRS() << "setBlock not called prior to addData" << LL_ENDL;
- return;
- }
-
- // kewl, add the data if it exists
- const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
- if (!var_data->getName())
- {
- LL_ERRS() << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << LL_ENDL;
- return;
- }
-
- // ok, it seems ok. . . are we MVT_VARIABLE?
- if (var_data->getType() == MVT_VARIABLE)
- {
- // nope
- LL_ERRS() << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << LL_ENDL;
- return;
- }
- else
- {
- mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
- mCurrentSendTotal += var_data->getSize();
- }
-}
-
-void LLTemplateMessageBuilder::addBinaryData(const char *varname,
- const void *data, S32 size)
-{
- addData(varname, data, MVT_FIXED, size);
-}
-
-void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
-{
- addData(varname, &s, MVT_S8, sizeof(s));
-}
-
-void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
-{
- addData(varname, &u, MVT_U8, sizeof(u));
-}
-
-void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
-{
- addData(varname, &i, MVT_S16, sizeof(i));
-}
-
-void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
-{
- addData(varname, &i, MVT_U16, sizeof(i));
-}
-
-void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
-{
- addData(varname, &f, MVT_F32, sizeof(f));
-}
-
-void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
-{
- addData(varname, &s, MVT_S32, sizeof(s));
-}
-
-void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
-{
- addData(varname, &u, MVT_U32, sizeof(u));
-}
-
-void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
-{
- addData(varname, &lu, MVT_U64, sizeof(lu));
-}
-
-void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
-{
- addData(varname, &d, MVT_F64, sizeof(d));
-}
-
-void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
-{
- addData(varname, &u, MVT_IP_ADDR, sizeof(u));
-}
-
-void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
-{
- u = htons(u);
- addData(varname, &u, MVT_IP_PORT, sizeof(u));
-}
-
-void LLTemplateMessageBuilder::addBOOL(const char* varname, bool b)
-{
- U8 temp = (b != 0);
- addData(varname, &temp, MVT_BOOL, sizeof(temp));
-}
-
-void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
-{
- if (s)
- addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */
- else
- addData( varname, NULL, MVT_VARIABLE, 0);
-}
-
-void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
-{
- if (s.size())
- addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1);
- else
- addData( varname, NULL, MVT_VARIABLE, 0);
-}
-
-void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
-{
- addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
-}
-
-void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
-{
- addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
-}
-
-void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
-{
- addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
-}
-
-void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
-{
- addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
-}
-
-void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
-{
- addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
-}
-
-static S32 zero_code(U8 **data, U32 *data_size)
-{
- // Encoded send buffer needs to be slightly larger since the zero
- // coding can potentially increase the size of the send data.
- static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
-
- S32 count = *data_size;
-
- S32 net_gain = 0;
- U8 num_zeroes = 0;
-
- U8 *inptr = (U8 *)*data;
- U8 *outptr = (U8 *)encodedSendBuffer;
-
-// skip the packet id field
-
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
- {
- count--;
- *outptr++ = *inptr++;
- }
-
-// build encoded packet, keeping track of net size gain
-
-// sequential zero bytes are encoded as 0 [U8 count]
-// with 0 0 [count] representing wrap (>256 zeroes)
-
- while (count--)
- {
- if (!(*inptr)) // in a zero count
- {
- if (num_zeroes)
- {
- if (++num_zeroes > 254)
- {
- *outptr++ = num_zeroes;
- num_zeroes = 0;
- }
- net_gain--; // subseqent zeroes save one
- }
- else
- {
- *outptr++ = 0;
- net_gain++; // starting a zero count adds one
- num_zeroes = 1;
- }
- inptr++;
- }
- else
- {
- if (num_zeroes)
- {
- *outptr++ = num_zeroes;
- num_zeroes = 0;
- }
- *outptr++ = *inptr++;
- }
- }
-
- if (num_zeroes)
- {
- *outptr++ = num_zeroes;
- }
-
- if (net_gain < 0)
- {
- // TODO: babbage: reinstate stat collecting...
- //mCompressedPacketsOut++;
- //mUncompressedBytesOut += *data_size;
-
- *data = encodedSendBuffer;
- *data_size += net_gain;
- encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG; // set the head bit to indicate zero coding
-
- //mCompressedBytesOut += *data_size;
-
- }
- //mTotalBytesOut += *data_size;
-
- return(net_gain);
-}
-
-void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
-{
- if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
- {
- zero_code(&buf_ptr, &buffer_length);
- }
-}
-
-bool LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
-{
- if(mCurrentSendTotal > MTUBYTES)
- {
- return true;
- }
- if(!blockname)
- {
- return false;
- }
- char* bnamep = (char*)blockname;
- S32 max;
-
- const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
-
- switch(template_data->mType)
- {
- case MBT_SINGLE:
- max = 1;
- break;
- case MBT_MULTIPLE:
- max = template_data->mNumber;
- break;
- case MBT_VARIABLE:
- default:
- max = MAX_BLOCKS;
- break;
- }
- if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
- {
- return true;
- }
- return false;
-}
-
-static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data)
-{
- S32 result = 0;
- LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName);
- const LLMsgBlkData* mbci = block_iter->second;
-
- // ok, if this is the first block of a repeating pack, set
- // block_count and, if it's type MBT_VARIABLE encode a byte
- // for how many there are
- S32 block_count = mbci->mBlockNumber;
- if (template_data->mType == MBT_VARIABLE)
- {
- // remember that mBlockNumber is a S32
- U8 temp_block_number = (U8)mbci->mBlockNumber;
- if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
- {
- memcpy(&buffer[result], &temp_block_number, sizeof(U8));
- result += sizeof(U8);
- }
- else
- {
- // Just reporting error is likely not enough. Need
- // to check how to abort or error out gracefully
- // from this function. XXXTBD
- LL_ERRS() << "buildBlock failed. Message excedding "
- << "sendBuffersize." << LL_ENDL;
- }
- }
- else if (template_data->mType == MBT_MULTIPLE)
- {
- if (block_count != template_data->mNumber)
- {
- // nope! need to fill it in all the way!
- LL_ERRS() << "Block " << mbci->mName
- << " is type MBT_MULTIPLE but only has data for "
- << block_count << " out of its "
- << template_data->mNumber << " blocks" << LL_ENDL;
- }
- }
-
- while(block_count > 0)
- {
- // now loop through the variables
- for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin();
- iter != mbci->mMemberVarData.end(); iter++)
- {
- const LLMsgVarData& mvci = *iter;
- if (mvci.getSize() == -1)
- {
- // oops, this variable wasn't ever set!
- LL_ERRS() << "The variable " << mvci.getName() << " in block "
- << mbci->mName << " of message "
- << template_data->mName
- << " wasn't set prior to buildMessage call" << LL_ENDL;
- }
- else
- {
- S32 data_size = mvci.getDataSize();
- if(data_size > 0)
- {
- // The type is MVT_VARIABLE, which means that we
- // need to encode a size argument. Otherwise,
- // there is no need.
- S32 size = mvci.getSize();
- U8 sizeb;
- U16 sizeh;
- switch(data_size)
- {
- case 1:
- sizeb = size;
- htolememcpy(&buffer[result], &sizeb, MVT_U8, 1);
- break;
- case 2:
- sizeh = size;
- htolememcpy(&buffer[result], &sizeh, MVT_U16, 2);
- break;
- case 4:
- htolememcpy(&buffer[result], &size, MVT_S32, 4);
- break;
- default:
- LL_ERRS() << "Attempting to build variable field with unknown size of " << size << LL_ENDL;
- break;
- }
- result += mvci.getDataSize();
- }
-
- // if there is any data to pack, pack it
- if((mvci.getData() != NULL) && mvci.getSize())
- {
- if(result + mvci.getSize() < buffer_size)
- {
- memcpy(
- &buffer[result],
- mvci.getData(),
- mvci.getSize());
- result += mvci.getSize();
- }
- else
- {
- // Just reporting error is likely not
- // enough. Need to check how to abort or error
- // out gracefully from this function. XXXTBD
- LL_ERRS() << "buildBlock failed. "
- << "Attempted to pack "
- << (result + mvci.getSize())
- << " bytes into a buffer with size "
- << buffer_size << "." << LL_ENDL;
- }
- }
- }
- }
-
- --block_count;
-
- if (block_iter != message_data->mMemberBlocks.end())
- {
- ++block_iter;
- if (block_iter != message_data->mMemberBlocks.end())
- {
- mbci = block_iter->second;
- }
- }
- }
-
- return result;
-}
-
-
-// make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
-U32 LLTemplateMessageBuilder::buildMessage(
- U8* buffer,
- U32 buffer_size,
- U8 offset_to_data)
-{
- // basic algorithm is to loop through the various pieces, building
- // size and offset info if we encounter a -1 for mSize at any
- // point that variable wasn't given data
-
- // do we have a current message?
- if (!mCurrentSMessageTemplate)
- {
- LL_ERRS() << "newMessage not called prior to buildMessage" << LL_ENDL;
- return 0;
- }
-
- // leave room for flags, packet sequence #, and data offset
- // information.
- buffer[PHL_OFFSET] = offset_to_data;
- U32 result = LL_PACKET_ID_SIZE;
-
- // encode message number and adjust total_offset
- if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
- {
-// old, endian-dependant way
-// memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
-
-// new, independant way
- buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
- result += sizeof(U8);
- }
- else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
- {
- U8 temp = 255;
- memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
- result += sizeof(U8);
-
- // mask off unsightly bits
- temp = mCurrentSMessageTemplate->mMessageNumber & 255;
- memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
- result += sizeof(U8);
- }
- else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
- {
- U8 temp = 255;
- U16 message_num;
- memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
- result += sizeof(U8);
- memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
- result += sizeof(U8);
-
- // mask off unsightly bits
- message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
-
- // convert to network byte order
- message_num = htons(message_num);
- memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
- result += sizeof(U16);
- }
- else
- {
- LL_ERRS() << "unexpected message frequency in buildMessage" << LL_ENDL;
- return 0;
- }
-
- // fast forward through the offset and build the message
- result += offset_to_data;
- for(LLMessageTemplate::message_block_map_t::const_iterator
- iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
- end = mCurrentSMessageTemplate->mMemberBlocks.end();
- iter != end;
- ++iter)
- {
- result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData);
- }
- mbSBuilt = true;
-
- return result;
-}
-
-void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
-{
- // copy the blocks
- // counting variables used to encode multiple block info
- S32 block_count = 0;
- char *block_name = NULL;
-
- // loop through msg blocks to loop through variables, totalling up size
- // data and filling the new (send) message
- LLMsgData::msg_blk_data_map_t::const_iterator iter =
- data.mMemberBlocks.begin();
- LLMsgData::msg_blk_data_map_t::const_iterator end =
- data.mMemberBlocks.end();
- for(; iter != end; ++iter)
- {
- const LLMsgBlkData* mbci = iter->second;
- if(!mbci) continue;
-
- // do we need to encode a block code?
- if (block_count == 0)
- {
- block_count = mbci->mBlockNumber;
- block_name = (char *)mbci->mName;
- }
-
- // counting down mutliple blocks
- block_count--;
-
- nextBlock(block_name);
-
- // now loop through the variables
- LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
- LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
-
- for(; dit != dend; ++dit)
- {
- const LLMsgVarData& mvci = *dit;
- addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
- }
- }
-}
-
-//virtual
-void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
-{
- // TODO
-}
-
-//virtual
-void LLTemplateMessageBuilder::setBuilt(bool b) { mbSBuilt = b; }
-
-//virtual
-bool LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
-
-//virtual
-bool LLTemplateMessageBuilder::isClear() const {return mbSClear;}
-
-//virtual
-S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
-
-//virtual
-const char* LLTemplateMessageBuilder::getMessageName() const
-{
- return mCurrentSMessageName;
-}
+/**
+ * @file lltemplatemessagebuilder.cpp
+ * @brief LLTemplateMessageBuilder class implementation.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltemplatemessagebuilder.h"
+
+#include "llmessagetemplate.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLTemplateMessageBuilder::LLTemplateMessageBuilder(const message_template_name_map_t& name_template_map) :
+ mCurrentSMessageData(NULL),
+ mCurrentSMessageTemplate(NULL),
+ mCurrentSDataBlock(NULL),
+ mCurrentSMessageName(NULL),
+ mCurrentSBlockName(NULL),
+ mbSBuilt(false),
+ mbSClear(true),
+ mCurrentSendTotal(0),
+ mMessageTemplates(name_template_map)
+{
+}
+
+//virtual
+LLTemplateMessageBuilder::~LLTemplateMessageBuilder()
+{
+ delete mCurrentSMessageData;
+ mCurrentSMessageData = NULL;
+}
+
+// virtual
+void LLTemplateMessageBuilder::newMessage(const char *name)
+{
+ mbSBuilt = false;
+ mbSClear = false;
+
+ mCurrentSendTotal = 0;
+
+ delete mCurrentSMessageData;
+ mCurrentSMessageData = NULL;
+
+ char* namep = (char*)name;
+ if (mMessageTemplates.count(namep) > 0)
+ {
+ mCurrentSMessageTemplate = mMessageTemplates.find(name)->second;
+ mCurrentSMessageData = new LLMsgData(namep);
+ mCurrentSMessageName = namep;
+ mCurrentSDataBlock = NULL;
+ mCurrentSBlockName = NULL;
+
+ // add at one of each block
+ const LLMessageTemplate* msg_template = mMessageTemplates.find(name)->second;
+
+ if (msg_template->getDeprecation() != MD_NOTDEPRECATED)
+ {
+ LL_WARNS() << "Sending deprecated message " << namep << LL_ENDL;
+ }
+
+ LLMessageTemplate::message_block_map_t::const_iterator iter;
+ for(iter = msg_template->mMemberBlocks.begin();
+ iter != msg_template->mMemberBlocks.end();
+ ++iter)
+ {
+ LLMessageBlock* ci = *iter;
+ LLMsgBlkData* tblockp = new LLMsgBlkData(ci->mName, 0);
+ mCurrentSMessageData->addBlock(tblockp);
+ }
+ }
+ else
+ {
+ LL_ERRS() << "newMessage - Message " << name << " not registered" << LL_ENDL;
+ }
+}
+
+// virtual
+void LLTemplateMessageBuilder::clearMessage()
+{
+ mbSBuilt = false;
+ mbSClear = true;
+
+ mCurrentSendTotal = 0;
+
+ mCurrentSMessageTemplate = NULL;
+
+ delete mCurrentSMessageData;
+ mCurrentSMessageData = NULL;
+
+ mCurrentSMessageName = NULL;
+ mCurrentSDataBlock = NULL;
+ mCurrentSBlockName = NULL;
+}
+
+// virtual
+void LLTemplateMessageBuilder::nextBlock(const char* blockname)
+{
+ char *bnamep = (char *)blockname;
+
+ if (!mCurrentSMessageTemplate)
+ {
+ LL_ERRS() << "newMessage not called prior to setBlock" << LL_ENDL;
+ return;
+ }
+
+ // now, does this block exist?
+ const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
+ if (!template_data)
+ {
+ LL_ERRS() << "LLTemplateMessageBuilder::nextBlock " << bnamep
+ << " not a block in " << mCurrentSMessageTemplate->mName << LL_ENDL;
+ return;
+ }
+
+ // ok, have we already set this block?
+ LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[bnamep];
+ if (block_data->mBlockNumber == 0)
+ {
+ // nope! set this as the current block
+ block_data->mBlockNumber = 1;
+ mCurrentSDataBlock = block_data;
+ mCurrentSBlockName = bnamep;
+
+ // add placeholders for each of the variables
+ for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
+ iter != template_data->mMemberVariables.end(); iter++)
+ {
+ LLMessageVariable& ci = **iter;
+ mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
+ }
+ return;
+ }
+ else
+ {
+ // already have this block. . .
+ // are we supposed to have a new one?
+
+ // if the block is type MBT_SINGLE this is bad!
+ if (template_data->mType == MBT_SINGLE)
+ {
+ LL_ERRS() << "LLTemplateMessageBuilder::nextBlock called multiple times"
+ << " for " << bnamep << " but is type MBT_SINGLE" << LL_ENDL;
+ return;
+ }
+
+
+ // if the block is type MBT_MULTIPLE then we need a known number,
+ // make sure that we're not exceeding it
+ if ( (template_data->mType == MBT_MULTIPLE)
+ &&(mCurrentSDataBlock->mBlockNumber == template_data->mNumber))
+ {
+ LL_ERRS() << "LLTemplateMessageBuilder::nextBlock called "
+ << mCurrentSDataBlock->mBlockNumber << " times for " << bnamep
+ << " exceeding " << template_data->mNumber
+ << " specified in type MBT_MULTIPLE." << LL_ENDL;
+ return;
+ }
+
+ // ok, we can make a new one
+ // modify the name to avoid name collision by adding number to end
+ S32 count = block_data->mBlockNumber;
+
+ // incrememt base name's count
+ block_data->mBlockNumber++;
+
+ if (block_data->mBlockNumber > MAX_BLOCKS)
+ {
+ LL_ERRS() << "Trying to pack too many blocks into MBT_VARIABLE type "
+ << "(limited to " << MAX_BLOCKS << ")" << LL_ENDL;
+ }
+
+ // create new name
+ // Nota Bene: if things are working correctly,
+ // mCurrentMessageData->mMemberBlocks[blockname]->mBlockNumber ==
+ // mCurrentDataBlock->mBlockNumber + 1
+
+ char *nbnamep = bnamep + count;
+
+ mCurrentSDataBlock = new LLMsgBlkData(bnamep, count);
+ mCurrentSDataBlock->mName = nbnamep;
+ mCurrentSMessageData->mMemberBlocks[nbnamep] = mCurrentSDataBlock;
+
+ // add placeholders for each of the variables
+ for (LLMessageBlock::message_variable_map_t::const_iterator
+ iter = template_data->mMemberVariables.begin(),
+ end = template_data->mMemberVariables.end();
+ iter != end; iter++)
+ {
+ LLMessageVariable& ci = **iter;
+ mCurrentSDataBlock->addVariable(ci.getName(), ci.getType());
+ }
+ return;
+ }
+}
+
+// TODO: Remove this horror...
+bool LLTemplateMessageBuilder::removeLastBlock()
+{
+ if (mCurrentSBlockName)
+ {
+ if ( (mCurrentSMessageData)
+ &&(mCurrentSMessageTemplate))
+ {
+ if (mCurrentSMessageData->mMemberBlocks[mCurrentSBlockName]->mBlockNumber >= 1)
+ {
+ // At least one block for the current block name.
+
+ // Store the current block name for future reference.
+ char *block_name = mCurrentSBlockName;
+
+ // Decrement the sent total by the size of the
+ // data in the message block that we're currently building.
+
+ const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName);
+
+ for (LLMessageBlock::message_variable_map_t::const_iterator iter = template_data->mMemberVariables.begin();
+ iter != template_data->mMemberVariables.end(); iter++)
+ {
+ LLMessageVariable& ci = **iter;
+ mCurrentSendTotal -= ci.getSize();
+ }
+
+
+ // Now we want to find the block that we're blowing away.
+
+ // Get the number of blocks.
+ LLMsgBlkData* block_data = mCurrentSMessageData->mMemberBlocks[block_name];
+ S32 num_blocks = block_data->mBlockNumber;
+
+ // Use the same (suspect?) algorithm that's used to generate
+ // the names in the nextBlock method to find it.
+ char *block_getting_whacked = block_name + num_blocks - 1;
+ LLMsgBlkData* whacked_data = mCurrentSMessageData->mMemberBlocks[block_getting_whacked];
+ delete whacked_data;
+ mCurrentSMessageData->mMemberBlocks.erase(block_getting_whacked);
+
+ if (num_blocks <= 1)
+ {
+ // we just blew away the last one, so return false
+ LL_WARNS() << "not blowing away the only block of message "
+ << mCurrentSMessageName
+ << ". Block: " << block_name
+ << ". Number: " << num_blocks
+ << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ // Decrement the counter.
+ block_data->mBlockNumber--;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// add data to variable in current block
+void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type, S32 size)
+{
+ char *vnamep = (char *)varname;
+
+ // do we have a current message?
+ if (!mCurrentSMessageTemplate)
+ {
+ LL_ERRS() << "newMessage not called prior to addData" << LL_ENDL;
+ return;
+ }
+
+ // do we have a current block?
+ if (!mCurrentSDataBlock)
+ {
+ LL_ERRS() << "setBlock not called prior to addData" << LL_ENDL;
+ return;
+ }
+
+ // kewl, add the data if it exists
+ const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
+ if (!var_data || !var_data->getName())
+ {
+ LL_ERRS() << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << LL_ENDL;
+ return;
+ }
+
+ // ok, it seems ok. . . are we the correct size?
+ if (var_data->getType() == MVT_VARIABLE)
+ {
+ // Variable 1 can only store 255 bytes, make sure our data is smaller
+ if ((var_data->getSize() == 1) &&
+ (size > 255))
+ {
+ LL_WARNS() << "Field " << varname << " is a Variable 1 but program "
+ << "attempted to stuff more than 255 bytes in "
+ << "(" << size << "). Clamping size and truncating data." << LL_ENDL;
+ size = 255;
+ char *truncate = (char *)data;
+ truncate[254] = 0; // array size is 255 but the last element index is 254
+ }
+
+ // no correct size for MVT_VARIABLE, instead we need to tell how many bytes the size will be encoded as
+ mCurrentSDataBlock->addData(vnamep, data, size, type, var_data->getSize());
+ mCurrentSendTotal += size;
+ }
+ else
+ {
+ if (size != var_data->getSize())
+ {
+ LL_ERRS() << varname << " is type MVT_FIXED but request size " << size << " doesn't match template size "
+ << var_data->getSize() << LL_ENDL;
+ return;
+ }
+ // alright, smash it in
+ mCurrentSDataBlock->addData(vnamep, data, size, type);
+ mCurrentSendTotal += size;
+ }
+}
+
+// add data to variable in current block - fails if variable isn't MVT_FIXED
+void LLTemplateMessageBuilder::addData(const char *varname, const void *data, EMsgVariableType type)
+{
+ char *vnamep = (char *)varname;
+
+ // do we have a current message?
+ if (!mCurrentSMessageTemplate)
+ {
+ LL_ERRS() << "newMessage not called prior to addData" << LL_ENDL;
+ return;
+ }
+
+ // do we have a current block?
+ if (!mCurrentSDataBlock)
+ {
+ LL_ERRS() << "setBlock not called prior to addData" << LL_ENDL;
+ return;
+ }
+
+ // kewl, add the data if it exists
+ const LLMessageVariable* var_data = mCurrentSMessageTemplate->getBlock(mCurrentSBlockName)->getVariable(vnamep);
+ if (!var_data->getName())
+ {
+ LL_ERRS() << vnamep << " not a variable in block " << mCurrentSBlockName << " of " << mCurrentSMessageTemplate->mName << LL_ENDL;
+ return;
+ }
+
+ // ok, it seems ok. . . are we MVT_VARIABLE?
+ if (var_data->getType() == MVT_VARIABLE)
+ {
+ // nope
+ LL_ERRS() << vnamep << " is type MVT_VARIABLE. Call using addData(name, data, size)" << LL_ENDL;
+ return;
+ }
+ else
+ {
+ mCurrentSDataBlock->addData(vnamep, data, var_data->getSize(), type);
+ mCurrentSendTotal += var_data->getSize();
+ }
+}
+
+void LLTemplateMessageBuilder::addBinaryData(const char *varname,
+ const void *data, S32 size)
+{
+ addData(varname, data, MVT_FIXED, size);
+}
+
+void LLTemplateMessageBuilder::addS8(const char *varname, S8 s)
+{
+ addData(varname, &s, MVT_S8, sizeof(s));
+}
+
+void LLTemplateMessageBuilder::addU8(const char *varname, U8 u)
+{
+ addData(varname, &u, MVT_U8, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addS16(const char *varname, S16 i)
+{
+ addData(varname, &i, MVT_S16, sizeof(i));
+}
+
+void LLTemplateMessageBuilder::addU16(const char *varname, U16 i)
+{
+ addData(varname, &i, MVT_U16, sizeof(i));
+}
+
+void LLTemplateMessageBuilder::addF32(const char *varname, F32 f)
+{
+ addData(varname, &f, MVT_F32, sizeof(f));
+}
+
+void LLTemplateMessageBuilder::addS32(const char *varname, S32 s)
+{
+ addData(varname, &s, MVT_S32, sizeof(s));
+}
+
+void LLTemplateMessageBuilder::addU32(const char *varname, U32 u)
+{
+ addData(varname, &u, MVT_U32, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addU64(const char *varname, U64 lu)
+{
+ addData(varname, &lu, MVT_U64, sizeof(lu));
+}
+
+void LLTemplateMessageBuilder::addF64(const char *varname, F64 d)
+{
+ addData(varname, &d, MVT_F64, sizeof(d));
+}
+
+void LLTemplateMessageBuilder::addIPAddr(const char *varname, U32 u)
+{
+ addData(varname, &u, MVT_IP_ADDR, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addIPPort(const char *varname, U16 u)
+{
+ u = htons(u);
+ addData(varname, &u, MVT_IP_PORT, sizeof(u));
+}
+
+void LLTemplateMessageBuilder::addBOOL(const char* varname, bool b)
+{
+ U8 temp = (b != 0);
+ addData(varname, &temp, MVT_BOOL, sizeof(temp));
+}
+
+void LLTemplateMessageBuilder::addString(const char* varname, const char* s)
+{
+ if (s)
+ addData( varname, (void *)s, MVT_VARIABLE, (S32)strlen(s) + 1); /* Flawfinder: ignore */
+ else
+ addData( varname, NULL, MVT_VARIABLE, 0);
+}
+
+void LLTemplateMessageBuilder::addString(const char* varname, const std::string& s)
+{
+ if (s.size())
+ addData( varname, (void *)s.c_str(), MVT_VARIABLE, (S32)(s.size()) + 1);
+ else
+ addData( varname, NULL, MVT_VARIABLE, 0);
+}
+
+void LLTemplateMessageBuilder::addVector3(const char *varname, const LLVector3& vec)
+{
+ addData(varname, vec.mV, MVT_LLVector3, sizeof(vec.mV));
+}
+
+void LLTemplateMessageBuilder::addVector4(const char *varname, const LLVector4& vec)
+{
+ addData(varname, vec.mV, MVT_LLVector4, sizeof(vec.mV));
+}
+
+void LLTemplateMessageBuilder::addVector3d(const char *varname, const LLVector3d& vec)
+{
+ addData(varname, vec.mdV, MVT_LLVector3d, sizeof(vec.mdV));
+}
+
+void LLTemplateMessageBuilder::addQuat(const char *varname, const LLQuaternion& quat)
+{
+ addData(varname, quat.packToVector3().mV, MVT_LLQuaternion, sizeof(LLVector3));
+}
+
+void LLTemplateMessageBuilder::addUUID(const char *varname, const LLUUID& uuid)
+{
+ addData(varname, uuid.mData, MVT_LLUUID, sizeof(uuid.mData));
+}
+
+static S32 zero_code(U8 **data, U32 *data_size)
+{
+ // Encoded send buffer needs to be slightly larger since the zero
+ // coding can potentially increase the size of the send data.
+ static U8 encodedSendBuffer[2 * MAX_BUFFER_SIZE];
+
+ S32 count = *data_size;
+
+ S32 net_gain = 0;
+ U8 num_zeroes = 0;
+
+ U8 *inptr = (U8 *)*data;
+ U8 *outptr = (U8 *)encodedSendBuffer;
+
+// skip the packet id field
+
+ for (U32 ii = 0; ii < LL_PACKET_ID_SIZE ; ++ii)
+ {
+ count--;
+ *outptr++ = *inptr++;
+ }
+
+// build encoded packet, keeping track of net size gain
+
+// sequential zero bytes are encoded as 0 [U8 count]
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+ while (count--)
+ {
+ if (!(*inptr)) // in a zero count
+ {
+ if (num_zeroes)
+ {
+ if (++num_zeroes > 254)
+ {
+ *outptr++ = num_zeroes;
+ num_zeroes = 0;
+ }
+ net_gain--; // subseqent zeroes save one
+ }
+ else
+ {
+ *outptr++ = 0;
+ net_gain++; // starting a zero count adds one
+ num_zeroes = 1;
+ }
+ inptr++;
+ }
+ else
+ {
+ if (num_zeroes)
+ {
+ *outptr++ = num_zeroes;
+ num_zeroes = 0;
+ }
+ *outptr++ = *inptr++;
+ }
+ }
+
+ if (num_zeroes)
+ {
+ *outptr++ = num_zeroes;
+ }
+
+ if (net_gain < 0)
+ {
+ // TODO: babbage: reinstate stat collecting...
+ //mCompressedPacketsOut++;
+ //mUncompressedBytesOut += *data_size;
+
+ *data = encodedSendBuffer;
+ *data_size += net_gain;
+ encodedSendBuffer[0] |= LL_ZERO_CODE_FLAG; // set the head bit to indicate zero coding
+
+ //mCompressedBytesOut += *data_size;
+
+ }
+ //mTotalBytesOut += *data_size;
+
+ return(net_gain);
+}
+
+void LLTemplateMessageBuilder::compressMessage(U8*& buf_ptr, U32& buffer_length)
+{
+ if(ME_ZEROCODED == mCurrentSMessageTemplate->getEncoding())
+ {
+ zero_code(&buf_ptr, &buffer_length);
+ }
+}
+
+bool LLTemplateMessageBuilder::isMessageFull(const char* blockname) const
+{
+ if(mCurrentSendTotal > MTUBYTES)
+ {
+ return true;
+ }
+ if(!blockname)
+ {
+ return false;
+ }
+ char* bnamep = (char*)blockname;
+ S32 max;
+
+ const LLMessageBlock* template_data = mCurrentSMessageTemplate->getBlock(bnamep);
+
+ switch(template_data->mType)
+ {
+ case MBT_SINGLE:
+ max = 1;
+ break;
+ case MBT_MULTIPLE:
+ max = template_data->mNumber;
+ break;
+ case MBT_VARIABLE:
+ default:
+ max = MAX_BLOCKS;
+ break;
+ }
+ if(mCurrentSMessageData->mMemberBlocks[bnamep]->mBlockNumber >= max)
+ {
+ return true;
+ }
+ return false;
+}
+
+static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* template_data, LLMsgData* message_data)
+{
+ S32 result = 0;
+ LLMsgData::msg_blk_data_map_t::const_iterator block_iter = message_data->mMemberBlocks.find(template_data->mName);
+ const LLMsgBlkData* mbci = block_iter->second;
+
+ // ok, if this is the first block of a repeating pack, set
+ // block_count and, if it's type MBT_VARIABLE encode a byte
+ // for how many there are
+ S32 block_count = mbci->mBlockNumber;
+ if (template_data->mType == MBT_VARIABLE)
+ {
+ // remember that mBlockNumber is a S32
+ U8 temp_block_number = (U8)mbci->mBlockNumber;
+ if ((S32)(result + sizeof(U8)) < MAX_BUFFER_SIZE)
+ {
+ memcpy(&buffer[result], &temp_block_number, sizeof(U8));
+ result += sizeof(U8);
+ }
+ else
+ {
+ // Just reporting error is likely not enough. Need
+ // to check how to abort or error out gracefully
+ // from this function. XXXTBD
+ LL_ERRS() << "buildBlock failed. Message excedding "
+ << "sendBuffersize." << LL_ENDL;
+ }
+ }
+ else if (template_data->mType == MBT_MULTIPLE)
+ {
+ if (block_count != template_data->mNumber)
+ {
+ // nope! need to fill it in all the way!
+ LL_ERRS() << "Block " << mbci->mName
+ << " is type MBT_MULTIPLE but only has data for "
+ << block_count << " out of its "
+ << template_data->mNumber << " blocks" << LL_ENDL;
+ }
+ }
+
+ while(block_count > 0)
+ {
+ // now loop through the variables
+ for (LLMsgBlkData::msg_var_data_map_t::const_iterator iter = mbci->mMemberVarData.begin();
+ iter != mbci->mMemberVarData.end(); iter++)
+ {
+ const LLMsgVarData& mvci = *iter;
+ if (mvci.getSize() == -1)
+ {
+ // oops, this variable wasn't ever set!
+ LL_ERRS() << "The variable " << mvci.getName() << " in block "
+ << mbci->mName << " of message "
+ << template_data->mName
+ << " wasn't set prior to buildMessage call" << LL_ENDL;
+ }
+ else
+ {
+ S32 data_size = mvci.getDataSize();
+ if(data_size > 0)
+ {
+ // The type is MVT_VARIABLE, which means that we
+ // need to encode a size argument. Otherwise,
+ // there is no need.
+ S32 size = mvci.getSize();
+ U8 sizeb;
+ U16 sizeh;
+ switch(data_size)
+ {
+ case 1:
+ sizeb = size;
+ htolememcpy(&buffer[result], &sizeb, MVT_U8, 1);
+ break;
+ case 2:
+ sizeh = size;
+ htolememcpy(&buffer[result], &sizeh, MVT_U16, 2);
+ break;
+ case 4:
+ htolememcpy(&buffer[result], &size, MVT_S32, 4);
+ break;
+ default:
+ LL_ERRS() << "Attempting to build variable field with unknown size of " << size << LL_ENDL;
+ break;
+ }
+ result += mvci.getDataSize();
+ }
+
+ // if there is any data to pack, pack it
+ if((mvci.getData() != NULL) && mvci.getSize())
+ {
+ if(result + mvci.getSize() < buffer_size)
+ {
+ memcpy(
+ &buffer[result],
+ mvci.getData(),
+ mvci.getSize());
+ result += mvci.getSize();
+ }
+ else
+ {
+ // Just reporting error is likely not
+ // enough. Need to check how to abort or error
+ // out gracefully from this function. XXXTBD
+ LL_ERRS() << "buildBlock failed. "
+ << "Attempted to pack "
+ << (result + mvci.getSize())
+ << " bytes into a buffer with size "
+ << buffer_size << "." << LL_ENDL;
+ }
+ }
+ }
+ }
+
+ --block_count;
+
+ if (block_iter != message_data->mMemberBlocks.end())
+ {
+ ++block_iter;
+ if (block_iter != message_data->mMemberBlocks.end())
+ {
+ mbci = block_iter->second;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+// make sure that all the desired data is in place and then copy the data into MAX_BUFFER_SIZEd buffer
+U32 LLTemplateMessageBuilder::buildMessage(
+ U8* buffer,
+ U32 buffer_size,
+ U8 offset_to_data)
+{
+ // basic algorithm is to loop through the various pieces, building
+ // size and offset info if we encounter a -1 for mSize at any
+ // point that variable wasn't given data
+
+ // do we have a current message?
+ if (!mCurrentSMessageTemplate)
+ {
+ LL_ERRS() << "newMessage not called prior to buildMessage" << LL_ENDL;
+ return 0;
+ }
+
+ // leave room for flags, packet sequence #, and data offset
+ // information.
+ buffer[PHL_OFFSET] = offset_to_data;
+ U32 result = LL_PACKET_ID_SIZE;
+
+ // encode message number and adjust total_offset
+ if (mCurrentSMessageTemplate->mFrequency == MFT_HIGH)
+ {
+// old, endian-dependant way
+// memcpy(&buffer[result], &mCurrentMessageTemplate->mMessageNumber, sizeof(U8));
+
+// new, independant way
+ buffer[result] = (U8)mCurrentSMessageTemplate->mMessageNumber;
+ result += sizeof(U8);
+ }
+ else if (mCurrentSMessageTemplate->mFrequency == MFT_MEDIUM)
+ {
+ U8 temp = 255;
+ memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
+ result += sizeof(U8);
+
+ // mask off unsightly bits
+ temp = mCurrentSMessageTemplate->mMessageNumber & 255;
+ memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
+ result += sizeof(U8);
+ }
+ else if (mCurrentSMessageTemplate->mFrequency == MFT_LOW)
+ {
+ U8 temp = 255;
+ U16 message_num;
+ memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
+ result += sizeof(U8);
+ memcpy(&buffer[result], &temp, sizeof(U8)); /*Flawfinder: ignore*/
+ result += sizeof(U8);
+
+ // mask off unsightly bits
+ message_num = mCurrentSMessageTemplate->mMessageNumber & 0xFFFF;
+
+ // convert to network byte order
+ message_num = htons(message_num);
+ memcpy(&buffer[result], &message_num, sizeof(U16)); /*Flawfinder: ignore*/
+ result += sizeof(U16);
+ }
+ else
+ {
+ LL_ERRS() << "unexpected message frequency in buildMessage" << LL_ENDL;
+ return 0;
+ }
+
+ // fast forward through the offset and build the message
+ result += offset_to_data;
+ for(LLMessageTemplate::message_block_map_t::const_iterator
+ iter = mCurrentSMessageTemplate->mMemberBlocks.begin(),
+ end = mCurrentSMessageTemplate->mMemberBlocks.end();
+ iter != end;
+ ++iter)
+ {
+ result += buildBlock(buffer + result, buffer_size - result, *iter, mCurrentSMessageData);
+ }
+ mbSBuilt = true;
+
+ return result;
+}
+
+void LLTemplateMessageBuilder::copyFromMessageData(const LLMsgData& data)
+{
+ // copy the blocks
+ // counting variables used to encode multiple block info
+ S32 block_count = 0;
+ char *block_name = NULL;
+
+ // loop through msg blocks to loop through variables, totalling up size
+ // data and filling the new (send) message
+ LLMsgData::msg_blk_data_map_t::const_iterator iter =
+ data.mMemberBlocks.begin();
+ LLMsgData::msg_blk_data_map_t::const_iterator end =
+ data.mMemberBlocks.end();
+ for(; iter != end; ++iter)
+ {
+ const LLMsgBlkData* mbci = iter->second;
+ if(!mbci) continue;
+
+ // do we need to encode a block code?
+ if (block_count == 0)
+ {
+ block_count = mbci->mBlockNumber;
+ block_name = (char *)mbci->mName;
+ }
+
+ // counting down mutliple blocks
+ block_count--;
+
+ nextBlock(block_name);
+
+ // now loop through the variables
+ LLMsgBlkData::msg_var_data_map_t::const_iterator dit = mbci->mMemberVarData.begin();
+ LLMsgBlkData::msg_var_data_map_t::const_iterator dend = mbci->mMemberVarData.end();
+
+ for(; dit != dend; ++dit)
+ {
+ const LLMsgVarData& mvci = *dit;
+ addData(mvci.getName(), mvci.getData(), mvci.getType(), mvci.getSize());
+ }
+ }
+}
+
+//virtual
+void LLTemplateMessageBuilder::copyFromLLSD(const LLSD&)
+{
+ // TODO
+}
+
+//virtual
+void LLTemplateMessageBuilder::setBuilt(bool b) { mbSBuilt = b; }
+
+//virtual
+bool LLTemplateMessageBuilder::isBuilt() const {return mbSBuilt;}
+
+//virtual
+bool LLTemplateMessageBuilder::isClear() const {return mbSClear;}
+
+//virtual
+S32 LLTemplateMessageBuilder::getMessageSize() {return mCurrentSendTotal;}
+
+//virtual
+const char* LLTemplateMessageBuilder::getMessageName() const
+{
+ return mCurrentSMessageName;
+}
diff --git a/indra/llmessage/lltemplatemessagebuilder.h b/indra/llmessage/lltemplatemessagebuilder.h
index f02ed0c06d..bb50b0ab8a 100644
--- a/indra/llmessage/lltemplatemessagebuilder.h
+++ b/indra/llmessage/lltemplatemessagebuilder.h
@@ -1,115 +1,115 @@
-/**
- * @file lltemplatemessagebuilder.h
- * @brief Declaration of LLTemplateMessageBuilder class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTEMPLATEMESSAGEBUILDER_H
-#define LL_LLTEMPLATEMESSAGEBUILDER_H
-
-#include <map>
-
-#include "llmessagebuilder.h"
-#include "llmsgvariabletype.h"
-
-class LLMsgData;
-class LLMessageTemplate;
-class LLMsgBlkData;
-class LLMessageTemplate;
-
-class LLTemplateMessageBuilder : public LLMessageBuilder
-{
-public:
-
- typedef std::map<const char* , LLMessageTemplate*> message_template_name_map_t;
-
- LLTemplateMessageBuilder(const message_template_name_map_t&);
- virtual ~LLTemplateMessageBuilder();
-
- virtual void newMessage(const char* name);
-
- virtual void nextBlock(const char* blockname);
- virtual bool removeLastBlock(); // TODO: babbage: remove this horror...
-
- /** All add* methods expect pointers to canonical varname strings. */
- virtual void addBinaryData(const char *varname, const void *data,
- S32 size);
- virtual void addBOOL(const char* varname, bool b);
- virtual void addS8(const char* varname, S8 s);
- virtual void addU8(const char* varname, U8 u);
- virtual void addS16(const char* varname, S16 i);
- virtual void addU16(const char* varname, U16 i);
- virtual void addF32(const char* varname, F32 f);
- virtual void addS32(const char* varname, S32 s);
- virtual void addU32(const char* varname, U32 u);
- virtual void addU64(const char* varname, U64 lu);
- virtual void addF64(const char* varname, F64 d);
- virtual void addVector3(const char* varname, const LLVector3& vec);
- virtual void addVector4(const char* varname, const LLVector4& vec);
- virtual void addVector3d(const char* varname, const LLVector3d& vec);
- virtual void addQuat(const char* varname, const LLQuaternion& quat);
- virtual void addUUID(const char* varname, const LLUUID& uuid);
- virtual void addIPAddr(const char* varname, const U32 ip);
- virtual void addIPPort(const char* varname, const U16 port);
- virtual void addString(const char* varname, const char* s);
- virtual void addString(const char* varname, const std::string& s);
-
- virtual bool isMessageFull(const char* blockname) const;
- virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
-
- virtual bool isBuilt() const;
- virtual bool isClear() const;
- virtual U32 buildMessage(U8* buffer, U32 buffer_size, U8 offset_to_data);
- /**< Return built message size */
-
- virtual void clearMessage();
-
- // TODO: babbage: remove this horror.
- virtual void setBuilt(bool b);
-
- virtual S32 getMessageSize();
- virtual const char* getMessageName() const;
-
- virtual void copyFromMessageData(const LLMsgData& data);
- virtual void copyFromLLSD(const LLSD&);
-
- LLMsgData* getCurrentMessage() const { return mCurrentSMessageData; }
-private:
- void addData(const char* varname, const void* data,
- EMsgVariableType type, S32 size);
-
- void addData(const char* varname, const void* data,
- EMsgVariableType type);
-
- LLMsgData* mCurrentSMessageData;
- const LLMessageTemplate* mCurrentSMessageTemplate;
- LLMsgBlkData* mCurrentSDataBlock;
- char* mCurrentSMessageName;
- char* mCurrentSBlockName;
- bool mbSBuilt;
- bool mbSClear;
- S32 mCurrentSendTotal;
- const message_template_name_map_t& mMessageTemplates;
-};
-
-#endif // LL_LLTEMPLATEMESSAGEBUILDER_H
+/**
+ * @file lltemplatemessagebuilder.h
+ * @brief Declaration of LLTemplateMessageBuilder class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEMPLATEMESSAGEBUILDER_H
+#define LL_LLTEMPLATEMESSAGEBUILDER_H
+
+#include <map>
+
+#include "llmessagebuilder.h"
+#include "llmsgvariabletype.h"
+
+class LLMsgData;
+class LLMessageTemplate;
+class LLMsgBlkData;
+class LLMessageTemplate;
+
+class LLTemplateMessageBuilder : public LLMessageBuilder
+{
+public:
+
+ typedef std::map<const char* , LLMessageTemplate*> message_template_name_map_t;
+
+ LLTemplateMessageBuilder(const message_template_name_map_t&);
+ virtual ~LLTemplateMessageBuilder();
+
+ virtual void newMessage(const char* name);
+
+ virtual void nextBlock(const char* blockname);
+ virtual bool removeLastBlock(); // TODO: babbage: remove this horror...
+
+ /** All add* methods expect pointers to canonical varname strings. */
+ virtual void addBinaryData(const char *varname, const void *data,
+ S32 size);
+ virtual void addBOOL(const char* varname, bool b);
+ virtual void addS8(const char* varname, S8 s);
+ virtual void addU8(const char* varname, U8 u);
+ virtual void addS16(const char* varname, S16 i);
+ virtual void addU16(const char* varname, U16 i);
+ virtual void addF32(const char* varname, F32 f);
+ virtual void addS32(const char* varname, S32 s);
+ virtual void addU32(const char* varname, U32 u);
+ virtual void addU64(const char* varname, U64 lu);
+ virtual void addF64(const char* varname, F64 d);
+ virtual void addVector3(const char* varname, const LLVector3& vec);
+ virtual void addVector4(const char* varname, const LLVector4& vec);
+ virtual void addVector3d(const char* varname, const LLVector3d& vec);
+ virtual void addQuat(const char* varname, const LLQuaternion& quat);
+ virtual void addUUID(const char* varname, const LLUUID& uuid);
+ virtual void addIPAddr(const char* varname, const U32 ip);
+ virtual void addIPPort(const char* varname, const U16 port);
+ virtual void addString(const char* varname, const char* s);
+ virtual void addString(const char* varname, const std::string& s);
+
+ virtual bool isMessageFull(const char* blockname) const;
+ virtual void compressMessage(U8*& buf_ptr, U32& buffer_length);
+
+ virtual bool isBuilt() const;
+ virtual bool isClear() const;
+ virtual U32 buildMessage(U8* buffer, U32 buffer_size, U8 offset_to_data);
+ /**< Return built message size */
+
+ virtual void clearMessage();
+
+ // TODO: babbage: remove this horror.
+ virtual void setBuilt(bool b);
+
+ virtual S32 getMessageSize();
+ virtual const char* getMessageName() const;
+
+ virtual void copyFromMessageData(const LLMsgData& data);
+ virtual void copyFromLLSD(const LLSD&);
+
+ LLMsgData* getCurrentMessage() const { return mCurrentSMessageData; }
+private:
+ void addData(const char* varname, const void* data,
+ EMsgVariableType type, S32 size);
+
+ void addData(const char* varname, const void* data,
+ EMsgVariableType type);
+
+ LLMsgData* mCurrentSMessageData;
+ const LLMessageTemplate* mCurrentSMessageTemplate;
+ LLMsgBlkData* mCurrentSDataBlock;
+ char* mCurrentSMessageName;
+ char* mCurrentSBlockName;
+ bool mbSBuilt;
+ bool mbSClear;
+ S32 mCurrentSendTotal;
+ const message_template_name_map_t& mMessageTemplates;
+};
+
+#endif // LL_LLTEMPLATEMESSAGEBUILDER_H
diff --git a/indra/llmessage/lltemplatemessagedispatcher.cpp b/indra/llmessage/lltemplatemessagedispatcher.cpp
index ee7a4e7e71..267c201705 100644
--- a/indra/llmessage/lltemplatemessagedispatcher.cpp
+++ b/indra/llmessage/lltemplatemessagedispatcher.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,33 +35,33 @@
LLTemplateMessageDispatcher::LLTemplateMessageDispatcher(LLTemplateMessageReader &template_message_reader) :
- mTemplateMessageReader(template_message_reader)
+ mTemplateMessageReader(template_message_reader)
{
}
void LLTemplateMessageDispatcher::dispatch(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
{
- std::vector<U8> data = message["body"]["binary-template-data"].asBinary();
- U32 size = data.size();
- if(size == 0)
- {
- return;
- }
+ std::vector<U8> data = message["body"]["binary-template-data"].asBinary();
+ U32 size = data.size();
+ if(size == 0)
+ {
+ return;
+ }
- LLHost host;
- host = gMessageSystem->getSender();
+ LLHost host;
+ host = gMessageSystem->getSender();
- bool validate_message = mTemplateMessageReader.validateMessage(&(data[0]), data.size(), host, true);
+ bool validate_message = mTemplateMessageReader.validateMessage(&(data[0]), data.size(), host, true);
- if (validate_message)
- {
- mTemplateMessageReader.readMessage(&(data[0]),host);
- }
- else
- {
- gMessageSystem->clearReceiveState();
- }
+ if (validate_message)
+ {
+ mTemplateMessageReader.readMessage(&(data[0]),host);
+ }
+ else
+ {
+ gMessageSystem->clearReceiveState();
+ }
}
diff --git a/indra/llmessage/lltemplatemessagedispatcher.h b/indra/llmessage/lltemplatemessagedispatcher.h
index fe77f92074..f33e96bb9e 100644
--- a/indra/llmessage/lltemplatemessagedispatcher.h
+++ b/indra/llmessage/lltemplatemessagedispatcher.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,13 +36,13 @@
class LLTemplateMessageDispatcher
{
public:
- LLTemplateMessageDispatcher(LLTemplateMessageReader& template_message_reader);
- void dispatch(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep);
+ LLTemplateMessageDispatcher(LLTemplateMessageReader& template_message_reader);
+ void dispatch(const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep);
private:
- LLTemplateMessageReader &mTemplateMessageReader;
+ LLTemplateMessageReader &mTemplateMessageReader;
};
#endif // LLTEMPLATEMESSAGEDISPATCHER_H
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 064c6e5bd4..46123f0f55 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -1,830 +1,830 @@
-/**
- * @file lltemplatemessagereader.cpp
- * @brief LLTemplateMessageReader class implementation.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "lltemplatemessagereader.h"
-
-#include "llfasttimer.h"
-#include "llmessagebuilder.h"
-#include "llmessagetemplate.h"
-#include "llmath.h"
-#include "llquaternion.h"
-#include "message.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-
-LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
- number_template_map) :
- mReceiveSize(0),
- mCurrentRMessageTemplate(NULL),
- mCurrentRMessageData(NULL),
- mMessageNumbers(number_template_map)
-{
-}
-
-//virtual
-LLTemplateMessageReader::~LLTemplateMessageReader()
-{
- delete mCurrentRMessageData;
- mCurrentRMessageData = NULL;
-}
-
-//virtual
-void LLTemplateMessageReader::clearMessage()
-{
- mReceiveSize = -1;
- mCurrentRMessageTemplate = NULL;
- delete mCurrentRMessageData;
- mCurrentRMessageData = NULL;
-}
-
-void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- {
- LL_ERRS() << "No message waiting for decode 2!" << LL_ENDL;
- return;
- }
-
- if (!mCurrentRMessageData)
- {
- LL_ERRS() << "Invalid mCurrentMessageData in getData!" << LL_ENDL;
- return;
- }
-
- char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference
- char *vnamep = (char *)varname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- {
- LL_ERRS() << "Block " << blockname << " #" << blocknum
- << " not in message " << mCurrentRMessageData->mName << LL_ENDL;
- return;
- }
-
- LLMsgBlkData *msg_block_data = iter->second;
- LLMsgBlkData::msg_var_data_map_t &var_data_map = msg_block_data->mMemberVarData;
-
- if (var_data_map.find(vnamep) == var_data_map.end())
- {
- LL_ERRS() << "Variable "<< vnamep << " not in message "
- << mCurrentRMessageData->mName<< " block " << bnamep << LL_ENDL;
- return;
- }
-
- LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
-
- if (size && size != vardata.getSize())
- {
- LL_ERRS() << "Msg " << mCurrentRMessageData->mName
- << " variable " << vnamep
- << " is size " << vardata.getSize()
- << " but copying into buffer of size " << size
- << LL_ENDL;
- return;
- }
-
-
- const S32 vardata_size = vardata.getSize();
- if( max_size >= vardata_size )
- {
- switch( vardata_size )
- {
- case 1:
- *((U8*)datap) = *((U8*)vardata.getData());
- break;
- case 2:
- *((U16*)datap) = *((U16*)vardata.getData());
- break;
- case 4:
- *((U32*)datap) = *((U32*)vardata.getData());
- break;
- case 8:
- ((U32*)datap)[0] = ((U32*)vardata.getData())[0];
- ((U32*)datap)[1] = ((U32*)vardata.getData())[1];
- break;
- default:
- memcpy(datap, vardata.getData(), vardata_size);
- break;
- }
- }
- else
- {
- LL_WARNS() << "Msg " << mCurrentRMessageData->mName
- << " variable " << vnamep
- << " is size " << vardata.getSize()
- << " but truncated to max size of " << max_size
- << LL_ENDL;
-
- memcpy(datap, vardata.getData(), max_size);
- }
-}
-
-S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- {
- LL_ERRS() << "No message waiting for decode 3!" << LL_ENDL;
- return -1;
- }
-
- if (!mCurrentRMessageData)
- {
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return -1;
- }
-
- char *bnamep = (char *)blockname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- {
- return 0;
- }
-
- return (iter->second)->mBlockNumber;
-}
-
-S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- { // This is a serious error - crash
- LL_ERRS() << "No message waiting for decode 4!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- if (!mCurrentRMessageData)
- { // This is a serious error - crash
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- char *bnamep = (char *)blockname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- { // don't crash
- LL_INFOS() << "Block " << bnamep << " not in message "
- << mCurrentRMessageData->mName << LL_ENDL;
- return LL_BLOCK_NOT_IN_MESSAGE;
- }
-
- char *vnamep = (char *)varname;
-
- LLMsgBlkData* msg_data = iter->second;
- LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-
- if (!vardata.getName())
- { // don't crash
- LL_INFOS() << "Variable " << varname << " not in message "
- << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
- return LL_VARIABLE_NOT_IN_BLOCK;
- }
-
- if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
- { // This is a serious error - crash
- LL_ERRS() << "Block " << bnamep << " isn't type MBT_SINGLE,"
- " use getSize with blocknum argument!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- return vardata.getSize();
-}
-
-S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
-{
- // is there a message ready to go?
- if (mReceiveSize == -1)
- { // This is a serious error - crash
- LL_ERRS() << "No message waiting for decode 5!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- if (!mCurrentRMessageData)
- { // This is a serious error - crash
- LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
- return LL_MESSAGE_ERROR;
- }
-
- char *bnamep = (char *)blockname + blocknum;
- char *vnamep = (char *)varname;
-
- LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
-
- if (iter == mCurrentRMessageData->mMemberBlocks.end())
- { // don't crash
- LL_INFOS() << "Block " << bnamep << " not in message "
- << mCurrentRMessageData->mName << LL_ENDL;
- return LL_BLOCK_NOT_IN_MESSAGE;
- }
-
- LLMsgBlkData* msg_data = iter->second;
- LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
-
- if (!vardata.getName())
- { // don't crash
- LL_INFOS() << "Variable " << vnamep << " not in message "
- << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
- return LL_VARIABLE_NOT_IN_BLOCK;
- }
-
- return vardata.getSize();
-}
-
-void LLTemplateMessageReader::getBinaryData(const char *blockname,
- const char *varname, void *datap,
- S32 size, S32 blocknum,
- S32 max_size)
-{
- getData(blockname, varname, datap, size, blocknum, max_size);
-}
-
-void LLTemplateMessageReader::getS8(const char *block, const char *var,
- S8 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(S8), blocknum);
-}
-
-void LLTemplateMessageReader::getU8(const char *block, const char *var,
- U8 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U8), blocknum);
-}
-
-void LLTemplateMessageReader::getBOOL(const char *block, const char *var,
- bool &b, S32 blocknum )
-{
- U8 value;
- getData(block, var, &value, sizeof(U8), blocknum);
- b = (bool)value;
-}
-
-void LLTemplateMessageReader::getS16(const char *block, const char *var,
- S16 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(S16), blocknum);
-}
-
-void LLTemplateMessageReader::getU16(const char *block, const char *var,
- U16 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U16), blocknum);
-}
-
-void LLTemplateMessageReader::getS32(const char *block, const char *var,
- S32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(S32), blocknum);
-}
-
-void LLTemplateMessageReader::getU32(const char *block, const char *var,
- U32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U32), blocknum);
-}
-
-void LLTemplateMessageReader::getU64(const char *block, const char *var,
- U64 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(U64), blocknum);
-}
-
-void LLTemplateMessageReader::getF32(const char *block, const char *var,
- F32 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(F32), blocknum);
-
- if( !llfinite( d ) )
- {
- LL_WARNS() << "non-finite in getF32Fast " << block << " " << var
- << LL_ENDL;
- d = 0;
- }
-}
-
-void LLTemplateMessageReader::getF64(const char *block, const char *var,
- F64 &d, S32 blocknum)
-{
- getData(block, var, &d, sizeof(F64), blocknum);
-
- if( !llfinite( d ) )
- {
- LL_WARNS() << "non-finite in getF64Fast " << block << " " << var
- << LL_ENDL;
- d = 0;
- }
-}
-
-void LLTemplateMessageReader::getVector3(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector3Fast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-}
-
-void LLTemplateMessageReader::getVector4(const char *block, const char *var,
- LLVector4 &v, S32 blocknum)
-{
- getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector4Fast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-}
-
-void LLTemplateMessageReader::getVector3d(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
-
- if( !v.isFinite() )
- {
- LL_WARNS() << "non-finite in getVector3dFast " << block << " "
- << var << LL_ENDL;
- v.zeroVec();
- }
-
-}
-
-void LLTemplateMessageReader::getQuat(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum)
-{
- LLVector3 vec;
- getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
- if( vec.isFinite() )
- {
- q.unpackFromVector3( vec );
- }
- else
- {
- LL_WARNS() << "non-finite in getQuatFast " << block << " " << var
- << LL_ENDL;
- q.loadIdentity();
- }
-}
-
-void LLTemplateMessageReader::getUUID(const char *block, const char *var,
- LLUUID &u, S32 blocknum)
-{
- getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
-}
-
-inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U32), blocknum);
-}
-
-inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
-{
- getData(block, var, &u, sizeof(U16), blocknum);
- u = ntohs(u);
-}
-
-inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
-{
- s[0] = '\0';
- getData(block, var, s, 0, blocknum, buffer_size);
- s[buffer_size - 1] = '\0';
-}
-
-inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum )
-{
- char s[MTUBYTES + 1]= {0}; // every element is initialized with 0
- getData(block, var, s, 0, blocknum, MTUBYTES);
- s[MTUBYTES] = '\0';
- outstr = s;
-}
-
-//virtual
-S32 LLTemplateMessageReader::getMessageSize() const
-{
- return mReceiveSize;
-}
-
-// Returns template for the message contained in buffer
-bool LLTemplateMessageReader::decodeTemplate(
- const U8* buffer, S32 buffer_size, // inputs
- LLMessageTemplate** msg_template ) // outputs
-{
- const U8* header = buffer + LL_PACKET_ID_SIZE;
-
- // is there a message ready to go?
- if (buffer_size <= 0)
- {
- LL_WARNS() << "No message waiting for decode!" << LL_ENDL;
- return(false);
- }
-
- U32 num = 0;
-
- if (header[0] != 255)
- {
- // high frequency message
- num = header[0];
- }
- else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
- {
- // medium frequency message
- num = (255 << 8) | header[1];
- }
- else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
- {
- // low frequency message
- U16 message_id_U16 = 0;
- // I think this check busts the message system.
- // it appears that if there is a NULL in the message #, it won't copy it....
- // what was the goal?
- //if(header[2])
- memcpy(&message_id_U16, &header[2], 2);
-
- // dependant on endian-ness:
- // U32 temp = (255 << 24) | (255 << 16) | header[2];
-
- // independant of endian-ness:
- message_id_U16 = ntohs(message_id_U16);
- num = 0xFFFF0000 | message_id_U16;
- }
- else // bogus packet received (too short)
- {
- LL_WARNS() << "Packet with unusable length received (too short): "
- << buffer_size << LL_ENDL;
- return(false);
- }
-
- LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
- if (temp)
- {
- *msg_template = temp;
- }
- else
- {
- // MAINT-7482 - make viewer more tolerant of unknown messages.
- LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
- << " received but not registered!" << LL_ENDL;
- //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
- return(false);
- }
-
- return(true);
-}
-
-void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted )
-{
- // we've run off the end of the packet!
- LL_WARNS() << "Ran off end of packet " << mCurrentRMessageTemplate->mName
-// << " with id " << mCurrentRecvPacketID
- << " from " << host
- << " trying to read " << wanted
- << " bytes at position " << where
- << " going past packet end at " << mReceiveSize
- << LL_ENDL;
- if(gMessageSystem->mVerboseLog)
- {
- LL_INFOS() << "MSG: -> " << host << "\tREAD PAST END:\t"
-// << mCurrentRecvPacketID << " "
- << getMessageName() << LL_ENDL;
- }
- gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
-}
-
-static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages");
-
-// decode a given message
-bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
-{
- LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES);
-
- llassert( mReceiveSize >= 0 );
- llassert( mCurrentRMessageTemplate);
- llassert( !mCurrentRMessageData );
- delete mCurrentRMessageData; // just to make sure
-
- // The offset tells us how may bytes to skip after the end of the
- // message name.
- U8 offset = buffer[PHL_OFFSET];
- S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
-
- // create base working data set
- mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
-
- // loop through the template building the data structure as we go
- LLMessageTemplate::message_block_map_t::const_iterator iter;
- for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
- iter != mCurrentRMessageTemplate->mMemberBlocks.end();
- ++iter)
- {
- LLMessageBlock* mbci = *iter;
- U8 repeat_number;
- S32 i;
-
- // how many of this block?
-
- if (mbci->mType == MBT_SINGLE)
- {
- // just one
- repeat_number = 1;
- }
- else if (mbci->mType == MBT_MULTIPLE)
- {
- // a known number
- repeat_number = mbci->mNumber;
- }
- else if (mbci->mType == MBT_VARIABLE)
- {
- // need to read the number from the message
- // repeat number is a single byte
- if (decode_pos >= mReceiveSize)
- {
- // commented out - hetgrid says that missing variable blocks
- // at end of message are legal
- // logRanOffEndOfPacket(sender, decode_pos, 1);
-
- // default to 0 repeats
- repeat_number = 0;
- }
- else
- {
- repeat_number = buffer[decode_pos];
- decode_pos++;
- }
- }
- else
- {
- LL_ERRS() << "Unknown block type" << LL_ENDL;
- return false;
- }
-
- LLMsgBlkData* cur_data_block = NULL;
-
- // now loop through the block
- for (i = 0; i < repeat_number; i++)
- {
- if (i)
- {
- // build new name to prevent collisions
- // TODO: This should really change to a vector
- cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
- cur_data_block->mName = mbci->mName + i;
- }
- else
- {
- cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
- }
-
- // add the block to the message
- mCurrentRMessageData->addBlock(cur_data_block);
-
- // now read the variables
- for (LLMessageBlock::message_variable_map_t::const_iterator iter =
- mbci->mMemberVariables.begin();
- iter != mbci->mMemberVariables.end(); iter++)
- {
- const LLMessageVariable& mvci = **iter;
-
- // ok, build out the variables
- // add variable block
- cur_data_block->addVariable(mvci.getName(), mvci.getType());
-
- // what type of variable?
- if (mvci.getType() == MVT_VARIABLE)
- {
- // variable, get the number of bytes to read from the template
- S32 data_size = mvci.getSize();
- U8 tsizeb = 0;
- U16 tsizeh = 0;
- U32 tsize = 0;
-
- if ((decode_pos + data_size) > mReceiveSize)
- {
- logRanOffEndOfPacket(sender, decode_pos, data_size);
-
- // default to 0 length variable blocks
- tsize = 0;
- }
- else
- {
- switch(data_size)
- {
- case 1:
- htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
- tsize = tsizeb;
- break;
- case 2:
- htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
- tsize = tsizeh;
- break;
- case 4:
- htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
- break;
- default:
- LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;
- break;
- }
- }
- decode_pos += data_size;
-
- cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
- decode_pos += tsize;
- }
- else
- {
- // fixed!
- // so, copy data pointer and set data size to fixed size
- if ((decode_pos + mvci.getSize()) > mReceiveSize)
- {
- logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
-
- // default to 0s.
- U32 size = mvci.getSize();
- std::vector<U8> data(size, 0);
- cur_data_block->addData(mvci.getName(), &(data[0]),
- size, mvci.getType());
- }
- else
- {
- cur_data_block->addData(mvci.getName(),
- &buffer[decode_pos],
- mvci.getSize(),
- mvci.getType());
- }
- decode_pos += mvci.getSize();
- }
- }
- }
- }
-
- if (mCurrentRMessageData->mMemberBlocks.empty()
- && !mCurrentRMessageTemplate->mMemberBlocks.empty())
- {
- LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
- return false;
- }
-
- {
- static LLTimer decode_timer;
-
- if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
- {
- decode_timer.reset();
- }
-
- if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
- {
- LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL;
- }
-
- if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
- {
- F32 decode_time = decode_timer.getElapsedTimeF32();
-
- if (gMessageSystem->getTimingCallback())
- {
- (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
- decode_time,
- gMessageSystem->getTimingCallbackData());
- }
-
- if (LLMessageReader::getTimeDecodes())
- {
- mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
-
- mCurrentRMessageTemplate->mTotalDecoded++;
- mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
-
- if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
- {
- mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
- }
-
-
- if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
- {
- LL_DEBUGS() << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
- mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
- (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << LL_ENDL;
- }
- }
- }
- }
- return true;
-}
-
-bool LLTemplateMessageReader::validateMessage(const U8* buffer,
- S32 buffer_size,
- const LLHost& sender,
- bool trusted)
-{
- mReceiveSize = buffer_size;
- bool valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
- if(valid)
- {
- mCurrentRMessageTemplate->mReceiveCount++;
- //LL_DEBUGS() << "MessageRecvd:"
- // << mCurrentRMessageTemplate->mName
- // << " from " << sender << LL_ENDL;
- }
-
- if (valid && isBanned(trusted))
- {
- LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
- << "received banned message "
- << getMessageName()
- << " from "
- << ((trusted) ? "trusted " : "untrusted ")
- << sender << LL_ENDL;
- valid = false;
- }
-
- if(valid && isUdpBanned())
- {
- LL_WARNS() << "Received UDP black listed message "
- << getMessageName()
- << " from " << sender << LL_ENDL;
- valid = false;
- }
- return valid;
-}
-
-bool LLTemplateMessageReader::readMessage(const U8* buffer,
- const LLHost& sender)
-{
- return decodeData(buffer, sender);
-}
-
-//virtual
-const char* LLTemplateMessageReader::getMessageName() const
-{
- if (!mCurrentRMessageTemplate)
- {
- // no message currently being read
- return "";
- }
- return mCurrentRMessageTemplate->mName;
-}
-
-//virtual
-bool LLTemplateMessageReader::isTrusted() const
-{
- return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
-}
-
-bool LLTemplateMessageReader::isBanned(bool trustedSource) const
-{
- return mCurrentRMessageTemplate->isBanned(trustedSource);
-}
-
-bool LLTemplateMessageReader::isUdpBanned() const
-{
- return mCurrentRMessageTemplate->isUdpBanned();
-}
-
-//virtual
-void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
-{
- if(NULL == mCurrentRMessageTemplate)
- {
- return;
- }
- builder.copyFromMessageData(*mCurrentRMessageData);
-}
+/**
+ * @file lltemplatemessagereader.cpp
+ * @brief LLTemplateMessageReader class implementation.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "lltemplatemessagereader.h"
+
+#include "llfasttimer.h"
+#include "llmessagebuilder.h"
+#include "llmessagetemplate.h"
+#include "llmath.h"
+#include "llquaternion.h"
+#include "message.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+
+LLTemplateMessageReader::LLTemplateMessageReader(message_template_number_map_t&
+ number_template_map) :
+ mReceiveSize(0),
+ mCurrentRMessageTemplate(NULL),
+ mCurrentRMessageData(NULL),
+ mMessageNumbers(number_template_map)
+{
+}
+
+//virtual
+LLTemplateMessageReader::~LLTemplateMessageReader()
+{
+ delete mCurrentRMessageData;
+ mCurrentRMessageData = NULL;
+}
+
+//virtual
+void LLTemplateMessageReader::clearMessage()
+{
+ mReceiveSize = -1;
+ mCurrentRMessageTemplate = NULL;
+ delete mCurrentRMessageData;
+ mCurrentRMessageData = NULL;
+}
+
+void LLTemplateMessageReader::getData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum, S32 max_size)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ {
+ LL_ERRS() << "No message waiting for decode 2!" << LL_ENDL;
+ return;
+ }
+
+ if (!mCurrentRMessageData)
+ {
+ LL_ERRS() << "Invalid mCurrentMessageData in getData!" << LL_ENDL;
+ return;
+ }
+
+ char *bnamep = (char *)blockname + blocknum; // this works because it's just a hash. The bnamep is never derefference
+ char *vnamep = (char *)varname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ {
+ LL_ERRS() << "Block " << blockname << " #" << blocknum
+ << " not in message " << mCurrentRMessageData->mName << LL_ENDL;
+ return;
+ }
+
+ LLMsgBlkData *msg_block_data = iter->second;
+ LLMsgBlkData::msg_var_data_map_t &var_data_map = msg_block_data->mMemberVarData;
+
+ if (var_data_map.find(vnamep) == var_data_map.end())
+ {
+ LL_ERRS() << "Variable "<< vnamep << " not in message "
+ << mCurrentRMessageData->mName<< " block " << bnamep << LL_ENDL;
+ return;
+ }
+
+ LLMsgVarData& vardata = msg_block_data->mMemberVarData[vnamep];
+
+ if (size && size != vardata.getSize())
+ {
+ LL_ERRS() << "Msg " << mCurrentRMessageData->mName
+ << " variable " << vnamep
+ << " is size " << vardata.getSize()
+ << " but copying into buffer of size " << size
+ << LL_ENDL;
+ return;
+ }
+
+
+ const S32 vardata_size = vardata.getSize();
+ if( max_size >= vardata_size )
+ {
+ switch( vardata_size )
+ {
+ case 1:
+ *((U8*)datap) = *((U8*)vardata.getData());
+ break;
+ case 2:
+ *((U16*)datap) = *((U16*)vardata.getData());
+ break;
+ case 4:
+ *((U32*)datap) = *((U32*)vardata.getData());
+ break;
+ case 8:
+ ((U32*)datap)[0] = ((U32*)vardata.getData())[0];
+ ((U32*)datap)[1] = ((U32*)vardata.getData())[1];
+ break;
+ default:
+ memcpy(datap, vardata.getData(), vardata_size);
+ break;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Msg " << mCurrentRMessageData->mName
+ << " variable " << vnamep
+ << " is size " << vardata.getSize()
+ << " but truncated to max size of " << max_size
+ << LL_ENDL;
+
+ memcpy(datap, vardata.getData(), max_size);
+ }
+}
+
+S32 LLTemplateMessageReader::getNumberOfBlocks(const char *blockname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ {
+ LL_ERRS() << "No message waiting for decode 3!" << LL_ENDL;
+ return -1;
+ }
+
+ if (!mCurrentRMessageData)
+ {
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return -1;
+ }
+
+ char *bnamep = (char *)blockname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ {
+ return 0;
+ }
+
+ return (iter->second)->mBlockNumber;
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, const char *varname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ { // This is a serious error - crash
+ LL_ERRS() << "No message waiting for decode 4!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ if (!mCurrentRMessageData)
+ { // This is a serious error - crash
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ char *bnamep = (char *)blockname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ { // don't crash
+ LL_INFOS() << "Block " << bnamep << " not in message "
+ << mCurrentRMessageData->mName << LL_ENDL;
+ return LL_BLOCK_NOT_IN_MESSAGE;
+ }
+
+ char *vnamep = (char *)varname;
+
+ LLMsgBlkData* msg_data = iter->second;
+ LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+
+ if (!vardata.getName())
+ { // don't crash
+ LL_INFOS() << "Variable " << varname << " not in message "
+ << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
+ return LL_VARIABLE_NOT_IN_BLOCK;
+ }
+
+ if (mCurrentRMessageTemplate->mMemberBlocks[bnamep]->mType != MBT_SINGLE)
+ { // This is a serious error - crash
+ LL_ERRS() << "Block " << bnamep << " isn't type MBT_SINGLE,"
+ " use getSize with blocknum argument!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ return vardata.getSize();
+}
+
+S32 LLTemplateMessageReader::getSize(const char *blockname, S32 blocknum, const char *varname)
+{
+ // is there a message ready to go?
+ if (mReceiveSize == -1)
+ { // This is a serious error - crash
+ LL_ERRS() << "No message waiting for decode 5!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ if (!mCurrentRMessageData)
+ { // This is a serious error - crash
+ LL_ERRS() << "Invalid mCurrentRMessageData in getData!" << LL_ENDL;
+ return LL_MESSAGE_ERROR;
+ }
+
+ char *bnamep = (char *)blockname + blocknum;
+ char *vnamep = (char *)varname;
+
+ LLMsgData::msg_blk_data_map_t::const_iterator iter = mCurrentRMessageData->mMemberBlocks.find(bnamep);
+
+ if (iter == mCurrentRMessageData->mMemberBlocks.end())
+ { // don't crash
+ LL_INFOS() << "Block " << bnamep << " not in message "
+ << mCurrentRMessageData->mName << LL_ENDL;
+ return LL_BLOCK_NOT_IN_MESSAGE;
+ }
+
+ LLMsgBlkData* msg_data = iter->second;
+ LLMsgVarData& vardata = msg_data->mMemberVarData[vnamep];
+
+ if (!vardata.getName())
+ { // don't crash
+ LL_INFOS() << "Variable " << vnamep << " not in message "
+ << mCurrentRMessageData->mName << " block " << bnamep << LL_ENDL;
+ return LL_VARIABLE_NOT_IN_BLOCK;
+ }
+
+ return vardata.getSize();
+}
+
+void LLTemplateMessageReader::getBinaryData(const char *blockname,
+ const char *varname, void *datap,
+ S32 size, S32 blocknum,
+ S32 max_size)
+{
+ getData(blockname, varname, datap, size, blocknum, max_size);
+}
+
+void LLTemplateMessageReader::getS8(const char *block, const char *var,
+ S8 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(S8), blocknum);
+}
+
+void LLTemplateMessageReader::getU8(const char *block, const char *var,
+ U8 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U8), blocknum);
+}
+
+void LLTemplateMessageReader::getBOOL(const char *block, const char *var,
+ bool &b, S32 blocknum )
+{
+ U8 value;
+ getData(block, var, &value, sizeof(U8), blocknum);
+ b = (bool)value;
+}
+
+void LLTemplateMessageReader::getS16(const char *block, const char *var,
+ S16 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(S16), blocknum);
+}
+
+void LLTemplateMessageReader::getU16(const char *block, const char *var,
+ U16 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U16), blocknum);
+}
+
+void LLTemplateMessageReader::getS32(const char *block, const char *var,
+ S32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(S32), blocknum);
+}
+
+void LLTemplateMessageReader::getU32(const char *block, const char *var,
+ U32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U32), blocknum);
+}
+
+void LLTemplateMessageReader::getU64(const char *block, const char *var,
+ U64 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(U64), blocknum);
+}
+
+void LLTemplateMessageReader::getF32(const char *block, const char *var,
+ F32 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(F32), blocknum);
+
+ if( !llfinite( d ) )
+ {
+ LL_WARNS() << "non-finite in getF32Fast " << block << " " << var
+ << LL_ENDL;
+ d = 0;
+ }
+}
+
+void LLTemplateMessageReader::getF64(const char *block, const char *var,
+ F64 &d, S32 blocknum)
+{
+ getData(block, var, &d, sizeof(F64), blocknum);
+
+ if( !llfinite( d ) )
+ {
+ LL_WARNS() << "non-finite in getF64Fast " << block << " " << var
+ << LL_ENDL;
+ d = 0;
+ }
+}
+
+void LLTemplateMessageReader::getVector3(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector3Fast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+}
+
+void LLTemplateMessageReader::getVector4(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum)
+{
+ getData(block, var, &v.mV[0], sizeof(v.mV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector4Fast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+}
+
+void LLTemplateMessageReader::getVector3d(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ getData(block, var, &v.mdV[0], sizeof(v.mdV), blocknum);
+
+ if( !v.isFinite() )
+ {
+ LL_WARNS() << "non-finite in getVector3dFast " << block << " "
+ << var << LL_ENDL;
+ v.zeroVec();
+ }
+
+}
+
+void LLTemplateMessageReader::getQuat(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum)
+{
+ LLVector3 vec;
+ getData(block, var, &vec.mV[0], sizeof(vec.mV), blocknum);
+ if( vec.isFinite() )
+ {
+ q.unpackFromVector3( vec );
+ }
+ else
+ {
+ LL_WARNS() << "non-finite in getQuatFast " << block << " " << var
+ << LL_ENDL;
+ q.loadIdentity();
+ }
+}
+
+void LLTemplateMessageReader::getUUID(const char *block, const char *var,
+ LLUUID &u, S32 blocknum)
+{
+ getData(block, var, &u.mData[0], sizeof(u.mData), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPAddr(const char *block, const char *var, U32 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U32), blocknum);
+}
+
+inline void LLTemplateMessageReader::getIPPort(const char *block, const char *var, U16 &u, S32 blocknum)
+{
+ getData(block, var, &u, sizeof(U16), blocknum);
+ u = ntohs(u);
+}
+
+inline void LLTemplateMessageReader::getString(const char *block, const char *var, S32 buffer_size, char *s, S32 blocknum )
+{
+ s[0] = '\0';
+ getData(block, var, s, 0, blocknum, buffer_size);
+ s[buffer_size - 1] = '\0';
+}
+
+inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum )
+{
+ char s[MTUBYTES + 1]= {0}; // every element is initialized with 0
+ getData(block, var, s, 0, blocknum, MTUBYTES);
+ s[MTUBYTES] = '\0';
+ outstr = s;
+}
+
+//virtual
+S32 LLTemplateMessageReader::getMessageSize() const
+{
+ return mReceiveSize;
+}
+
+// Returns template for the message contained in buffer
+bool LLTemplateMessageReader::decodeTemplate(
+ const U8* buffer, S32 buffer_size, // inputs
+ LLMessageTemplate** msg_template ) // outputs
+{
+ const U8* header = buffer + LL_PACKET_ID_SIZE;
+
+ // is there a message ready to go?
+ if (buffer_size <= 0)
+ {
+ LL_WARNS() << "No message waiting for decode!" << LL_ENDL;
+ return(false);
+ }
+
+ U32 num = 0;
+
+ if (header[0] != 255)
+ {
+ // high frequency message
+ num = header[0];
+ }
+ else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 1)) && (header[1] != 255))
+ {
+ // medium frequency message
+ num = (255 << 8) | header[1];
+ }
+ else if ((buffer_size >= ((S32) LL_MINIMUM_VALID_PACKET_SIZE + 3)) && (header[1] == 255))
+ {
+ // low frequency message
+ U16 message_id_U16 = 0;
+ // I think this check busts the message system.
+ // it appears that if there is a NULL in the message #, it won't copy it....
+ // what was the goal?
+ //if(header[2])
+ memcpy(&message_id_U16, &header[2], 2);
+
+ // dependant on endian-ness:
+ // U32 temp = (255 << 24) | (255 << 16) | header[2];
+
+ // independant of endian-ness:
+ message_id_U16 = ntohs(message_id_U16);
+ num = 0xFFFF0000 | message_id_U16;
+ }
+ else // bogus packet received (too short)
+ {
+ LL_WARNS() << "Packet with unusable length received (too short): "
+ << buffer_size << LL_ENDL;
+ return(false);
+ }
+
+ LLMessageTemplate* temp = get_ptr_in_map(mMessageNumbers,num);
+ if (temp)
+ {
+ *msg_template = temp;
+ }
+ else
+ {
+ // MAINT-7482 - make viewer more tolerant of unknown messages.
+ LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
+ << " received but not registered!" << LL_ENDL;
+ //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
+ return(false);
+ }
+
+ return(true);
+}
+
+void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted )
+{
+ // we've run off the end of the packet!
+ LL_WARNS() << "Ran off end of packet " << mCurrentRMessageTemplate->mName
+// << " with id " << mCurrentRecvPacketID
+ << " from " << host
+ << " trying to read " << wanted
+ << " bytes at position " << where
+ << " going past packet end at " << mReceiveSize
+ << LL_ENDL;
+ if(gMessageSystem->mVerboseLog)
+ {
+ LL_INFOS() << "MSG: -> " << host << "\tREAD PAST END:\t"
+// << mCurrentRecvPacketID << " "
+ << getMessageName() << LL_ENDL;
+ }
+ gMessageSystem->callExceptionFunc(MX_RAN_OFF_END_OF_PACKET);
+}
+
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages");
+
+// decode a given message
+bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
+{
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES);
+
+ llassert( mReceiveSize >= 0 );
+ llassert( mCurrentRMessageTemplate);
+ llassert( !mCurrentRMessageData );
+ delete mCurrentRMessageData; // just to make sure
+
+ // The offset tells us how may bytes to skip after the end of the
+ // message name.
+ U8 offset = buffer[PHL_OFFSET];
+ S32 decode_pos = LL_PACKET_ID_SIZE + (S32)(mCurrentRMessageTemplate->mFrequency) + offset;
+
+ // create base working data set
+ mCurrentRMessageData = new LLMsgData(mCurrentRMessageTemplate->mName);
+
+ // loop through the template building the data structure as we go
+ LLMessageTemplate::message_block_map_t::const_iterator iter;
+ for(iter = mCurrentRMessageTemplate->mMemberBlocks.begin();
+ iter != mCurrentRMessageTemplate->mMemberBlocks.end();
+ ++iter)
+ {
+ LLMessageBlock* mbci = *iter;
+ U8 repeat_number;
+ S32 i;
+
+ // how many of this block?
+
+ if (mbci->mType == MBT_SINGLE)
+ {
+ // just one
+ repeat_number = 1;
+ }
+ else if (mbci->mType == MBT_MULTIPLE)
+ {
+ // a known number
+ repeat_number = mbci->mNumber;
+ }
+ else if (mbci->mType == MBT_VARIABLE)
+ {
+ // need to read the number from the message
+ // repeat number is a single byte
+ if (decode_pos >= mReceiveSize)
+ {
+ // commented out - hetgrid says that missing variable blocks
+ // at end of message are legal
+ // logRanOffEndOfPacket(sender, decode_pos, 1);
+
+ // default to 0 repeats
+ repeat_number = 0;
+ }
+ else
+ {
+ repeat_number = buffer[decode_pos];
+ decode_pos++;
+ }
+ }
+ else
+ {
+ LL_ERRS() << "Unknown block type" << LL_ENDL;
+ return false;
+ }
+
+ LLMsgBlkData* cur_data_block = NULL;
+
+ // now loop through the block
+ for (i = 0; i < repeat_number; i++)
+ {
+ if (i)
+ {
+ // build new name to prevent collisions
+ // TODO: This should really change to a vector
+ cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+ cur_data_block->mName = mbci->mName + i;
+ }
+ else
+ {
+ cur_data_block = new LLMsgBlkData(mbci->mName, repeat_number);
+ }
+
+ // add the block to the message
+ mCurrentRMessageData->addBlock(cur_data_block);
+
+ // now read the variables
+ for (LLMessageBlock::message_variable_map_t::const_iterator iter =
+ mbci->mMemberVariables.begin();
+ iter != mbci->mMemberVariables.end(); iter++)
+ {
+ const LLMessageVariable& mvci = **iter;
+
+ // ok, build out the variables
+ // add variable block
+ cur_data_block->addVariable(mvci.getName(), mvci.getType());
+
+ // what type of variable?
+ if (mvci.getType() == MVT_VARIABLE)
+ {
+ // variable, get the number of bytes to read from the template
+ S32 data_size = mvci.getSize();
+ U8 tsizeb = 0;
+ U16 tsizeh = 0;
+ U32 tsize = 0;
+
+ if ((decode_pos + data_size) > mReceiveSize)
+ {
+ logRanOffEndOfPacket(sender, decode_pos, data_size);
+
+ // default to 0 length variable blocks
+ tsize = 0;
+ }
+ else
+ {
+ switch(data_size)
+ {
+ case 1:
+ htolememcpy(&tsizeb, &buffer[decode_pos], MVT_U8, 1);
+ tsize = tsizeb;
+ break;
+ case 2:
+ htolememcpy(&tsizeh, &buffer[decode_pos], MVT_U16, 2);
+ tsize = tsizeh;
+ break;
+ case 4:
+ htolememcpy(&tsize, &buffer[decode_pos], MVT_U32, 4);
+ break;
+ default:
+ LL_ERRS() << "Attempting to read variable field with unknown size of " << data_size << LL_ENDL;
+ break;
+ }
+ }
+ decode_pos += data_size;
+
+ cur_data_block->addData(mvci.getName(), &buffer[decode_pos], tsize, mvci.getType());
+ decode_pos += tsize;
+ }
+ else
+ {
+ // fixed!
+ // so, copy data pointer and set data size to fixed size
+ if ((decode_pos + mvci.getSize()) > mReceiveSize)
+ {
+ logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
+
+ // default to 0s.
+ U32 size = mvci.getSize();
+ std::vector<U8> data(size, 0);
+ cur_data_block->addData(mvci.getName(), &(data[0]),
+ size, mvci.getType());
+ }
+ else
+ {
+ cur_data_block->addData(mvci.getName(),
+ &buffer[decode_pos],
+ mvci.getSize(),
+ mvci.getType());
+ }
+ decode_pos += mvci.getSize();
+ }
+ }
+ }
+ }
+
+ if (mCurrentRMessageData->mMemberBlocks.empty()
+ && !mCurrentRMessageTemplate->mMemberBlocks.empty())
+ {
+ LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
+ return false;
+ }
+
+ {
+ static LLTimer decode_timer;
+
+ if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+ {
+ decode_timer.reset();
+ }
+
+ if( !mCurrentRMessageTemplate->callHandlerFunc(gMessageSystem) )
+ {
+ LL_WARNS() << "Message from " << sender << " with no handler function received: " << mCurrentRMessageTemplate->mName << LL_ENDL;
+ }
+
+ if(LLMessageReader::getTimeDecodes() || gMessageSystem->getTimingCallback())
+ {
+ F32 decode_time = decode_timer.getElapsedTimeF32();
+
+ if (gMessageSystem->getTimingCallback())
+ {
+ (gMessageSystem->getTimingCallback())(mCurrentRMessageTemplate->mName,
+ decode_time,
+ gMessageSystem->getTimingCallbackData());
+ }
+
+ if (LLMessageReader::getTimeDecodes())
+ {
+ mCurrentRMessageTemplate->mDecodeTimeThisFrame += decode_time;
+
+ mCurrentRMessageTemplate->mTotalDecoded++;
+ mCurrentRMessageTemplate->mTotalDecodeTime += decode_time;
+
+ if( mCurrentRMessageTemplate->mMaxDecodeTimePerMsg < decode_time )
+ {
+ mCurrentRMessageTemplate->mMaxDecodeTimePerMsg = decode_time;
+ }
+
+
+ if(decode_time > LLMessageReader::getTimeDecodesSpamThreshold())
+ {
+ LL_DEBUGS() << "--------- Message " << mCurrentRMessageTemplate->mName << " decode took " << decode_time << " seconds. (" <<
+ mCurrentRMessageTemplate->mMaxDecodeTimePerMsg << " max, " <<
+ (mCurrentRMessageTemplate->mTotalDecodeTime / mCurrentRMessageTemplate->mTotalDecoded) << " avg)" << LL_ENDL;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool LLTemplateMessageReader::validateMessage(const U8* buffer,
+ S32 buffer_size,
+ const LLHost& sender,
+ bool trusted)
+{
+ mReceiveSize = buffer_size;
+ bool valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
+ if(valid)
+ {
+ mCurrentRMessageTemplate->mReceiveCount++;
+ //LL_DEBUGS() << "MessageRecvd:"
+ // << mCurrentRMessageTemplate->mName
+ // << " from " << sender << LL_ENDL;
+ }
+
+ if (valid && isBanned(trusted))
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::checkMessages "
+ << "received banned message "
+ << getMessageName()
+ << " from "
+ << ((trusted) ? "trusted " : "untrusted ")
+ << sender << LL_ENDL;
+ valid = false;
+ }
+
+ if(valid && isUdpBanned())
+ {
+ LL_WARNS() << "Received UDP black listed message "
+ << getMessageName()
+ << " from " << sender << LL_ENDL;
+ valid = false;
+ }
+ return valid;
+}
+
+bool LLTemplateMessageReader::readMessage(const U8* buffer,
+ const LLHost& sender)
+{
+ return decodeData(buffer, sender);
+}
+
+//virtual
+const char* LLTemplateMessageReader::getMessageName() const
+{
+ if (!mCurrentRMessageTemplate)
+ {
+ // no message currently being read
+ return "";
+ }
+ return mCurrentRMessageTemplate->mName;
+}
+
+//virtual
+bool LLTemplateMessageReader::isTrusted() const
+{
+ return mCurrentRMessageTemplate->getTrust() == MT_TRUST;
+}
+
+bool LLTemplateMessageReader::isBanned(bool trustedSource) const
+{
+ return mCurrentRMessageTemplate->isBanned(trustedSource);
+}
+
+bool LLTemplateMessageReader::isUdpBanned() const
+{
+ return mCurrentRMessageTemplate->isUdpBanned();
+}
+
+//virtual
+void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
+{
+ if(NULL == mCurrentRMessageTemplate)
+ {
+ return;
+ }
+ builder.copyFromMessageData(*mCurrentRMessageData);
+}
diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h
index 14656230e3..0b06f6d23a 100644
--- a/indra/llmessage/lltemplatemessagereader.h
+++ b/indra/llmessage/lltemplatemessagereader.h
@@ -1,127 +1,127 @@
-/**
- * @file lltemplatemessagereader.h
- * @brief Declaration of LLTemplateMessageReader class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTEMPLATEMESSAGEREADER_H
-#define LL_LLTEMPLATEMESSAGEREADER_H
-
-#include "llmessagereader.h"
-
-#include <map>
-
-class LLMessageTemplate;
-class LLMsgData;
-
-class LLTemplateMessageReader : public LLMessageReader
-{
-public:
-
- typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
-
- LLTemplateMessageReader(message_template_number_map_t&);
- virtual ~LLTemplateMessageReader();
-
- /** All get* methods expect pointers to canonical strings. */
- virtual void getBinaryData(const char *blockname, const char *varname,
- void *datap, S32 size, S32 blocknum = 0,
- S32 max_size = S32_MAX);
- virtual void getBOOL(const char *block, const char *var, bool &data,
- S32 blocknum = 0);
- virtual void getS8(const char *block, const char *var, S8 &data,
- S32 blocknum = 0);
- virtual void getU8(const char *block, const char *var, U8 &data,
- S32 blocknum = 0);
- virtual void getS16(const char *block, const char *var, S16 &data,
- S32 blocknum = 0);
- virtual void getU16(const char *block, const char *var, U16 &data,
- S32 blocknum = 0);
- virtual void getS32(const char *block, const char *var, S32 &data,
- S32 blocknum = 0);
- virtual void getF32(const char *block, const char *var, F32 &data,
- S32 blocknum = 0);
- virtual void getU32(const char *block, const char *var, U32 &data,
- S32 blocknum = 0);
- virtual void getU64(const char *block, const char *var, U64 &data,
- S32 blocknum = 0);
- virtual void getF64(const char *block, const char *var, F64 &data,
- S32 blocknum = 0);
- virtual void getVector3(const char *block, const char *var,
- LLVector3 &vec, S32 blocknum = 0);
- virtual void getVector4(const char *block, const char *var,
- LLVector4 &vec, S32 blocknum = 0);
- virtual void getVector3d(const char *block, const char *var,
- LLVector3d &vec, S32 blocknum = 0);
- virtual void getQuat(const char *block, const char *var, LLQuaternion &q,
- S32 blocknum = 0);
- virtual void getUUID(const char *block, const char *var, LLUUID &uuid,
- S32 blocknum = 0);
- virtual void getIPAddr(const char *block, const char *var, U32 &ip,
- S32 blocknum = 0);
- virtual void getIPPort(const char *block, const char *var, U16 &port,
- S32 blocknum = 0);
- virtual void getString(const char *block, const char *var,
- S32 buffer_size, char *buffer, S32 blocknum = 0);
- virtual void getString(const char *block, const char *var, std::string& outstr,
- S32 blocknum = 0);
-
- virtual S32 getNumberOfBlocks(const char *blockname);
- virtual S32 getSize(const char *blockname, const char *varname);
- virtual S32 getSize(const char *blockname, S32 blocknum,
- const char *varname);
-
- virtual void clearMessage();
-
- virtual const char* getMessageName() const;
- virtual S32 getMessageSize() const;
-
- virtual void copyToBuilder(LLMessageBuilder&) const;
-
- bool validateMessage(const U8* buffer, S32 buffer_size,
- const LLHost& sender, bool trusted = false);
- bool readMessage(const U8* buffer, const LLHost& sender);
-
- bool isTrusted() const;
- bool isBanned(bool trusted_source) const;
- bool isUdpBanned() const;
-
-private:
-
- void getData(const char *blockname, const char *varname, void *datap,
- S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
-
- bool decodeTemplate(const U8* buffer, S32 buffer_size, // inputs
- LLMessageTemplate** msg_template ); // outputs
-
- void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted );
-
- bool decodeData(const U8* buffer, const LLHost& sender );
-
- S32 mReceiveSize;
- LLMessageTemplate* mCurrentRMessageTemplate;
- LLMsgData* mCurrentRMessageData;
- message_template_number_map_t& mMessageNumbers;
-};
-
-#endif // LL_LLTEMPLATEMESSAGEREADER_H
+/**
+ * @file lltemplatemessagereader.h
+ * @brief Declaration of LLTemplateMessageReader class.
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTEMPLATEMESSAGEREADER_H
+#define LL_LLTEMPLATEMESSAGEREADER_H
+
+#include "llmessagereader.h"
+
+#include <map>
+
+class LLMessageTemplate;
+class LLMsgData;
+
+class LLTemplateMessageReader : public LLMessageReader
+{
+public:
+
+ typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
+
+ LLTemplateMessageReader(message_template_number_map_t&);
+ virtual ~LLTemplateMessageReader();
+
+ /** All get* methods expect pointers to canonical strings. */
+ virtual void getBinaryData(const char *blockname, const char *varname,
+ void *datap, S32 size, S32 blocknum = 0,
+ S32 max_size = S32_MAX);
+ virtual void getBOOL(const char *block, const char *var, bool &data,
+ S32 blocknum = 0);
+ virtual void getS8(const char *block, const char *var, S8 &data,
+ S32 blocknum = 0);
+ virtual void getU8(const char *block, const char *var, U8 &data,
+ S32 blocknum = 0);
+ virtual void getS16(const char *block, const char *var, S16 &data,
+ S32 blocknum = 0);
+ virtual void getU16(const char *block, const char *var, U16 &data,
+ S32 blocknum = 0);
+ virtual void getS32(const char *block, const char *var, S32 &data,
+ S32 blocknum = 0);
+ virtual void getF32(const char *block, const char *var, F32 &data,
+ S32 blocknum = 0);
+ virtual void getU32(const char *block, const char *var, U32 &data,
+ S32 blocknum = 0);
+ virtual void getU64(const char *block, const char *var, U64 &data,
+ S32 blocknum = 0);
+ virtual void getF64(const char *block, const char *var, F64 &data,
+ S32 blocknum = 0);
+ virtual void getVector3(const char *block, const char *var,
+ LLVector3 &vec, S32 blocknum = 0);
+ virtual void getVector4(const char *block, const char *var,
+ LLVector4 &vec, S32 blocknum = 0);
+ virtual void getVector3d(const char *block, const char *var,
+ LLVector3d &vec, S32 blocknum = 0);
+ virtual void getQuat(const char *block, const char *var, LLQuaternion &q,
+ S32 blocknum = 0);
+ virtual void getUUID(const char *block, const char *var, LLUUID &uuid,
+ S32 blocknum = 0);
+ virtual void getIPAddr(const char *block, const char *var, U32 &ip,
+ S32 blocknum = 0);
+ virtual void getIPPort(const char *block, const char *var, U16 &port,
+ S32 blocknum = 0);
+ virtual void getString(const char *block, const char *var,
+ S32 buffer_size, char *buffer, S32 blocknum = 0);
+ virtual void getString(const char *block, const char *var, std::string& outstr,
+ S32 blocknum = 0);
+
+ virtual S32 getNumberOfBlocks(const char *blockname);
+ virtual S32 getSize(const char *blockname, const char *varname);
+ virtual S32 getSize(const char *blockname, S32 blocknum,
+ const char *varname);
+
+ virtual void clearMessage();
+
+ virtual const char* getMessageName() const;
+ virtual S32 getMessageSize() const;
+
+ virtual void copyToBuilder(LLMessageBuilder&) const;
+
+ bool validateMessage(const U8* buffer, S32 buffer_size,
+ const LLHost& sender, bool trusted = false);
+ bool readMessage(const U8* buffer, const LLHost& sender);
+
+ bool isTrusted() const;
+ bool isBanned(bool trusted_source) const;
+ bool isUdpBanned() const;
+
+private:
+
+ void getData(const char *blockname, const char *varname, void *datap,
+ S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
+
+ bool decodeTemplate(const U8* buffer, S32 buffer_size, // inputs
+ LLMessageTemplate** msg_template ); // outputs
+
+ void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted );
+
+ bool decodeData(const U8* buffer, const LLHost& sender );
+
+ S32 mReceiveSize;
+ LLMessageTemplate* mCurrentRMessageTemplate;
+ LLMsgData* mCurrentRMessageData;
+ message_template_number_map_t& mMessageNumbers;
+};
+
+#endif // LL_LLTEMPLATEMESSAGEREADER_H
diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp
index 0cfe5dbf38..a3f02204d0 100644
--- a/indra/llmessage/llthrottle.cpp
+++ b/indra/llmessage/llthrottle.cpp
@@ -1,577 +1,577 @@
-/**
- * @file llthrottle.cpp
- * @brief LLThrottle class used for network bandwidth control.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llthrottle.h"
-#include "llmath.h"
-#include "lldatapacker.h"
-#include "message.h"
-
-
-LLThrottle::LLThrottle(const F32 rate)
-{
- mRate = rate;
- mAvailable = 0.f;
- mLookaheadSecs = 0.25f;
- mLastSendTime = LLMessageSystem::getMessageTimeSeconds(true);
-}
-
-
-void LLThrottle::setRate(const F32 rate)
-{
- // Need to accumulate available bits when adjusting the rate.
- mAvailable = getAvailable();
- mLastSendTime = LLMessageSystem::getMessageTimeSeconds();
- mRate = rate;
-}
-
-F32 LLThrottle::getAvailable()
-{
- // use a temporary bits_available
- // since we don't want to change mBitsAvailable every time
- F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
- return mAvailable + (mRate * elapsed_time.value());
-}
-
-bool LLThrottle::checkOverflow(const F32 amount)
-{
- bool retval = true;
-
- F32 lookahead_amount = mRate * mLookaheadSecs;
-
- // use a temporary bits_available
- // since we don't want to change mBitsAvailable every time
- F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
- F32 amount_available = mAvailable + (mRate * elapsed_time.value());
-
- if ((amount_available >= lookahead_amount) || (amount_available > amount))
- {
- // ...enough space to send this message
- // Also do if > lookahead so we can use if amount > capped amount.
- retval = false;
- }
-
- return retval;
-}
-
-bool LLThrottle::throttleOverflow(const F32 amount)
-{
- F32Seconds elapsed_time;
- F32 lookahead_amount;
- bool retval = true;
-
- lookahead_amount = mRate * mLookaheadSecs;
-
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
- elapsed_time = mt_sec - mLastSendTime;
- mLastSendTime = mt_sec;
-
- mAvailable += mRate * elapsed_time.value();
-
- if (mAvailable >= lookahead_amount)
- {
- // ...channel completely open, so allow send regardless
- // of size. This allows sends on very low BPS channels.
- mAvailable = lookahead_amount;
- retval = false;
- }
- else if (mAvailable > amount)
- {
- // ...enough space to send this message
- retval = false;
- }
-
- // We actually already sent the bits.
- mAvailable -= amount;
-
- // What if bitsavailable goes negative?
- // That's OK, because it means someone is banging on the channel,
- // so we need some time to recover.
-
- return retval;
-}
-
-
-
-const F32 THROTTLE_LOOKAHEAD_TIME = 1.f; // seconds
-
-// Make sure that we don't set above these
-// values, even if the client asks to be set
-// higher
-// Note that these values are replicated on the
-// client side to set max bandwidth throttling there,
-// in llviewerthrottle.cpp. These values are the sum
-// of the top two tiers of bandwidth there.
-
-F32 gThrottleMaximumBPS[TC_EOF] =
-{
- 150000.f, // TC_RESEND
- 170000.f, // TC_LAND
- 34000.f, // TC_WIND
- 34000.f, // TC_CLOUD
- 446000.f, // TC_TASK
- 446000.f, // TC_TEXTURE
- 220000.f, // TC_ASSET
-};
-
-// Start low until viewer informs us of capability
-// Asset and resend get high values, since they
-// aren't used JUST by the viewer necessarily.
-// This is a HACK and should be dealt with more properly on
-// circuit creation.
-
-F32 gThrottleDefaultBPS[TC_EOF] =
-{
- 100000.f, // TC_RESEND
- 4000.f, // TC_LAND
- 4000.f, // TC_WIND
- 4000.f, // TC_CLOUD
- 4000.f, // TC_TASK
- 4000.f, // TC_TEXTURE
- 100000.f, // TC_ASSET
-};
-
-// Don't throttle down lower than this
-// This potentially wastes 50 kbps, but usually
-// wont.
-F32 gThrottleMinimumBPS[TC_EOF] =
-{
- 10000.f, // TC_RESEND
- 10000.f, // TC_LAND
- 4000.f, // TC_WIND
- 4000.f, // TC_CLOUD
- 20000.f, // TC_TASK
- 10000.f, // TC_TEXTURE
- 10000.f, // TC_ASSET
-};
-
-const char* THROTTLE_NAMES[TC_EOF] =
-{
- "Resend ",
- "Land ",
- "Wind ",
- "Cloud ",
- "Task ",
- "Texture",
- "Asset "
-};
-
-LLThrottleGroup::LLThrottleGroup()
-{
- S32 i;
- for (i = 0; i < TC_EOF; i++)
- {
- mThrottleTotal[i] = gThrottleDefaultBPS[i];
- mNominalBPS[i] = gThrottleDefaultBPS[i];
- }
-
- resetDynamicAdjust();
-}
-
-void LLThrottleGroup::packThrottle(LLDataPacker &dp) const
-{
- S32 i;
- for (i = 0; i < TC_EOF; i++)
- {
- dp.packF32(mThrottleTotal[i], "Throttle");
- }
-}
-
-void LLThrottleGroup::unpackThrottle(LLDataPacker &dp)
-{
- S32 i;
- for (i = 0; i < TC_EOF; i++)
- {
- F32 temp_throttle;
- dp.unpackF32(temp_throttle, "Throttle");
- temp_throttle = llclamp(temp_throttle, 0.f, 2250000.f);
- mThrottleTotal[i] = temp_throttle;
- if(mThrottleTotal[i] > gThrottleMaximumBPS[i])
- {
- mThrottleTotal[i] = gThrottleMaximumBPS[i];
- }
- }
-}
-
-// Call this whenever mNominalBPS changes. Need to reset
-// the measurement systems. In the future, we should look
-// into NOT resetting the system.
-void LLThrottleGroup::resetDynamicAdjust()
-{
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
- S32 i;
- for (i = 0; i < TC_EOF; i++)
- {
- mCurrentBPS[i] = mNominalBPS[i];
- mBitsAvailable[i] = mNominalBPS[i] * THROTTLE_LOOKAHEAD_TIME;
- mLastSendTime[i] = mt_sec;
- mBitsSentThisPeriod[i] = 0;
- mBitsSentHistory[i] = 0;
- }
- mDynamicAdjustTime = mt_sec;
-}
-
-
-bool LLThrottleGroup::setNominalBPS(F32* throttle_vec)
-{
- bool changed = false;
- S32 i;
- for (i = 0; i < TC_EOF; i++)
- {
- if (mNominalBPS[i] != throttle_vec[i])
- {
- changed = true;
- mNominalBPS[i] = throttle_vec[i];
- }
- }
-
- // If we changed the nominal settings, reset the dynamic
- // adjustment subsystem.
- if (changed)
- {
- resetDynamicAdjust();
- }
-
- return changed;
-}
-
-// Return bits available in the channel
-S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
-{
- S32 retval = 0;
-
- F32 category_bps = mCurrentBPS[throttle_cat];
- F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
-
- // use a temporary bits_available
- // since we don't want to change mBitsAvailable every time
- F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
- F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
-
- if (bits_available >= lookahead_bits)
- {
- retval = (S32) gThrottleMaximumBPS[throttle_cat];
- }
- else
- {
- retval = (S32) bits_available;
- }
-
- return retval;
-}
-
-
-bool LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
-{
- bool retval = true;
-
- F32 category_bps = mCurrentBPS[throttle_cat];
- F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
-
- // use a temporary bits_available
- // since we don't want to change mBitsAvailable every time
- F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
- F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
-
- if (bits_available >= lookahead_bits)
- {
- // ...channel completely open, so allow send regardless
- // of size. This allows sends on very low BPS channels.
- mBitsAvailable[throttle_cat] = lookahead_bits;
- retval = false;
- }
- else if ( bits_available > bits )
- {
- // ...enough space to send this message
- retval = false;
- }
-
- return retval;
-}
-
-bool LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
-{
- F32Seconds elapsed_time;
- F32 category_bps;
- F32 lookahead_bits;
- bool retval = true;
-
- category_bps = mCurrentBPS[throttle_cat];
- lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
-
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
- elapsed_time = mt_sec - mLastSendTime[throttle_cat];
- mLastSendTime[throttle_cat] = mt_sec;
- mBitsAvailable[throttle_cat] += category_bps * elapsed_time.value();
-
- if (mBitsAvailable[throttle_cat] >= lookahead_bits)
- {
- // ...channel completely open, so allow send regardless
- // of size. This allows sends on very low BPS channels.
- mBitsAvailable[throttle_cat] = lookahead_bits;
- retval = false;
- }
- else if ( mBitsAvailable[throttle_cat] > bits )
- {
- // ...enough space to send this message
- retval = false;
- }
-
- // We actually already sent the bits.
- mBitsAvailable[throttle_cat] -= bits;
-
- mBitsSentThisPeriod[throttle_cat] += bits;
-
- // What if bitsavailable goes negative?
- // That's OK, because it means someone is banging on the channel,
- // so we need some time to recover.
-
- return retval;
-}
-
-
-bool LLThrottleGroup::dynamicAdjust()
-{
- const F32Seconds DYNAMIC_ADJUST_TIME(1.0f);
- const F32 CURRENT_PERIOD_WEIGHT = .25f; // how much weight to give to last period while determining BPS utilization
- const F32 BUSY_PERCENT = 0.75f; // if use more than this fraction of BPS, you are busy
- const F32 IDLE_PERCENT = 0.70f; // if use less than this fraction, you are "idle"
- const F32 TRANSFER_PERCENT = 0.90f; // how much unused bandwidth to take away each adjustment
- const F32 RECOVER_PERCENT = 0.25f; // how much to give back during recovery phase
-
- S32 i;
-
- F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
-
- // Only dynamically adjust every few seconds
- if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME)
- {
- return false;
- }
- mDynamicAdjustTime = mt_sec;
-
- // Update historical information
- for (i = 0; i < TC_EOF; i++)
- {
- if (mBitsSentHistory[i] == 0)
- {
- // first run, just copy current period
- mBitsSentHistory[i] = mBitsSentThisPeriod[i];
- }
- else
- {
- // have some history, so weight accordingly
- mBitsSentHistory[i] = (1.f - CURRENT_PERIOD_WEIGHT) * mBitsSentHistory[i]
- + CURRENT_PERIOD_WEIGHT * mBitsSentThisPeriod[i];
- }
-
- mBitsSentThisPeriod[i] = 0;
- }
-
- // Look for busy channels
- // TODO: Fold into loop above.
- bool channels_busy = false;
- F32 busy_nominal_sum = 0;
- bool channel_busy[TC_EOF];
- bool channel_idle[TC_EOF];
- bool channel_over_nominal[TC_EOF];
-
- for (i = 0; i < TC_EOF; i++)
- {
- // Is this a busy channel?
- if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i])
- {
- // this channel is busy
- channels_busy = true;
- busy_nominal_sum += mNominalBPS[i]; // use for allocation of pooled idle bandwidth
- channel_busy[i] = true;
- }
- else
- {
- channel_busy[i] = false;
- }
-
- // Is this an idle channel?
- if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i]) &&
- (mBitsAvailable[i] > 0))
- {
- channel_idle[i] = true;
- }
- else
- {
- channel_idle[i] = false;
- }
-
- // Is this an overpumped channel?
- if (mCurrentBPS[i] > mNominalBPS[i])
- {
- channel_over_nominal[i] = true;
- }
- else
- {
- channel_over_nominal[i] = false;
- }
- }
-
- if (channels_busy)
- {
- // Some channels are busy. Let's see if we can get them some bandwidth.
- F32 used_bps;
- F32 avail_bps;
- F32 transfer_bps;
-
- F32 pool_bps = 0;
-
- for (i = 0; i < TC_EOF; i++)
- {
- if (channel_idle[i] || channel_over_nominal[i] )
- {
- // Either channel i is idle, or has been overpumped.
- // Therefore it's a candidate to give up some bandwidth.
- // Figure out how much bandwidth it has been using, and how
- // much is available to steal.
- used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME.value();
-
- // CRO make sure to keep a minimum amount of throttle available
- // CRO NB: channels set to < MINIMUM_BPS will never give up bps,
- // which is correct I think
- if (used_bps < gThrottleMinimumBPS[i])
- {
- used_bps = gThrottleMinimumBPS[i];
- }
-
- if (channel_over_nominal[i])
- {
- F32 unused_current = mCurrentBPS[i] - used_bps;
- avail_bps = llmax(mCurrentBPS[i] - mNominalBPS[i], unused_current);
- }
- else
- {
- avail_bps = mCurrentBPS[i] - used_bps;
- }
-
- //LL_INFOS() << i << " avail " << avail_bps << LL_ENDL;
-
- // Historically, a channel could have used more than its current share,
- // even if it's idle right now.
- // Make sure we don't steal too much.
- if (avail_bps < 0)
- {
- continue;
- }
-
- // Transfer some bandwidth from this channel into the global pool.
- transfer_bps = avail_bps * TRANSFER_PERCENT;
- mCurrentBPS[i] -= transfer_bps;
- pool_bps += transfer_bps;
- }
- }
-
- //LL_INFOS() << "Pool BPS: " << pool_bps << LL_ENDL;
- // Now redistribute the bandwidth to busy channels.
- F32 unused_bps = 0.f;
-
- for (i = 0; i < TC_EOF; i++)
- {
- if (channel_busy[i])
- {
- F32 add_amount = pool_bps * (mNominalBPS[i] / busy_nominal_sum);
- //LL_INFOS() << "Busy " << i << " gets " << pool_bps << LL_ENDL;
- mCurrentBPS[i] += add_amount;
-
- // CRO: make sure this doesn't get too huge
- // JC - Actually, need to let mCurrentBPS go less than nominal, otherwise
- // you aren't allowing bandwidth to actually be moved from one channel
- // to another.
- // *TODO: If clamping high end, would be good to re-
- // allocate to other channels in the above code.
- const F32 MAX_BPS = 4 * mNominalBPS[i];
- if (mCurrentBPS[i] > MAX_BPS)
- {
- F32 overage = mCurrentBPS[i] - MAX_BPS;
- mCurrentBPS[i] -= overage;
- unused_bps += overage;
- }
-
- // Paranoia
- if (mCurrentBPS[i] < gThrottleMinimumBPS[i])
- {
- mCurrentBPS[i] = gThrottleMinimumBPS[i];
- }
- }
- }
-
- // For fun, add the overage back in to objects
- if (unused_bps > 0.f)
- {
- mCurrentBPS[TC_TASK] += unused_bps;
- }
- }
- else
- {
- // No one is busy.
- // Make the channel allocations seek toward nominal.
-
- // Look for overpumped channels
- F32 starved_nominal_sum = 0;
- F32 avail_bps = 0;
- F32 transfer_bps = 0;
- F32 pool_bps = 0;
- for (i = 0; i < TC_EOF; i++)
- {
- if (mCurrentBPS[i] > mNominalBPS[i])
- {
- avail_bps = (mCurrentBPS[i] - mNominalBPS[i]);
- transfer_bps = avail_bps * RECOVER_PERCENT;
-
- mCurrentBPS[i] -= transfer_bps;
- pool_bps += transfer_bps;
- }
- }
-
- // Evenly distribute bandwidth to channels currently
- // using less than nominal.
- for (i = 0; i < TC_EOF; i++)
- {
- if (mCurrentBPS[i] < mNominalBPS[i])
- {
- // We're going to weight allocations by nominal BPS.
- starved_nominal_sum += mNominalBPS[i];
- }
- }
-
- for (i = 0; i < TC_EOF; i++)
- {
- if (mCurrentBPS[i] < mNominalBPS[i])
- {
- // Distribute bandwidth according to nominal allocation ratios.
- mCurrentBPS[i] += pool_bps * (mNominalBPS[i] / starved_nominal_sum);
- }
- }
- }
- return true;
-}
+/**
+ * @file llthrottle.cpp
+ * @brief LLThrottle class used for network bandwidth control.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llthrottle.h"
+#include "llmath.h"
+#include "lldatapacker.h"
+#include "message.h"
+
+
+LLThrottle::LLThrottle(const F32 rate)
+{
+ mRate = rate;
+ mAvailable = 0.f;
+ mLookaheadSecs = 0.25f;
+ mLastSendTime = LLMessageSystem::getMessageTimeSeconds(true);
+}
+
+
+void LLThrottle::setRate(const F32 rate)
+{
+ // Need to accumulate available bits when adjusting the rate.
+ mAvailable = getAvailable();
+ mLastSendTime = LLMessageSystem::getMessageTimeSeconds();
+ mRate = rate;
+}
+
+F32 LLThrottle::getAvailable()
+{
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
+ return mAvailable + (mRate * elapsed_time.value());
+}
+
+bool LLThrottle::checkOverflow(const F32 amount)
+{
+ bool retval = true;
+
+ F32 lookahead_amount = mRate * mLookaheadSecs;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
+ F32 amount_available = mAvailable + (mRate * elapsed_time.value());
+
+ if ((amount_available >= lookahead_amount) || (amount_available > amount))
+ {
+ // ...enough space to send this message
+ // Also do if > lookahead so we can use if amount > capped amount.
+ retval = false;
+ }
+
+ return retval;
+}
+
+bool LLThrottle::throttleOverflow(const F32 amount)
+{
+ F32Seconds elapsed_time;
+ F32 lookahead_amount;
+ bool retval = true;
+
+ lookahead_amount = mRate * mLookaheadSecs;
+
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
+ elapsed_time = mt_sec - mLastSendTime;
+ mLastSendTime = mt_sec;
+
+ mAvailable += mRate * elapsed_time.value();
+
+ if (mAvailable >= lookahead_amount)
+ {
+ // ...channel completely open, so allow send regardless
+ // of size. This allows sends on very low BPS channels.
+ mAvailable = lookahead_amount;
+ retval = false;
+ }
+ else if (mAvailable > amount)
+ {
+ // ...enough space to send this message
+ retval = false;
+ }
+
+ // We actually already sent the bits.
+ mAvailable -= amount;
+
+ // What if bitsavailable goes negative?
+ // That's OK, because it means someone is banging on the channel,
+ // so we need some time to recover.
+
+ return retval;
+}
+
+
+
+const F32 THROTTLE_LOOKAHEAD_TIME = 1.f; // seconds
+
+// Make sure that we don't set above these
+// values, even if the client asks to be set
+// higher
+// Note that these values are replicated on the
+// client side to set max bandwidth throttling there,
+// in llviewerthrottle.cpp. These values are the sum
+// of the top two tiers of bandwidth there.
+
+F32 gThrottleMaximumBPS[TC_EOF] =
+{
+ 150000.f, // TC_RESEND
+ 170000.f, // TC_LAND
+ 34000.f, // TC_WIND
+ 34000.f, // TC_CLOUD
+ 446000.f, // TC_TASK
+ 446000.f, // TC_TEXTURE
+ 220000.f, // TC_ASSET
+};
+
+// Start low until viewer informs us of capability
+// Asset and resend get high values, since they
+// aren't used JUST by the viewer necessarily.
+// This is a HACK and should be dealt with more properly on
+// circuit creation.
+
+F32 gThrottleDefaultBPS[TC_EOF] =
+{
+ 100000.f, // TC_RESEND
+ 4000.f, // TC_LAND
+ 4000.f, // TC_WIND
+ 4000.f, // TC_CLOUD
+ 4000.f, // TC_TASK
+ 4000.f, // TC_TEXTURE
+ 100000.f, // TC_ASSET
+};
+
+// Don't throttle down lower than this
+// This potentially wastes 50 kbps, but usually
+// wont.
+F32 gThrottleMinimumBPS[TC_EOF] =
+{
+ 10000.f, // TC_RESEND
+ 10000.f, // TC_LAND
+ 4000.f, // TC_WIND
+ 4000.f, // TC_CLOUD
+ 20000.f, // TC_TASK
+ 10000.f, // TC_TEXTURE
+ 10000.f, // TC_ASSET
+};
+
+const char* THROTTLE_NAMES[TC_EOF] =
+{
+ "Resend ",
+ "Land ",
+ "Wind ",
+ "Cloud ",
+ "Task ",
+ "Texture",
+ "Asset "
+};
+
+LLThrottleGroup::LLThrottleGroup()
+{
+ S32 i;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ mThrottleTotal[i] = gThrottleDefaultBPS[i];
+ mNominalBPS[i] = gThrottleDefaultBPS[i];
+ }
+
+ resetDynamicAdjust();
+}
+
+void LLThrottleGroup::packThrottle(LLDataPacker &dp) const
+{
+ S32 i;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ dp.packF32(mThrottleTotal[i], "Throttle");
+ }
+}
+
+void LLThrottleGroup::unpackThrottle(LLDataPacker &dp)
+{
+ S32 i;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ F32 temp_throttle;
+ dp.unpackF32(temp_throttle, "Throttle");
+ temp_throttle = llclamp(temp_throttle, 0.f, 2250000.f);
+ mThrottleTotal[i] = temp_throttle;
+ if(mThrottleTotal[i] > gThrottleMaximumBPS[i])
+ {
+ mThrottleTotal[i] = gThrottleMaximumBPS[i];
+ }
+ }
+}
+
+// Call this whenever mNominalBPS changes. Need to reset
+// the measurement systems. In the future, we should look
+// into NOT resetting the system.
+void LLThrottleGroup::resetDynamicAdjust()
+{
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
+ S32 i;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ mCurrentBPS[i] = mNominalBPS[i];
+ mBitsAvailable[i] = mNominalBPS[i] * THROTTLE_LOOKAHEAD_TIME;
+ mLastSendTime[i] = mt_sec;
+ mBitsSentThisPeriod[i] = 0;
+ mBitsSentHistory[i] = 0;
+ }
+ mDynamicAdjustTime = mt_sec;
+}
+
+
+bool LLThrottleGroup::setNominalBPS(F32* throttle_vec)
+{
+ bool changed = false;
+ S32 i;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (mNominalBPS[i] != throttle_vec[i])
+ {
+ changed = true;
+ mNominalBPS[i] = throttle_vec[i];
+ }
+ }
+
+ // If we changed the nominal settings, reset the dynamic
+ // adjustment subsystem.
+ if (changed)
+ {
+ resetDynamicAdjust();
+ }
+
+ return changed;
+}
+
+// Return bits available in the channel
+S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
+{
+ S32 retval = 0;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
+
+ if (bits_available >= lookahead_bits)
+ {
+ retval = (S32) gThrottleMaximumBPS[throttle_cat];
+ }
+ else
+ {
+ retval = (S32) bits_available;
+ }
+
+ return retval;
+}
+
+
+bool LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
+{
+ bool retval = true;
+
+ F32 category_bps = mCurrentBPS[throttle_cat];
+ F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ // use a temporary bits_available
+ // since we don't want to change mBitsAvailable every time
+ F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
+ F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
+
+ if (bits_available >= lookahead_bits)
+ {
+ // ...channel completely open, so allow send regardless
+ // of size. This allows sends on very low BPS channels.
+ mBitsAvailable[throttle_cat] = lookahead_bits;
+ retval = false;
+ }
+ else if ( bits_available > bits )
+ {
+ // ...enough space to send this message
+ retval = false;
+ }
+
+ return retval;
+}
+
+bool LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
+{
+ F32Seconds elapsed_time;
+ F32 category_bps;
+ F32 lookahead_bits;
+ bool retval = true;
+
+ category_bps = mCurrentBPS[throttle_cat];
+ lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
+
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
+ elapsed_time = mt_sec - mLastSendTime[throttle_cat];
+ mLastSendTime[throttle_cat] = mt_sec;
+ mBitsAvailable[throttle_cat] += category_bps * elapsed_time.value();
+
+ if (mBitsAvailable[throttle_cat] >= lookahead_bits)
+ {
+ // ...channel completely open, so allow send regardless
+ // of size. This allows sends on very low BPS channels.
+ mBitsAvailable[throttle_cat] = lookahead_bits;
+ retval = false;
+ }
+ else if ( mBitsAvailable[throttle_cat] > bits )
+ {
+ // ...enough space to send this message
+ retval = false;
+ }
+
+ // We actually already sent the bits.
+ mBitsAvailable[throttle_cat] -= bits;
+
+ mBitsSentThisPeriod[throttle_cat] += bits;
+
+ // What if bitsavailable goes negative?
+ // That's OK, because it means someone is banging on the channel,
+ // so we need some time to recover.
+
+ return retval;
+}
+
+
+bool LLThrottleGroup::dynamicAdjust()
+{
+ const F32Seconds DYNAMIC_ADJUST_TIME(1.0f);
+ const F32 CURRENT_PERIOD_WEIGHT = .25f; // how much weight to give to last period while determining BPS utilization
+ const F32 BUSY_PERCENT = 0.75f; // if use more than this fraction of BPS, you are busy
+ const F32 IDLE_PERCENT = 0.70f; // if use less than this fraction, you are "idle"
+ const F32 TRANSFER_PERCENT = 0.90f; // how much unused bandwidth to take away each adjustment
+ const F32 RECOVER_PERCENT = 0.25f; // how much to give back during recovery phase
+
+ S32 i;
+
+ F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
+
+ // Only dynamically adjust every few seconds
+ if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME)
+ {
+ return false;
+ }
+ mDynamicAdjustTime = mt_sec;
+
+ // Update historical information
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (mBitsSentHistory[i] == 0)
+ {
+ // first run, just copy current period
+ mBitsSentHistory[i] = mBitsSentThisPeriod[i];
+ }
+ else
+ {
+ // have some history, so weight accordingly
+ mBitsSentHistory[i] = (1.f - CURRENT_PERIOD_WEIGHT) * mBitsSentHistory[i]
+ + CURRENT_PERIOD_WEIGHT * mBitsSentThisPeriod[i];
+ }
+
+ mBitsSentThisPeriod[i] = 0;
+ }
+
+ // Look for busy channels
+ // TODO: Fold into loop above.
+ bool channels_busy = false;
+ F32 busy_nominal_sum = 0;
+ bool channel_busy[TC_EOF];
+ bool channel_idle[TC_EOF];
+ bool channel_over_nominal[TC_EOF];
+
+ for (i = 0; i < TC_EOF; i++)
+ {
+ // Is this a busy channel?
+ if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i])
+ {
+ // this channel is busy
+ channels_busy = true;
+ busy_nominal_sum += mNominalBPS[i]; // use for allocation of pooled idle bandwidth
+ channel_busy[i] = true;
+ }
+ else
+ {
+ channel_busy[i] = false;
+ }
+
+ // Is this an idle channel?
+ if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i]) &&
+ (mBitsAvailable[i] > 0))
+ {
+ channel_idle[i] = true;
+ }
+ else
+ {
+ channel_idle[i] = false;
+ }
+
+ // Is this an overpumped channel?
+ if (mCurrentBPS[i] > mNominalBPS[i])
+ {
+ channel_over_nominal[i] = true;
+ }
+ else
+ {
+ channel_over_nominal[i] = false;
+ }
+ }
+
+ if (channels_busy)
+ {
+ // Some channels are busy. Let's see if we can get them some bandwidth.
+ F32 used_bps;
+ F32 avail_bps;
+ F32 transfer_bps;
+
+ F32 pool_bps = 0;
+
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (channel_idle[i] || channel_over_nominal[i] )
+ {
+ // Either channel i is idle, or has been overpumped.
+ // Therefore it's a candidate to give up some bandwidth.
+ // Figure out how much bandwidth it has been using, and how
+ // much is available to steal.
+ used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME.value();
+
+ // CRO make sure to keep a minimum amount of throttle available
+ // CRO NB: channels set to < MINIMUM_BPS will never give up bps,
+ // which is correct I think
+ if (used_bps < gThrottleMinimumBPS[i])
+ {
+ used_bps = gThrottleMinimumBPS[i];
+ }
+
+ if (channel_over_nominal[i])
+ {
+ F32 unused_current = mCurrentBPS[i] - used_bps;
+ avail_bps = llmax(mCurrentBPS[i] - mNominalBPS[i], unused_current);
+ }
+ else
+ {
+ avail_bps = mCurrentBPS[i] - used_bps;
+ }
+
+ //LL_INFOS() << i << " avail " << avail_bps << LL_ENDL;
+
+ // Historically, a channel could have used more than its current share,
+ // even if it's idle right now.
+ // Make sure we don't steal too much.
+ if (avail_bps < 0)
+ {
+ continue;
+ }
+
+ // Transfer some bandwidth from this channel into the global pool.
+ transfer_bps = avail_bps * TRANSFER_PERCENT;
+ mCurrentBPS[i] -= transfer_bps;
+ pool_bps += transfer_bps;
+ }
+ }
+
+ //LL_INFOS() << "Pool BPS: " << pool_bps << LL_ENDL;
+ // Now redistribute the bandwidth to busy channels.
+ F32 unused_bps = 0.f;
+
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (channel_busy[i])
+ {
+ F32 add_amount = pool_bps * (mNominalBPS[i] / busy_nominal_sum);
+ //LL_INFOS() << "Busy " << i << " gets " << pool_bps << LL_ENDL;
+ mCurrentBPS[i] += add_amount;
+
+ // CRO: make sure this doesn't get too huge
+ // JC - Actually, need to let mCurrentBPS go less than nominal, otherwise
+ // you aren't allowing bandwidth to actually be moved from one channel
+ // to another.
+ // *TODO: If clamping high end, would be good to re-
+ // allocate to other channels in the above code.
+ const F32 MAX_BPS = 4 * mNominalBPS[i];
+ if (mCurrentBPS[i] > MAX_BPS)
+ {
+ F32 overage = mCurrentBPS[i] - MAX_BPS;
+ mCurrentBPS[i] -= overage;
+ unused_bps += overage;
+ }
+
+ // Paranoia
+ if (mCurrentBPS[i] < gThrottleMinimumBPS[i])
+ {
+ mCurrentBPS[i] = gThrottleMinimumBPS[i];
+ }
+ }
+ }
+
+ // For fun, add the overage back in to objects
+ if (unused_bps > 0.f)
+ {
+ mCurrentBPS[TC_TASK] += unused_bps;
+ }
+ }
+ else
+ {
+ // No one is busy.
+ // Make the channel allocations seek toward nominal.
+
+ // Look for overpumped channels
+ F32 starved_nominal_sum = 0;
+ F32 avail_bps = 0;
+ F32 transfer_bps = 0;
+ F32 pool_bps = 0;
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (mCurrentBPS[i] > mNominalBPS[i])
+ {
+ avail_bps = (mCurrentBPS[i] - mNominalBPS[i]);
+ transfer_bps = avail_bps * RECOVER_PERCENT;
+
+ mCurrentBPS[i] -= transfer_bps;
+ pool_bps += transfer_bps;
+ }
+ }
+
+ // Evenly distribute bandwidth to channels currently
+ // using less than nominal.
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (mCurrentBPS[i] < mNominalBPS[i])
+ {
+ // We're going to weight allocations by nominal BPS.
+ starved_nominal_sum += mNominalBPS[i];
+ }
+ }
+
+ for (i = 0; i < TC_EOF; i++)
+ {
+ if (mCurrentBPS[i] < mNominalBPS[i])
+ {
+ // Distribute bandwidth according to nominal allocation ratios.
+ mCurrentBPS[i] += pool_bps * (mNominalBPS[i] / starved_nominal_sum);
+ }
+ }
+ }
+ return true;
+}
diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h
index 4eb800de06..be497d9371 100644
--- a/indra/llmessage/llthrottle.h
+++ b/indra/llmessage/llthrottle.h
@@ -1,101 +1,101 @@
-/**
- * @file llthrottle.h
- * @brief LLThrottle class used for network bandwidth control
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTHROTTLE_H
-#define LL_LLTHROTTLE_H
-
-#include "lltimer.h"
-
-const S32 MAX_THROTTLE_SIZE = 32;
-
-class LLDataPacker;
-
-// Single instance of a generic throttle
-class LLThrottle
-{
-public:
- LLThrottle(const F32 throttle = 1.f);
- ~LLThrottle() { }
-
- void setRate(const F32 rate);
- bool checkOverflow(const F32 amount); // I'm about to add an amount, true if would overflow throttle
- bool throttleOverflow(const F32 amount); // I just sent amount, true if that overflowed the throttle
-
- F32 getAvailable(); // Return the available bits
- F32 getRate() const { return mRate; }
-private:
- F32 mLookaheadSecs; // Seconds to look ahead, maximum
- F32 mRate; // BPS available, dynamically adjusted
- F32 mAvailable; // Bits available to send right now on each channel
- F64Seconds mLastSendTime; // Time since last send on this channel
-};
-
-typedef enum e_throttle_categories
-{
- TC_RESEND,
- TC_LAND,
- TC_WIND,
- TC_CLOUD,
- TC_TASK,
- TC_TEXTURE,
- TC_ASSET,
- TC_EOF
-} EThrottleCats;
-
-
-class LLThrottleGroup
-{
-public:
- LLThrottleGroup();
- ~LLThrottleGroup() { }
-
- void resetDynamicAdjust();
- bool checkOverflow(S32 throttle_cat, F32 bits); // I'm about to send bits, true if would overflow channel
- bool throttleOverflow(S32 throttle_cat, F32 bits); // I just sent bits, true if that overflowed the channel
- bool dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, true if adjustment occurred
- bool setNominalBPS(F32* throttle_vec); // true if any value was different, resets adjustment system if was different
-
- S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
-
- void packThrottle(LLDataPacker &dp) const;
- void unpackThrottle(LLDataPacker &dp);
-public:
- F32 mThrottleTotal[TC_EOF]; // BPS available, sent by viewer, sum for all simulators
-
-protected:
- F32 mNominalBPS[TC_EOF]; // BPS available, adjusted to be just this simulator
- F32 mCurrentBPS[TC_EOF]; // BPS available, dynamically adjusted
-
- F32 mBitsAvailable[TC_EOF]; // Bits available to send right now on each channel
- F32 mBitsSentThisPeriod[TC_EOF]; // Sent in this dynamic allocation period
- F32 mBitsSentHistory[TC_EOF]; // Sent before this dynamic allocation period, adjusted to one period length
-
- F64Seconds mLastSendTime[TC_EOF]; // Time since last send on this channel
- F64Seconds mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so.
-
-};
-
-#endif
+/**
+ * @file llthrottle.h
+ * @brief LLThrottle class used for network bandwidth control
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHROTTLE_H
+#define LL_LLTHROTTLE_H
+
+#include "lltimer.h"
+
+const S32 MAX_THROTTLE_SIZE = 32;
+
+class LLDataPacker;
+
+// Single instance of a generic throttle
+class LLThrottle
+{
+public:
+ LLThrottle(const F32 throttle = 1.f);
+ ~LLThrottle() { }
+
+ void setRate(const F32 rate);
+ bool checkOverflow(const F32 amount); // I'm about to add an amount, true if would overflow throttle
+ bool throttleOverflow(const F32 amount); // I just sent amount, true if that overflowed the throttle
+
+ F32 getAvailable(); // Return the available bits
+ F32 getRate() const { return mRate; }
+private:
+ F32 mLookaheadSecs; // Seconds to look ahead, maximum
+ F32 mRate; // BPS available, dynamically adjusted
+ F32 mAvailable; // Bits available to send right now on each channel
+ F64Seconds mLastSendTime; // Time since last send on this channel
+};
+
+typedef enum e_throttle_categories
+{
+ TC_RESEND,
+ TC_LAND,
+ TC_WIND,
+ TC_CLOUD,
+ TC_TASK,
+ TC_TEXTURE,
+ TC_ASSET,
+ TC_EOF
+} EThrottleCats;
+
+
+class LLThrottleGroup
+{
+public:
+ LLThrottleGroup();
+ ~LLThrottleGroup() { }
+
+ void resetDynamicAdjust();
+ bool checkOverflow(S32 throttle_cat, F32 bits); // I'm about to send bits, true if would overflow channel
+ bool throttleOverflow(S32 throttle_cat, F32 bits); // I just sent bits, true if that overflowed the channel
+ bool dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, true if adjustment occurred
+ bool setNominalBPS(F32* throttle_vec); // true if any value was different, resets adjustment system if was different
+
+ S32 getAvailable(S32 throttle_cat); // Return bits available in the channel
+
+ void packThrottle(LLDataPacker &dp) const;
+ void unpackThrottle(LLDataPacker &dp);
+public:
+ F32 mThrottleTotal[TC_EOF]; // BPS available, sent by viewer, sum for all simulators
+
+protected:
+ F32 mNominalBPS[TC_EOF]; // BPS available, adjusted to be just this simulator
+ F32 mCurrentBPS[TC_EOF]; // BPS available, dynamically adjusted
+
+ F32 mBitsAvailable[TC_EOF]; // Bits available to send right now on each channel
+ F32 mBitsSentThisPeriod[TC_EOF]; // Sent in this dynamic allocation period
+ F32 mBitsSentHistory[TC_EOF]; // Sent before this dynamic allocation period, adjusted to one period length
+
+ F64Seconds mLastSendTime[TC_EOF]; // Time since last send on this channel
+ F64Seconds mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so.
+
+};
+
+#endif
diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp
index bad12101e5..f5351c6b58 100644
--- a/indra/llmessage/lltransfermanager.cpp
+++ b/indra/llmessage/lltransfermanager.cpp
@@ -1,1401 +1,1401 @@
-/**
- * @file lltransfermanager.cpp
- * @brief Improved transfer mechanism for moving data through the
- * message system.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltransfermanager.h"
-
-#include "llerror.h"
-#include "message.h"
-#include "lldatapacker.h"
-
-#include "lltransfersourcefile.h"
-#include "lltransfersourceasset.h"
-#include "lltransfertargetfile.h"
-#include "lltransfertargetvfile.h"
-
-const S32 MAX_PACKET_DATA_SIZE = 2048;
-const S32 MAX_PARAMS_SIZE = 1024;
-
-LLTransferManager gTransferManager;
-LLTransferSource::stype_scfunc_map LLTransferSource::sSourceCreateMap;
-
-//
-// LLTransferManager implementation
-//
-
-LLTransferManager::LLTransferManager() :
- mValid(false)
-{
- S32 i;
- for (i = 0; i < LLTTT_NUM_TYPES; i++)
- {
- mTransferBitsIn[i] = 0;
- mTransferBitsOut[i] = 0;
- }
-}
-
-
-LLTransferManager::~LLTransferManager()
-{
- // LLTransferManager should have been cleaned up by message system shutdown process
- llassert(!mValid);
- if (mValid)
- {
- // Usually happens if OS tries to kill viewer
- cleanup();
- }
-}
-
-
-void LLTransferManager::init()
-{
- if (mValid)
- {
- LL_ERRS() << "Double initializing LLTransferManager!" << LL_ENDL;
- }
- mValid = true;
-
- // Register message system handlers
- gMessageSystem->setHandlerFunc("TransferRequest", processTransferRequest, NULL);
- gMessageSystem->setHandlerFunc("TransferInfo", processTransferInfo, NULL);
- gMessageSystem->setHandlerFunc("TransferPacket", processTransferPacket, NULL);
- gMessageSystem->setHandlerFunc("TransferAbort", processTransferAbort, NULL);
-}
-
-
-void LLTransferManager::cleanup()
-{
- mValid = false;
-
- host_tc_map::iterator iter;
- for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
- {
- delete iter->second;
- }
- mTransferConnections.clear();
-}
-
-
-void LLTransferManager::updateTransfers()
-{
- host_tc_map::iterator iter,cur;
-
- iter = mTransferConnections.begin();
-
- while (iter !=mTransferConnections.end())
- {
- cur = iter;
- iter++;
- cur->second->updateTransfers();
- }
-}
-
-
-void LLTransferManager::cleanupConnection(const LLHost &host)
-{
- host_tc_map::iterator iter;
- iter = mTransferConnections.find(host);
- if (iter == mTransferConnections.end())
- {
- // This can happen legitimately if we've never done a transfer, and we're
- // cleaning up a circuit.
- //LL_WARNS() << "Cleaning up nonexistent transfer connection to " << host << LL_ENDL;
- return;
- }
- LLTransferConnection *connp = iter->second;
- delete connp;
- mTransferConnections.erase(iter);
-}
-
-
-LLTransferConnection *LLTransferManager::getTransferConnection(const LLHost &host)
-{
- host_tc_map::iterator iter;
- iter = mTransferConnections.find(host);
- if (iter == mTransferConnections.end())
- {
- mTransferConnections[host] = new LLTransferConnection(host);
- return mTransferConnections[host];
- }
-
- return iter->second;
-}
-
-
-LLTransferSourceChannel *LLTransferManager::getSourceChannel(const LLHost &host, const LLTransferChannelType type)
-{
- LLTransferConnection *tcp = getTransferConnection(host);
- if (!tcp)
- {
- return NULL;
- }
- return tcp->getSourceChannel(type);
-}
-
-
-
-LLTransferTargetChannel *LLTransferManager::getTargetChannel(const LLHost &host, const LLTransferChannelType type)
-{
- LLTransferConnection *tcp = getTransferConnection(host);
- if (!tcp)
- {
- return NULL;
- }
- return tcp->getTargetChannel(type);
-}
-
-// virtual
-LLTransferSourceParams::~LLTransferSourceParams()
-{ }
-
-
-LLTransferSource *LLTransferManager::findTransferSource(const LLUUID &transfer_id)
-{
- // This linear traversal could screw us later if we do lots of
- // searches for sources. However, this ONLY happens right now
- // in asset transfer callbacks, so this should be relatively quick.
- host_tc_map::iterator iter;
- for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
- {
- LLTransferConnection *tcp = iter->second;
- LLTransferConnection::tsc_iter sc_iter;
- for (sc_iter = tcp->mTransferSourceChannels.begin(); sc_iter != tcp->mTransferSourceChannels.end(); sc_iter++)
- {
- LLTransferSourceChannel *scp = *sc_iter;
- LLTransferSource *sourcep = scp->findTransferSource(transfer_id);
- if (sourcep)
- {
- return sourcep;
- }
- }
- }
-
- return NULL;
-}
-
-//
-// Message handlers
-//
-
-//static
-void LLTransferManager::processTransferRequest(LLMessageSystem *msgp, void **)
-{
- //LL_INFOS() << "LLTransferManager::processTransferRequest" << LL_ENDL;
-
- LLUUID transfer_id;
- LLTransferSourceType source_type;
- LLTransferChannelType channel_type;
- F32 priority;
-
- msgp->getUUID("TransferInfo", "TransferID", transfer_id);
- msgp->getS32("TransferInfo", "SourceType", (S32 &)source_type);
- msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
- msgp->getF32("TransferInfo", "Priority", priority);
-
- LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
-
- if (!tscp)
- {
- LL_WARNS() << "Source channel not found" << LL_ENDL;
- return;
- }
-
- if (tscp->findTransferSource(transfer_id))
- {
- LL_WARNS() << "Duplicate request for transfer " << transfer_id << ", aborting!" << LL_ENDL;
- return;
- }
-
- S32 size = msgp->getSize("TransferInfo", "Params");
- if(size > MAX_PARAMS_SIZE)
- {
- LL_WARNS() << "LLTransferManager::processTransferRequest params too big."
- << LL_ENDL;
- return;
- }
-
- //LL_INFOS() << transfer_id << ":" << source_type << ":" << channel_type << ":" << priority << LL_ENDL;
- LLTransferSource* tsp = LLTransferSource::createSource(
- source_type,
- transfer_id,
- priority);
- if(!tsp)
- {
- LL_WARNS() << "LLTransferManager::processTransferRequest couldn't create"
- << " transfer source!" << LL_ENDL;
- return;
- }
- U8 tmp[MAX_PARAMS_SIZE];
- msgp->getBinaryData("TransferInfo", "Params", tmp, size);
-
- LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
- bool unpack_ok = tsp->unpackParams(dpb);
- if (!unpack_ok)
- {
- // This should only happen if the data is corrupt or
- // incorrectly packed.
- // *NOTE: We may want to call abortTransfer().
- LL_WARNS() << "LLTransferManager::processTransferRequest: bad parameters."
- << LL_ENDL;
- delete tsp;
- return;
- }
-
- tscp->addTransferSource(tsp);
- tsp->initTransfer();
-}
-
-
-//static
-void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
-{
- //LL_INFOS() << "LLTransferManager::processTransferInfo" << LL_ENDL;
-
- LLUUID transfer_id;
- LLTransferTargetType target_type;
- LLTransferChannelType channel_type;
- LLTSCode status;
- S32 size;
-
- msgp->getUUID("TransferInfo", "TransferID", transfer_id);
- msgp->getS32("TransferInfo", "TargetType", (S32 &)target_type);
- msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
- msgp->getS32("TransferInfo", "Status", (S32 &)status);
- msgp->getS32("TransferInfo", "Size", size);
-
- //LL_INFOS() << transfer_id << ":" << target_type<< ":" << channel_type << LL_ENDL;
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
- if (!ttcp)
- {
- LL_WARNS() << "Target channel not found" << LL_ENDL;
- // Should send a message to abort the transfer.
- return;
- }
-
- LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
- if (!ttp)
- {
- LL_WARNS() << "TransferInfo for unknown transfer! Not able to handle this yet!" << LL_ENDL;
- // This could happen if we're doing a push transfer, although to avoid confusion,
- // maybe it should be a different message.
- return;
- }
-
- if (status != LLTS_OK)
- {
- LL_WARNS() << transfer_id << ": Non-ok status, cleaning up" << LL_ENDL;
- ttp->completionCallback(status);
- // Clean up the transfer.
- ttcp->deleteTransfer(ttp);
- return;
- }
-
- // unpack the params
- S32 params_size = msgp->getSize("TransferInfo", "Params");
- if(params_size > MAX_PARAMS_SIZE)
- {
- LL_WARNS() << "LLTransferManager::processTransferInfo params too big."
- << LL_ENDL;
- return;
- }
- else if(params_size > 0)
- {
- U8 tmp[MAX_PARAMS_SIZE];
- msgp->getBinaryData("TransferInfo", "Params", tmp, params_size);
- LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
- if (!ttp->unpackParams(dpb))
- {
- // This should only happen if the data is corrupt or
- // incorrectly packed.
- LL_WARNS() << "LLTransferManager::processTransferRequest: bad params."
- << LL_ENDL;
- ttp->abortTransfer();
- ttcp->deleteTransfer(ttp);
- return;
- }
- }
-
- //LL_INFOS() << "Receiving " << transfer_id << ", size " << size << " bytes" << LL_ENDL;
- ttp->setSize(size);
- ttp->setGotInfo(true);
-
- // OK, at this point we to handle any delayed transfer packets (which could happen
- // if this packet was lost)
-
- // This is a lame cut and paste of code down below. If we change the logic down there,
- // we HAVE to change the logic up here.
-
- while (1)
- {
- S32 packet_id = 0;
- U8 tmp_data[MAX_PACKET_DATA_SIZE];
- // See if we've got any delayed packets
- packet_id = ttp->getNextPacketID();
- if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
- {
- // Perhaps this stuff should be inside a method in LLTransferPacket?
- // I'm too lazy to do it now, though.
-// LL_INFOS() << "Playing back delayed packet " << packet_id << LL_ENDL;
- LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
-
- // This is somewhat inefficient, but avoids us having to duplicate
- // code between the off-the-wire and delayed paths.
- packet_id = packetp->mPacketID;
- size = packetp->mSize;
- if (size)
- {
- if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
- {
- memcpy(tmp_data, packetp->mDatap, size); /*Flawfinder: ignore*/
- }
- }
- status = packetp->mStatus;
- ttp->mDelayedPacketMap.erase(packet_id);
- delete packetp;
- }
- else
- {
- // No matching delayed packet, we're done.
- break;
- }
-
- LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
- if (ret_code == LLTS_OK)
- {
- ttp->setLastPacketID(packet_id);
- }
-
- if (status != LLTS_OK)
- {
- if (status != LLTS_DONE)
- {
- LL_WARNS() << "LLTransferManager::processTransferInfo Error in playback!" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "LLTransferManager::processTransferInfo replay FINISHED for " << transfer_id << LL_ENDL;
- }
- // This transfer is done, either via error or not.
- ttp->completionCallback(status);
- ttcp->deleteTransfer(ttp);
- return;
- }
- }
-}
-
-
-//static
-void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
-{
- //LL_INFOS() << "LLTransferManager::processTransferPacket" << LL_ENDL;
-
- LLUUID transfer_id;
- LLTransferChannelType channel_type;
- S32 packet_id;
- LLTSCode status;
- S32 size;
- msgp->getUUID("TransferData", "TransferID", transfer_id);
- msgp->getS32("TransferData", "ChannelType", (S32 &)channel_type);
- msgp->getS32("TransferData", "Packet", packet_id);
- msgp->getS32("TransferData", "Status", (S32 &)status);
-
- // Find the transfer associated with this packet.
- //LL_INFOS() << transfer_id << ":" << channel_type << LL_ENDL;
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
- if (!ttcp)
- {
- LL_WARNS() << "Target channel not found" << LL_ENDL;
- return;
- }
-
- LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
- if (!ttp)
- {
- LL_WARNS() << "Didn't find matching transfer for " << transfer_id
- << " processing packet " << packet_id
- << " from " << msgp->getSender() << LL_ENDL;
- return;
- }
-
- size = msgp->getSize("TransferData", "Data");
-
- S32 msg_bytes = 0;
- if (msgp->getReceiveCompressedSize())
- {
- msg_bytes = msgp->getReceiveCompressedSize();
- }
- else
- {
- msg_bytes = msgp->getReceiveSize();
- }
- gTransferManager.addTransferBitsIn(ttcp->mChannelType, msg_bytes*8);
-
- if ((size < 0) || (size > MAX_PACKET_DATA_SIZE))
- {
- LL_WARNS() << "Invalid transfer packet size " << size << LL_ENDL;
- return;
- }
-
- U8 tmp_data[MAX_PACKET_DATA_SIZE];
- if (size > 0)
- {
- // Only pull the data out if the size is > 0
- msgp->getBinaryData("TransferData", "Data", tmp_data, size);
- }
-
- if ((!ttp->gotInfo()) || (ttp->getNextPacketID() != packet_id))
- {
- // Put this on a list of packets to be delivered later.
- if(!ttp->addDelayedPacket(packet_id, status, tmp_data, size))
- {
- // Whoops - failed to add a delayed packet for some reason.
- LL_WARNS() << "Too many delayed packets processing transfer "
- << transfer_id << " from " << msgp->getSender() << LL_ENDL;
- ttp->abortTransfer();
- ttcp->deleteTransfer(ttp);
- return;
- }
-#if 0
- // Spammy!
- const S32 LL_TRANSFER_WARN_GAP = 10;
- if(!ttp->gotInfo())
- {
- LL_WARNS() << "Got data packet before information in transfer "
- << transfer_id << " from " << msgp->getSender()
- << ", got " << packet_id << LL_ENDL;
- }
- else if((packet_id - ttp->getNextPacketID()) > LL_TRANSFER_WARN_GAP)
- {
- LL_WARNS() << "Out of order packet in transfer " << transfer_id
- << " from " << msgp->getSender() << ", got " << packet_id
- << " expecting " << ttp->getNextPacketID() << LL_ENDL;
- }
-#endif
- return;
- }
-
- // Loop through this until we're done with all delayed packets
-
- //
- // NOTE: THERE IS A CUT AND PASTE OF THIS CODE IN THE TRANSFERINFO HANDLER
- // SO WE CAN PLAY BACK DELAYED PACKETS THERE!!!!!!!!!!!!!!!!!!!!!!!!!
- //
- bool done = false;
- while (!done)
- {
- LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
- if (ret_code == LLTS_OK)
- {
- ttp->setLastPacketID(packet_id);
- }
-
- if (status != LLTS_OK)
- {
- if (status != LLTS_DONE)
- {
- LL_WARNS() << "LLTransferManager::processTransferPacket Error in transfer!" << LL_ENDL;
- }
- else
- {
-// LL_INFOS() << "LLTransferManager::processTransferPacket done for " << transfer_id << LL_ENDL;
- }
- // This transfer is done, either via error or not.
- ttp->completionCallback(status);
- ttcp->deleteTransfer(ttp);
- return;
- }
-
- // See if we've got any delayed packets
- packet_id = ttp->getNextPacketID();
- if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
- {
- // Perhaps this stuff should be inside a method in LLTransferPacket?
- // I'm too lazy to do it now, though.
-// LL_INFOS() << "Playing back delayed packet " << packet_id << LL_ENDL;
- LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
-
- // This is somewhat inefficient, but avoids us having to duplicate
- // code between the off-the-wire and delayed paths.
- packet_id = packetp->mPacketID;
- size = packetp->mSize;
- if (size)
- {
- if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
- {
- memcpy(tmp_data, packetp->mDatap, size); /*Flawfinder: ignore*/
- }
- }
- status = packetp->mStatus;
- ttp->mDelayedPacketMap.erase(packet_id);
- delete packetp;
- }
- else
- {
- // No matching delayed packet, abort it.
- done = true;
- }
- }
-}
-
-
-//static
-void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
-{
- //LL_INFOS() << "LLTransferManager::processTransferPacket" << LL_ENDL;
-
- LLUUID transfer_id;
- LLTransferChannelType channel_type;
- msgp->getUUID("TransferInfo", "TransferID", transfer_id);
- msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
-
- // See if it's a target that we're trying to abort
- // Find the transfer associated with this packet.
- LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
- if (ttcp)
- {
- LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
- if (ttp)
- {
- ttp->abortTransfer();
- ttcp->deleteTransfer(ttp);
- return;
- }
- }
-
- // Hmm, not a target. Maybe it's a source.
- LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
- if (tscp)
- {
- LLTransferSource *tsp = tscp->findTransferSource(transfer_id);
- if (tsp)
- {
- tsp->abortTransfer();
- tscp->deleteTransfer(tsp);
- return;
- }
- }
-
- LL_WARNS() << "Couldn't find transfer " << transfer_id << " to abort!" << LL_ENDL;
-}
-
-
-//static
-void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
-{
- LLUUID *transfer_idp = (LLUUID *)user_data;
- if (result &&
- transfer_idp != NULL)
- {
- LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
- if (tsp)
- {
- LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL;
- LLTransferSourceChannel *tscp = tsp->mChannelp;
- tsp->abortTransfer();
- tscp->deleteTransfer(tsp);
- }
- else
- {
- LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << LL_ENDL;
- }
- }
- delete transfer_idp;
-}
-
-//
-// LLTransferConnection implementation
-//
-
-LLTransferConnection::LLTransferConnection(const LLHost &host)
-{
- mHost = host;
-}
-
-LLTransferConnection::~LLTransferConnection()
-{
- tsc_iter itersc;
- for (itersc = mTransferSourceChannels.begin(); itersc != mTransferSourceChannels.end(); itersc++)
- {
- delete *itersc;
- }
- mTransferSourceChannels.clear();
-
- ttc_iter itertc;
- for (itertc = mTransferTargetChannels.begin(); itertc != mTransferTargetChannels.end(); itertc++)
- {
- delete *itertc;
- }
- mTransferTargetChannels.clear();
-}
-
-
-void LLTransferConnection::updateTransfers()
-{
- // Do stuff for source transfers (basically, send data out).
- tsc_iter iter, cur;
- iter = mTransferSourceChannels.begin();
-
- while (iter !=mTransferSourceChannels.end())
- {
- cur = iter;
- iter++;
- (*cur)->updateTransfers();
- }
-
- // Do stuff for target transfers
- // Primarily, we should be aborting transfers that are irredeemably broken
- // (large packet gaps that don't appear to be getting filled in, most likely)
- // Probably should NOT be doing timeouts for other things, as new priority scheme
- // means that a high priority transfer COULD block a transfer for a long time.
-}
-
-
-LLTransferSourceChannel *LLTransferConnection::getSourceChannel(const LLTransferChannelType channel_type)
-{
- tsc_iter iter;
- for (iter = mTransferSourceChannels.begin(); iter != mTransferSourceChannels.end(); iter++)
- {
- if ((*iter)->getChannelType() == channel_type)
- {
- return *iter;
- }
- }
-
- LLTransferSourceChannel *tscp = new LLTransferSourceChannel(channel_type, mHost);
- mTransferSourceChannels.push_back(tscp);
- return tscp;
-}
-
-
-LLTransferTargetChannel *LLTransferConnection::getTargetChannel(const LLTransferChannelType channel_type)
-{
- ttc_iter iter;
- for (iter = mTransferTargetChannels.begin(); iter != mTransferTargetChannels.end(); iter++)
- {
- if ((*iter)->getChannelType() == channel_type)
- {
- return *iter;
- }
- }
-
- LLTransferTargetChannel *ttcp = new LLTransferTargetChannel(channel_type, mHost);
- mTransferTargetChannels.push_back(ttcp);
- return ttcp;
-}
-
-
-//
-// LLTransferSourceChannel implementation
-//
-
-const S32 DEFAULT_PACKET_SIZE = 1000;
-
-
-LLTransferSourceChannel::LLTransferSourceChannel(const LLTransferChannelType channel_type, const LLHost &host) :
- mChannelType(channel_type),
- mHost(host),
- mTransferSources(LLTransferSource::sSetPriority, LLTransferSource::sGetPriority),
- mThrottleID(TC_ASSET)
-{
-}
-
-
-LLTransferSourceChannel::~LLTransferSourceChannel()
-{
- LLPriQueueMap<LLTransferSource*>::pqm_iter iter =
- mTransferSources.mMap.begin();
- LLPriQueueMap<LLTransferSource*>::pqm_iter end =
- mTransferSources.mMap.end();
- for (; iter != end; ++iter)
- {
- // Just kill off all of the transfers
- (*iter).second->abortTransfer();
- delete iter->second;
- }
- mTransferSources.mMap.clear();
-}
-
-void LLTransferSourceChannel::updatePriority(LLTransferSource *tsp, const F32 priority)
-{
- mTransferSources.reprioritize(priority, tsp);
-}
-
-void LLTransferSourceChannel::updateTransfers()
-{
- // Actually, this should do the following:
- // Decide if we can actually send data.
- // If so, update priorities so we know who gets to send it.
- // Send data from the sources, while updating until we've sent our throttle allocation.
-
- LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(getHost());
- if (!cdp)
- {
- return;
- }
-
- if (cdp->isBlocked())
- {
- // *NOTE: We need to make sure that the throttle bits
- // available gets reset.
-
- // We DON'T want to send any packets if they're blocked, they'll just end up
- // piling up on the other end.
- //LL_WARNS() << "Blocking transfers due to blocked circuit for " << getHost() << LL_ENDL;
- return;
- }
-
- const S32 throttle_id = mThrottleID;
-
- LLThrottleGroup &tg = cdp->getThrottleGroup();
-
- if (tg.checkOverflow(throttle_id, 0.f))
- {
- return;
- }
-
- LLPriQueueMap<LLTransferSource *>::pqm_iter iter, next;
-
- bool done = false;
- for (iter = mTransferSources.mMap.begin(); (iter != mTransferSources.mMap.end()) && !done;)
- {
- //LL_INFOS() << "LLTransferSourceChannel::updateTransfers()" << LL_ENDL;
- // Do stuff.
- next = iter;
- next++;
-
- LLTransferSource *tsp = iter->second;
- U8 *datap = NULL;
- S32 data_size = 0;
- bool delete_data = false;
- S32 packet_id = 0;
- S32 sent_bytes = 0;
- LLTSCode status = LLTS_OK;
-
- // Get the packetID for the next packet that we're transferring.
- packet_id = tsp->getNextPacketID();
- status = tsp->dataCallback(packet_id, DEFAULT_PACKET_SIZE, &datap, data_size, delete_data);
-
- if (status == LLTS_SKIP)
- {
- // We don't have any data, but we're not done, just go on.
- // This will presumably be used for streaming or async transfers that
- // are stalled waiting for data from another source.
- iter=next;
- continue;
- }
-
- LLUUID *cb_uuid = new LLUUID(tsp->getID());
- LLUUID transaction_id = tsp->getID();
-
- // Send the data now, even if it's an error.
- // The status code will tell the other end what to do.
- gMessageSystem->newMessage("TransferPacket");
- gMessageSystem->nextBlock("TransferData");
- gMessageSystem->addUUID("TransferID", tsp->getID());
- gMessageSystem->addS32("ChannelType", getChannelType());
- gMessageSystem->addS32("Packet", packet_id); // HACK! Need to put in a REAL packet id
- gMessageSystem->addS32("Status", status);
- gMessageSystem->addBinaryData("Data", datap, data_size);
- sent_bytes = gMessageSystem->getCurrentSendTotal();
- gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, true, F32Seconds(0.f),
- LLTransferManager::reliablePacketCallback, (void**)cb_uuid);
-
- // Do bookkeeping for the throttle
- done = tg.throttleOverflow(throttle_id, sent_bytes*8.f);
- gTransferManager.addTransferBitsOut(mChannelType, sent_bytes*8);
-
- // Clean up our temporary data.
- if (delete_data)
- {
- delete[] datap;
- datap = NULL;
- }
-
- if (findTransferSource(transaction_id) == NULL)
- {
- //Warning! In the case of an aborted transfer, the sendReliable call above calls
- //AbortTransfer which in turn calls deleteTransfer which means that somewhere way
- //down the chain our current iter can get invalidated resulting in an infrequent
- //sim crash. This check gets us to a valid transfer source in this event.
- iter=next;
- continue;
- }
-
- // Update the packet counter
- tsp->setLastPacketID(packet_id);
-
- switch (status)
- {
- case LLTS_OK:
- // We're OK, don't need to do anything. Keep sending data.
- break;
- case LLTS_ERROR:
- LL_WARNS() << "Error in transfer dataCallback!" << LL_ENDL;
- // fall through
- case LLTS_DONE:
- // We need to clean up this transfer source.
- //LL_INFOS() << "LLTransferSourceChannel::updateTransfers() " << tsp->getID() << " done" << LL_ENDL;
- tsp->completionCallback(status);
- delete tsp;
-
- mTransferSources.mMap.erase(iter);
- iter = next;
- break;
- default:
- LL_ERRS() << "Unknown transfer error code!" << LL_ENDL;
- }
-
- // At this point, we should do priority adjustment (since some transfers like
- // streaming transfers will adjust priority based on how much they've sent and time,
- // but I'm not going to bother yet. - djs.
- }
-}
-
-
-void LLTransferSourceChannel::addTransferSource(LLTransferSource *sourcep)
-{
- sourcep->mChannelp = this;
- mTransferSources.push(sourcep->getPriority(), sourcep);
-}
-
-
-LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &transfer_id)
-{
- LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
- for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
- {
- LLTransferSource *tsp = iter->second;
- if (tsp->getID() == transfer_id)
- {
- return tsp;
- }
- }
- return NULL;
-}
-
-
-void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
-{
- if (tsp)
- {
- LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
- for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
- {
- if (iter->second == tsp)
- {
- delete tsp;
- mTransferSources.mMap.erase(iter);
- return;
- }
- }
-
- LL_WARNS() << "Unable to find transfer source id "
- << tsp->getID()
- << " to delete!"
- << LL_ENDL;
- }
-}
-
-
-//
-// LLTransferTargetChannel implementation
-//
-
-LLTransferTargetChannel::LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host) :
- mChannelType(channel_type),
- mHost(host)
-{
-}
-
-LLTransferTargetChannel::~LLTransferTargetChannel()
-{
- tt_iter iter;
- for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
- {
- // Abort all of the current transfers
- (*iter)->abortTransfer();
- delete *iter;
- }
- mTransferTargets.clear();
-}
-
-
-void LLTransferTargetChannel::requestTransfer(
- const LLTransferSourceParams& source_params,
- const LLTransferTargetParams& target_params,
- const F32 priority)
-{
- LLUUID id;
- id.generate();
- LLTransferTarget* ttp = LLTransferTarget::createTarget(
- target_params.getType(),
- id,
- source_params.getType());
- if (!ttp)
- {
- LL_WARNS() << "LLTransferManager::requestTransfer aborting due to target creation failure!" << LL_ENDL;
- return;
- }
-
- ttp->applyParams(target_params);
- addTransferTarget(ttp);
-
- sendTransferRequest(ttp, source_params, priority);
-}
-
-
-void LLTransferTargetChannel::sendTransferRequest(LLTransferTarget *targetp,
- const LLTransferSourceParams &params,
- const F32 priority)
-{
- //
- // Pack the message with data which explains how to get the source, and
- // send it off to the source for this channel.
- //
- llassert(targetp);
- llassert(targetp->getChannel() == this);
-
- gMessageSystem->newMessage("TransferRequest");
- gMessageSystem->nextBlock("TransferInfo");
- gMessageSystem->addUUID("TransferID", targetp->getID());
- gMessageSystem->addS32("SourceType", params.getType());
- gMessageSystem->addS32("ChannelType", getChannelType());
- gMessageSystem->addF32("Priority", priority);
-
- U8 tmp[MAX_PARAMS_SIZE];
- LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
- params.packParams(dp);
- S32 len = dp.getCurrentSize();
- gMessageSystem->addBinaryData("Params", tmp, len);
-
- gMessageSystem->sendReliable(mHost);
-}
-
-
-void LLTransferTargetChannel::addTransferTarget(LLTransferTarget *targetp)
-{
- targetp->mChannelp = this;
- mTransferTargets.push_back(targetp);
-}
-
-
-LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &transfer_id)
-{
- tt_iter iter;
- for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
- {
- LLTransferTarget *ttp = *iter;
- if (ttp->getID() == transfer_id)
- {
- return ttp;
- }
- }
- return NULL;
-}
-
-
-void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
-{
- if (ttp)
- {
- tt_iter iter;
- for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
- {
- if (*iter == ttp)
- {
- delete ttp;
- mTransferTargets.erase(iter);
- return;
- }
- }
-
- LL_WARNS() << "Unable to find transfer target id "
- << ttp->getID()
- << " to delete!"
- << LL_ENDL;
- }
-}
-
-
-//
-// LLTransferSource implementation
-//
-
-LLTransferSource::LLTransferSource(const LLTransferSourceType type,
- const LLUUID &transfer_id,
- const F32 priority) :
- mType(type),
- mID(transfer_id),
- mChannelp(NULL),
- mPriority(priority),
- mSize(0),
- mLastPacketID(-1)
-{
- setPriority(priority);
-}
-
-
-LLTransferSource::~LLTransferSource()
-{
- // No actual cleanup of the transfer is done here, this is purely for
- // memory cleanup. The completionCallback is guaranteed to get called
- // before this happens.
-}
-
-
-void LLTransferSource::sendTransferStatus(LLTSCode status)
-{
- gMessageSystem->newMessage("TransferInfo");
- gMessageSystem->nextBlock("TransferInfo");
- gMessageSystem->addUUID("TransferID", getID());
- gMessageSystem->addS32("TargetType", LLTTT_UNKNOWN);
- gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
- gMessageSystem->addS32("Status", status);
- gMessageSystem->addS32("Size", mSize);
- U8 tmp[MAX_PARAMS_SIZE];
- LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
- packParams(dp);
- S32 len = dp.getCurrentSize();
- gMessageSystem->addBinaryData("Params", tmp, len);
- gMessageSystem->sendReliable(mChannelp->getHost());
-
- // Abort if there was as asset system issue.
- if (status != LLTS_OK)
- {
- completionCallback(status);
- mChannelp->deleteTransfer(this);
- }
-}
-
-
-// This should never be called directly, the transfer manager is responsible for
-// aborting the transfer from the channel. I might want to rethink this in the
-// future, though.
-void LLTransferSource::abortTransfer()
-{
- // Send a message down, call the completion callback
- LL_INFOS() << "LLTransferSource::Aborting transfer " << getID() << " to " << mChannelp->getHost() << LL_ENDL;
- gMessageSystem->newMessage("TransferAbort");
- gMessageSystem->nextBlock("TransferInfo");
- gMessageSystem->addUUID("TransferID", getID());
- gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
- gMessageSystem->sendReliable(mChannelp->getHost());
-
- completionCallback(LLTS_ABORT);
-}
-
-
-//static
-void LLTransferSource::registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc func)
-{
- if (sSourceCreateMap.count(stype))
- {
- // Disallow changing what class handles a source type
- // Unclear when you would want to do this, and whether it would work.
- LL_ERRS() << "Reregistering source type " << stype << LL_ENDL;
- }
- else
- {
- sSourceCreateMap[stype] = func;
- }
-}
-
-//static
-LLTransferSource *LLTransferSource::createSource(const LLTransferSourceType stype,
- const LLUUID &id,
- const F32 priority)
-{
- switch (stype)
- {
- // *NOTE: The source file transfer mechanism is highly insecure and could
- // lead to easy exploitation of a server process.
- // I have removed all uses of it from the codebase. Phoenix.
- //
- //case LLTST_FILE:
- // return new LLTransferSourceFile(id, priority);
- case LLTST_ASSET:
- return new LLTransferSourceAsset(id, priority);
- default:
- {
- if (!sSourceCreateMap.count(stype))
- {
- // Use the callback to create the source type if it's not there.
- LL_WARNS() << "Unknown transfer source type: " << stype << LL_ENDL;
- return NULL;
- }
- return (sSourceCreateMap[stype])(id, priority);
- }
- }
-}
-
-
-// static
-void LLTransferSource::sSetPriority(LLTransferSource *&tsp, const F32 priority)
-{
- tsp->setPriority(priority);
-}
-
-
-// static
-F32 LLTransferSource::sGetPriority(LLTransferSource *&tsp)
-{
- return tsp->getPriority();
-}
-
-
-//
-// LLTransferPacket implementation
-//
-
-LLTransferPacket::LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size) :
- mPacketID(packet_id),
- mStatus(status),
- mDatap(NULL),
- mSize(size)
-{
- if (size == 0)
- {
- return;
- }
-
- mDatap = new U8[size];
- if (mDatap != NULL)
- {
- memcpy(mDatap, datap, size); /*Flawfinder: ignore*/
- }
-}
-
-LLTransferPacket::~LLTransferPacket()
-{
- delete[] mDatap;
-}
-
-//
-// LLTransferTarget implementation
-//
-
-LLTransferTarget::LLTransferTarget(
- LLTransferTargetType type,
- const LLUUID& transfer_id,
- LLTransferSourceType source_type) :
- mType(type),
- mSourceType(source_type),
- mID(transfer_id),
- mChannelp(NULL),
- mGotInfo(false),
- mSize(0),
- mLastPacketID(-1)
-{
-}
-
-LLTransferTarget::~LLTransferTarget()
-{
- // No actual cleanup of the transfer is done here, this is purely for
- // memory cleanup. The completionCallback is guaranteed to get called
- // before this happens.
- tpm_iter iter;
- for (iter = mDelayedPacketMap.begin(); iter != mDelayedPacketMap.end(); iter++)
- {
- delete iter->second;
- }
- mDelayedPacketMap.clear();
-}
-
-// This should never be called directly, the transfer manager is responsible for
-// aborting the transfer from the channel. I might want to rethink this in the
-// future, though.
-void LLTransferTarget::abortTransfer()
-{
- // Send a message up, call the completion callback
- LL_INFOS() << "LLTransferTarget::Aborting transfer " << getID() << " from " << mChannelp->getHost() << LL_ENDL;
- gMessageSystem->newMessage("TransferAbort");
- gMessageSystem->nextBlock("TransferInfo");
- gMessageSystem->addUUID("TransferID", getID());
- gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
- gMessageSystem->sendReliable(mChannelp->getHost());
-
- completionCallback(LLTS_ABORT);
-}
-
-bool LLTransferTarget::addDelayedPacket(
- const S32 packet_id,
- const LLTSCode status,
- U8* datap,
- const S32 size)
-{
- const transfer_packet_map::size_type LL_MAX_DELAYED_PACKETS = 100;
- if(mDelayedPacketMap.size() > LL_MAX_DELAYED_PACKETS)
- {
- // too many delayed packets
- return false;
- }
-
- LLTransferPacket* tpp = new LLTransferPacket(
- packet_id,
- status,
- datap,
- size);
-
-#ifdef _DEBUG
- transfer_packet_map::iterator iter = mDelayedPacketMap.find(packet_id);
- if (iter != mDelayedPacketMap.end())
- {
- if (!(iter->second->mSize == size) && !(iter->second->mDatap == datap))
- {
- LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL;
- }
- }
-#endif
-
- mDelayedPacketMap[packet_id] = tpp;
- return true;
-}
-
-
-LLTransferTarget* LLTransferTarget::createTarget(
- LLTransferTargetType type,
- const LLUUID& id,
- LLTransferSourceType source_type)
-{
- switch (type)
- {
- case LLTTT_FILE:
- return new LLTransferTargetFile(id, source_type);
- case LLTTT_VFILE:
- return new LLTransferTargetVFile(id, source_type);
- default:
- LL_WARNS() << "Unknown transfer target type: " << type << LL_ENDL;
- return NULL;
- }
-}
-
-
-LLTransferSourceParamsInvItem::LLTransferSourceParamsInvItem() : LLTransferSourceParams(LLTST_SIM_INV_ITEM), mAssetType(LLAssetType::AT_NONE)
-{
-}
-
-
-void LLTransferSourceParamsInvItem::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
-{
- mAgentID = agent_id;
- mSessionID = session_id;
-}
-
-
-void LLTransferSourceParamsInvItem::setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id)
-{
- mOwnerID = owner_id;
- mTaskID = task_id;
- mItemID = item_id;
-}
-
-
-void LLTransferSourceParamsInvItem::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
-{
- mAssetID = asset_id;
- mAssetType = asset_type;
-}
-
-
-void LLTransferSourceParamsInvItem::packParams(LLDataPacker &dp) const
-{
- LL_DEBUGS() << "LLTransferSourceParamsInvItem::packParams()" << LL_ENDL;
- dp.packUUID(mAgentID, "AgentID");
- dp.packUUID(mSessionID, "SessionID");
- dp.packUUID(mOwnerID, "OwnerID");
- dp.packUUID(mTaskID, "TaskID");
- dp.packUUID(mItemID, "ItemID");
- dp.packUUID(mAssetID, "AssetID");
- dp.packS32(mAssetType, "AssetType");
-}
-
-
-bool LLTransferSourceParamsInvItem::unpackParams(LLDataPacker &dp)
-{
- S32 tmp_at;
-
- dp.unpackUUID(mAgentID, "AgentID");
- dp.unpackUUID(mSessionID, "SessionID");
- dp.unpackUUID(mOwnerID, "OwnerID");
- dp.unpackUUID(mTaskID, "TaskID");
- dp.unpackUUID(mItemID, "ItemID");
- dp.unpackUUID(mAssetID, "AssetID");
- dp.unpackS32(tmp_at, "AssetType");
-
- mAssetType = (LLAssetType::EType)tmp_at;
-
- return true;
-}
-
-LLTransferSourceParamsEstate::LLTransferSourceParamsEstate() :
- LLTransferSourceParams(LLTST_SIM_ESTATE),
- mEstateAssetType(ET_NONE),
- mAssetType(LLAssetType::AT_NONE)
-{
-}
-
-void LLTransferSourceParamsEstate::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
-{
- mAgentID = agent_id;
- mSessionID = session_id;
-}
-
-void LLTransferSourceParamsEstate::setEstateAssetType(const EstateAssetType etype)
-{
- mEstateAssetType = etype;
-}
-
-void LLTransferSourceParamsEstate::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
-{
- mAssetID = asset_id;
- mAssetType = asset_type;
-}
-
-void LLTransferSourceParamsEstate::packParams(LLDataPacker &dp) const
-{
- dp.packUUID(mAgentID, "AgentID");
- // *NOTE: We do not want to pass the session id from the server to
- // the client, but I am not sure if anyone expects this value to
- // be set on the client.
- dp.packUUID(mSessionID, "SessionID");
- dp.packS32(mEstateAssetType, "EstateAssetType");
-}
-
-
-bool LLTransferSourceParamsEstate::unpackParams(LLDataPacker &dp)
-{
- S32 tmp_et;
-
- dp.unpackUUID(mAgentID, "AgentID");
- dp.unpackUUID(mSessionID, "SessionID");
- dp.unpackS32(tmp_et, "EstateAssetType");
-
- mEstateAssetType = (EstateAssetType)tmp_et;
-
- return true;
-}
+/**
+ * @file lltransfermanager.cpp
+ * @brief Improved transfer mechanism for moving data through the
+ * message system.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltransfermanager.h"
+
+#include "llerror.h"
+#include "message.h"
+#include "lldatapacker.h"
+
+#include "lltransfersourcefile.h"
+#include "lltransfersourceasset.h"
+#include "lltransfertargetfile.h"
+#include "lltransfertargetvfile.h"
+
+const S32 MAX_PACKET_DATA_SIZE = 2048;
+const S32 MAX_PARAMS_SIZE = 1024;
+
+LLTransferManager gTransferManager;
+LLTransferSource::stype_scfunc_map LLTransferSource::sSourceCreateMap;
+
+//
+// LLTransferManager implementation
+//
+
+LLTransferManager::LLTransferManager() :
+ mValid(false)
+{
+ S32 i;
+ for (i = 0; i < LLTTT_NUM_TYPES; i++)
+ {
+ mTransferBitsIn[i] = 0;
+ mTransferBitsOut[i] = 0;
+ }
+}
+
+
+LLTransferManager::~LLTransferManager()
+{
+ // LLTransferManager should have been cleaned up by message system shutdown process
+ llassert(!mValid);
+ if (mValid)
+ {
+ // Usually happens if OS tries to kill viewer
+ cleanup();
+ }
+}
+
+
+void LLTransferManager::init()
+{
+ if (mValid)
+ {
+ LL_ERRS() << "Double initializing LLTransferManager!" << LL_ENDL;
+ }
+ mValid = true;
+
+ // Register message system handlers
+ gMessageSystem->setHandlerFunc("TransferRequest", processTransferRequest, NULL);
+ gMessageSystem->setHandlerFunc("TransferInfo", processTransferInfo, NULL);
+ gMessageSystem->setHandlerFunc("TransferPacket", processTransferPacket, NULL);
+ gMessageSystem->setHandlerFunc("TransferAbort", processTransferAbort, NULL);
+}
+
+
+void LLTransferManager::cleanup()
+{
+ mValid = false;
+
+ host_tc_map::iterator iter;
+ for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
+ {
+ delete iter->second;
+ }
+ mTransferConnections.clear();
+}
+
+
+void LLTransferManager::updateTransfers()
+{
+ host_tc_map::iterator iter,cur;
+
+ iter = mTransferConnections.begin();
+
+ while (iter !=mTransferConnections.end())
+ {
+ cur = iter;
+ iter++;
+ cur->second->updateTransfers();
+ }
+}
+
+
+void LLTransferManager::cleanupConnection(const LLHost &host)
+{
+ host_tc_map::iterator iter;
+ iter = mTransferConnections.find(host);
+ if (iter == mTransferConnections.end())
+ {
+ // This can happen legitimately if we've never done a transfer, and we're
+ // cleaning up a circuit.
+ //LL_WARNS() << "Cleaning up nonexistent transfer connection to " << host << LL_ENDL;
+ return;
+ }
+ LLTransferConnection *connp = iter->second;
+ delete connp;
+ mTransferConnections.erase(iter);
+}
+
+
+LLTransferConnection *LLTransferManager::getTransferConnection(const LLHost &host)
+{
+ host_tc_map::iterator iter;
+ iter = mTransferConnections.find(host);
+ if (iter == mTransferConnections.end())
+ {
+ mTransferConnections[host] = new LLTransferConnection(host);
+ return mTransferConnections[host];
+ }
+
+ return iter->second;
+}
+
+
+LLTransferSourceChannel *LLTransferManager::getSourceChannel(const LLHost &host, const LLTransferChannelType type)
+{
+ LLTransferConnection *tcp = getTransferConnection(host);
+ if (!tcp)
+ {
+ return NULL;
+ }
+ return tcp->getSourceChannel(type);
+}
+
+
+
+LLTransferTargetChannel *LLTransferManager::getTargetChannel(const LLHost &host, const LLTransferChannelType type)
+{
+ LLTransferConnection *tcp = getTransferConnection(host);
+ if (!tcp)
+ {
+ return NULL;
+ }
+ return tcp->getTargetChannel(type);
+}
+
+// virtual
+LLTransferSourceParams::~LLTransferSourceParams()
+{ }
+
+
+LLTransferSource *LLTransferManager::findTransferSource(const LLUUID &transfer_id)
+{
+ // This linear traversal could screw us later if we do lots of
+ // searches for sources. However, this ONLY happens right now
+ // in asset transfer callbacks, so this should be relatively quick.
+ host_tc_map::iterator iter;
+ for (iter = mTransferConnections.begin(); iter != mTransferConnections.end(); iter++)
+ {
+ LLTransferConnection *tcp = iter->second;
+ LLTransferConnection::tsc_iter sc_iter;
+ for (sc_iter = tcp->mTransferSourceChannels.begin(); sc_iter != tcp->mTransferSourceChannels.end(); sc_iter++)
+ {
+ LLTransferSourceChannel *scp = *sc_iter;
+ LLTransferSource *sourcep = scp->findTransferSource(transfer_id);
+ if (sourcep)
+ {
+ return sourcep;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+//
+// Message handlers
+//
+
+//static
+void LLTransferManager::processTransferRequest(LLMessageSystem *msgp, void **)
+{
+ //LL_INFOS() << "LLTransferManager::processTransferRequest" << LL_ENDL;
+
+ LLUUID transfer_id;
+ LLTransferSourceType source_type;
+ LLTransferChannelType channel_type;
+ F32 priority;
+
+ msgp->getUUID("TransferInfo", "TransferID", transfer_id);
+ msgp->getS32("TransferInfo", "SourceType", (S32 &)source_type);
+ msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
+ msgp->getF32("TransferInfo", "Priority", priority);
+
+ LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
+
+ if (!tscp)
+ {
+ LL_WARNS() << "Source channel not found" << LL_ENDL;
+ return;
+ }
+
+ if (tscp->findTransferSource(transfer_id))
+ {
+ LL_WARNS() << "Duplicate request for transfer " << transfer_id << ", aborting!" << LL_ENDL;
+ return;
+ }
+
+ S32 size = msgp->getSize("TransferInfo", "Params");
+ if(size > MAX_PARAMS_SIZE)
+ {
+ LL_WARNS() << "LLTransferManager::processTransferRequest params too big."
+ << LL_ENDL;
+ return;
+ }
+
+ //LL_INFOS() << transfer_id << ":" << source_type << ":" << channel_type << ":" << priority << LL_ENDL;
+ LLTransferSource* tsp = LLTransferSource::createSource(
+ source_type,
+ transfer_id,
+ priority);
+ if(!tsp)
+ {
+ LL_WARNS() << "LLTransferManager::processTransferRequest couldn't create"
+ << " transfer source!" << LL_ENDL;
+ return;
+ }
+ U8 tmp[MAX_PARAMS_SIZE];
+ msgp->getBinaryData("TransferInfo", "Params", tmp, size);
+
+ LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
+ bool unpack_ok = tsp->unpackParams(dpb);
+ if (!unpack_ok)
+ {
+ // This should only happen if the data is corrupt or
+ // incorrectly packed.
+ // *NOTE: We may want to call abortTransfer().
+ LL_WARNS() << "LLTransferManager::processTransferRequest: bad parameters."
+ << LL_ENDL;
+ delete tsp;
+ return;
+ }
+
+ tscp->addTransferSource(tsp);
+ tsp->initTransfer();
+}
+
+
+//static
+void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
+{
+ //LL_INFOS() << "LLTransferManager::processTransferInfo" << LL_ENDL;
+
+ LLUUID transfer_id;
+ LLTransferTargetType target_type;
+ LLTransferChannelType channel_type;
+ LLTSCode status;
+ S32 size;
+
+ msgp->getUUID("TransferInfo", "TransferID", transfer_id);
+ msgp->getS32("TransferInfo", "TargetType", (S32 &)target_type);
+ msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
+ msgp->getS32("TransferInfo", "Status", (S32 &)status);
+ msgp->getS32("TransferInfo", "Size", size);
+
+ //LL_INFOS() << transfer_id << ":" << target_type<< ":" << channel_type << LL_ENDL;
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
+ if (!ttcp)
+ {
+ LL_WARNS() << "Target channel not found" << LL_ENDL;
+ // Should send a message to abort the transfer.
+ return;
+ }
+
+ LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
+ if (!ttp)
+ {
+ LL_WARNS() << "TransferInfo for unknown transfer! Not able to handle this yet!" << LL_ENDL;
+ // This could happen if we're doing a push transfer, although to avoid confusion,
+ // maybe it should be a different message.
+ return;
+ }
+
+ if (status != LLTS_OK)
+ {
+ LL_WARNS() << transfer_id << ": Non-ok status, cleaning up" << LL_ENDL;
+ ttp->completionCallback(status);
+ // Clean up the transfer.
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+
+ // unpack the params
+ S32 params_size = msgp->getSize("TransferInfo", "Params");
+ if(params_size > MAX_PARAMS_SIZE)
+ {
+ LL_WARNS() << "LLTransferManager::processTransferInfo params too big."
+ << LL_ENDL;
+ return;
+ }
+ else if(params_size > 0)
+ {
+ U8 tmp[MAX_PARAMS_SIZE];
+ msgp->getBinaryData("TransferInfo", "Params", tmp, params_size);
+ LLDataPackerBinaryBuffer dpb(tmp, MAX_PARAMS_SIZE);
+ if (!ttp->unpackParams(dpb))
+ {
+ // This should only happen if the data is corrupt or
+ // incorrectly packed.
+ LL_WARNS() << "LLTransferManager::processTransferRequest: bad params."
+ << LL_ENDL;
+ ttp->abortTransfer();
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+ }
+
+ //LL_INFOS() << "Receiving " << transfer_id << ", size " << size << " bytes" << LL_ENDL;
+ ttp->setSize(size);
+ ttp->setGotInfo(true);
+
+ // OK, at this point we to handle any delayed transfer packets (which could happen
+ // if this packet was lost)
+
+ // This is a lame cut and paste of code down below. If we change the logic down there,
+ // we HAVE to change the logic up here.
+
+ while (1)
+ {
+ S32 packet_id = 0;
+ U8 tmp_data[MAX_PACKET_DATA_SIZE];
+ // See if we've got any delayed packets
+ packet_id = ttp->getNextPacketID();
+ if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
+ {
+ // Perhaps this stuff should be inside a method in LLTransferPacket?
+ // I'm too lazy to do it now, though.
+// LL_INFOS() << "Playing back delayed packet " << packet_id << LL_ENDL;
+ LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
+
+ // This is somewhat inefficient, but avoids us having to duplicate
+ // code between the off-the-wire and delayed paths.
+ packet_id = packetp->mPacketID;
+ size = packetp->mSize;
+ if (size)
+ {
+ if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
+ {
+ memcpy(tmp_data, packetp->mDatap, size); /*Flawfinder: ignore*/
+ }
+ }
+ status = packetp->mStatus;
+ ttp->mDelayedPacketMap.erase(packet_id);
+ delete packetp;
+ }
+ else
+ {
+ // No matching delayed packet, we're done.
+ break;
+ }
+
+ LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
+ if (ret_code == LLTS_OK)
+ {
+ ttp->setLastPacketID(packet_id);
+ }
+
+ if (status != LLTS_OK)
+ {
+ if (status != LLTS_DONE)
+ {
+ LL_WARNS() << "LLTransferManager::processTransferInfo Error in playback!" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "LLTransferManager::processTransferInfo replay FINISHED for " << transfer_id << LL_ENDL;
+ }
+ // This transfer is done, either via error or not.
+ ttp->completionCallback(status);
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+ }
+}
+
+
+//static
+void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **)
+{
+ //LL_INFOS() << "LLTransferManager::processTransferPacket" << LL_ENDL;
+
+ LLUUID transfer_id;
+ LLTransferChannelType channel_type;
+ S32 packet_id;
+ LLTSCode status;
+ S32 size;
+ msgp->getUUID("TransferData", "TransferID", transfer_id);
+ msgp->getS32("TransferData", "ChannelType", (S32 &)channel_type);
+ msgp->getS32("TransferData", "Packet", packet_id);
+ msgp->getS32("TransferData", "Status", (S32 &)status);
+
+ // Find the transfer associated with this packet.
+ //LL_INFOS() << transfer_id << ":" << channel_type << LL_ENDL;
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
+ if (!ttcp)
+ {
+ LL_WARNS() << "Target channel not found" << LL_ENDL;
+ return;
+ }
+
+ LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
+ if (!ttp)
+ {
+ LL_WARNS() << "Didn't find matching transfer for " << transfer_id
+ << " processing packet " << packet_id
+ << " from " << msgp->getSender() << LL_ENDL;
+ return;
+ }
+
+ size = msgp->getSize("TransferData", "Data");
+
+ S32 msg_bytes = 0;
+ if (msgp->getReceiveCompressedSize())
+ {
+ msg_bytes = msgp->getReceiveCompressedSize();
+ }
+ else
+ {
+ msg_bytes = msgp->getReceiveSize();
+ }
+ gTransferManager.addTransferBitsIn(ttcp->mChannelType, msg_bytes*8);
+
+ if ((size < 0) || (size > MAX_PACKET_DATA_SIZE))
+ {
+ LL_WARNS() << "Invalid transfer packet size " << size << LL_ENDL;
+ return;
+ }
+
+ U8 tmp_data[MAX_PACKET_DATA_SIZE];
+ if (size > 0)
+ {
+ // Only pull the data out if the size is > 0
+ msgp->getBinaryData("TransferData", "Data", tmp_data, size);
+ }
+
+ if ((!ttp->gotInfo()) || (ttp->getNextPacketID() != packet_id))
+ {
+ // Put this on a list of packets to be delivered later.
+ if(!ttp->addDelayedPacket(packet_id, status, tmp_data, size))
+ {
+ // Whoops - failed to add a delayed packet for some reason.
+ LL_WARNS() << "Too many delayed packets processing transfer "
+ << transfer_id << " from " << msgp->getSender() << LL_ENDL;
+ ttp->abortTransfer();
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+#if 0
+ // Spammy!
+ const S32 LL_TRANSFER_WARN_GAP = 10;
+ if(!ttp->gotInfo())
+ {
+ LL_WARNS() << "Got data packet before information in transfer "
+ << transfer_id << " from " << msgp->getSender()
+ << ", got " << packet_id << LL_ENDL;
+ }
+ else if((packet_id - ttp->getNextPacketID()) > LL_TRANSFER_WARN_GAP)
+ {
+ LL_WARNS() << "Out of order packet in transfer " << transfer_id
+ << " from " << msgp->getSender() << ", got " << packet_id
+ << " expecting " << ttp->getNextPacketID() << LL_ENDL;
+ }
+#endif
+ return;
+ }
+
+ // Loop through this until we're done with all delayed packets
+
+ //
+ // NOTE: THERE IS A CUT AND PASTE OF THIS CODE IN THE TRANSFERINFO HANDLER
+ // SO WE CAN PLAY BACK DELAYED PACKETS THERE!!!!!!!!!!!!!!!!!!!!!!!!!
+ //
+ bool done = false;
+ while (!done)
+ {
+ LLTSCode ret_code = ttp->dataCallback(packet_id, tmp_data, size);
+ if (ret_code == LLTS_OK)
+ {
+ ttp->setLastPacketID(packet_id);
+ }
+
+ if (status != LLTS_OK)
+ {
+ if (status != LLTS_DONE)
+ {
+ LL_WARNS() << "LLTransferManager::processTransferPacket Error in transfer!" << LL_ENDL;
+ }
+ else
+ {
+// LL_INFOS() << "LLTransferManager::processTransferPacket done for " << transfer_id << LL_ENDL;
+ }
+ // This transfer is done, either via error or not.
+ ttp->completionCallback(status);
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+
+ // See if we've got any delayed packets
+ packet_id = ttp->getNextPacketID();
+ if (ttp->mDelayedPacketMap.find(packet_id) != ttp->mDelayedPacketMap.end())
+ {
+ // Perhaps this stuff should be inside a method in LLTransferPacket?
+ // I'm too lazy to do it now, though.
+// LL_INFOS() << "Playing back delayed packet " << packet_id << LL_ENDL;
+ LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id];
+
+ // This is somewhat inefficient, but avoids us having to duplicate
+ // code between the off-the-wire and delayed paths.
+ packet_id = packetp->mPacketID;
+ size = packetp->mSize;
+ if (size)
+ {
+ if ((packetp->mDatap != NULL) && (size<(S32)sizeof(tmp_data)))
+ {
+ memcpy(tmp_data, packetp->mDatap, size); /*Flawfinder: ignore*/
+ }
+ }
+ status = packetp->mStatus;
+ ttp->mDelayedPacketMap.erase(packet_id);
+ delete packetp;
+ }
+ else
+ {
+ // No matching delayed packet, abort it.
+ done = true;
+ }
+ }
+}
+
+
+//static
+void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
+{
+ //LL_INFOS() << "LLTransferManager::processTransferPacket" << LL_ENDL;
+
+ LLUUID transfer_id;
+ LLTransferChannelType channel_type;
+ msgp->getUUID("TransferInfo", "TransferID", transfer_id);
+ msgp->getS32("TransferInfo", "ChannelType", (S32 &)channel_type);
+
+ // See if it's a target that we're trying to abort
+ // Find the transfer associated with this packet.
+ LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(msgp->getSender(), channel_type);
+ if (ttcp)
+ {
+ LLTransferTarget *ttp = ttcp->findTransferTarget(transfer_id);
+ if (ttp)
+ {
+ ttp->abortTransfer();
+ ttcp->deleteTransfer(ttp);
+ return;
+ }
+ }
+
+ // Hmm, not a target. Maybe it's a source.
+ LLTransferSourceChannel *tscp = gTransferManager.getSourceChannel(msgp->getSender(), channel_type);
+ if (tscp)
+ {
+ LLTransferSource *tsp = tscp->findTransferSource(transfer_id);
+ if (tsp)
+ {
+ tsp->abortTransfer();
+ tscp->deleteTransfer(tsp);
+ return;
+ }
+ }
+
+ LL_WARNS() << "Couldn't find transfer " << transfer_id << " to abort!" << LL_ENDL;
+}
+
+
+//static
+void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
+{
+ LLUUID *transfer_idp = (LLUUID *)user_data;
+ if (result &&
+ transfer_idp != NULL)
+ {
+ LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
+ if (tsp)
+ {
+ LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL;
+ LLTransferSourceChannel *tscp = tsp->mChannelp;
+ tsp->abortTransfer();
+ tscp->deleteTransfer(tsp);
+ }
+ else
+ {
+ LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << LL_ENDL;
+ }
+ }
+ delete transfer_idp;
+}
+
+//
+// LLTransferConnection implementation
+//
+
+LLTransferConnection::LLTransferConnection(const LLHost &host)
+{
+ mHost = host;
+}
+
+LLTransferConnection::~LLTransferConnection()
+{
+ tsc_iter itersc;
+ for (itersc = mTransferSourceChannels.begin(); itersc != mTransferSourceChannels.end(); itersc++)
+ {
+ delete *itersc;
+ }
+ mTransferSourceChannels.clear();
+
+ ttc_iter itertc;
+ for (itertc = mTransferTargetChannels.begin(); itertc != mTransferTargetChannels.end(); itertc++)
+ {
+ delete *itertc;
+ }
+ mTransferTargetChannels.clear();
+}
+
+
+void LLTransferConnection::updateTransfers()
+{
+ // Do stuff for source transfers (basically, send data out).
+ tsc_iter iter, cur;
+ iter = mTransferSourceChannels.begin();
+
+ while (iter !=mTransferSourceChannels.end())
+ {
+ cur = iter;
+ iter++;
+ (*cur)->updateTransfers();
+ }
+
+ // Do stuff for target transfers
+ // Primarily, we should be aborting transfers that are irredeemably broken
+ // (large packet gaps that don't appear to be getting filled in, most likely)
+ // Probably should NOT be doing timeouts for other things, as new priority scheme
+ // means that a high priority transfer COULD block a transfer for a long time.
+}
+
+
+LLTransferSourceChannel *LLTransferConnection::getSourceChannel(const LLTransferChannelType channel_type)
+{
+ tsc_iter iter;
+ for (iter = mTransferSourceChannels.begin(); iter != mTransferSourceChannels.end(); iter++)
+ {
+ if ((*iter)->getChannelType() == channel_type)
+ {
+ return *iter;
+ }
+ }
+
+ LLTransferSourceChannel *tscp = new LLTransferSourceChannel(channel_type, mHost);
+ mTransferSourceChannels.push_back(tscp);
+ return tscp;
+}
+
+
+LLTransferTargetChannel *LLTransferConnection::getTargetChannel(const LLTransferChannelType channel_type)
+{
+ ttc_iter iter;
+ for (iter = mTransferTargetChannels.begin(); iter != mTransferTargetChannels.end(); iter++)
+ {
+ if ((*iter)->getChannelType() == channel_type)
+ {
+ return *iter;
+ }
+ }
+
+ LLTransferTargetChannel *ttcp = new LLTransferTargetChannel(channel_type, mHost);
+ mTransferTargetChannels.push_back(ttcp);
+ return ttcp;
+}
+
+
+//
+// LLTransferSourceChannel implementation
+//
+
+const S32 DEFAULT_PACKET_SIZE = 1000;
+
+
+LLTransferSourceChannel::LLTransferSourceChannel(const LLTransferChannelType channel_type, const LLHost &host) :
+ mChannelType(channel_type),
+ mHost(host),
+ mTransferSources(LLTransferSource::sSetPriority, LLTransferSource::sGetPriority),
+ mThrottleID(TC_ASSET)
+{
+}
+
+
+LLTransferSourceChannel::~LLTransferSourceChannel()
+{
+ LLPriQueueMap<LLTransferSource*>::pqm_iter iter =
+ mTransferSources.mMap.begin();
+ LLPriQueueMap<LLTransferSource*>::pqm_iter end =
+ mTransferSources.mMap.end();
+ for (; iter != end; ++iter)
+ {
+ // Just kill off all of the transfers
+ (*iter).second->abortTransfer();
+ delete iter->second;
+ }
+ mTransferSources.mMap.clear();
+}
+
+void LLTransferSourceChannel::updatePriority(LLTransferSource *tsp, const F32 priority)
+{
+ mTransferSources.reprioritize(priority, tsp);
+}
+
+void LLTransferSourceChannel::updateTransfers()
+{
+ // Actually, this should do the following:
+ // Decide if we can actually send data.
+ // If so, update priorities so we know who gets to send it.
+ // Send data from the sources, while updating until we've sent our throttle allocation.
+
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(getHost());
+ if (!cdp)
+ {
+ return;
+ }
+
+ if (cdp->isBlocked())
+ {
+ // *NOTE: We need to make sure that the throttle bits
+ // available gets reset.
+
+ // We DON'T want to send any packets if they're blocked, they'll just end up
+ // piling up on the other end.
+ //LL_WARNS() << "Blocking transfers due to blocked circuit for " << getHost() << LL_ENDL;
+ return;
+ }
+
+ const S32 throttle_id = mThrottleID;
+
+ LLThrottleGroup &tg = cdp->getThrottleGroup();
+
+ if (tg.checkOverflow(throttle_id, 0.f))
+ {
+ return;
+ }
+
+ LLPriQueueMap<LLTransferSource *>::pqm_iter iter, next;
+
+ bool done = false;
+ for (iter = mTransferSources.mMap.begin(); (iter != mTransferSources.mMap.end()) && !done;)
+ {
+ //LL_INFOS() << "LLTransferSourceChannel::updateTransfers()" << LL_ENDL;
+ // Do stuff.
+ next = iter;
+ next++;
+
+ LLTransferSource *tsp = iter->second;
+ U8 *datap = NULL;
+ S32 data_size = 0;
+ bool delete_data = false;
+ S32 packet_id = 0;
+ S32 sent_bytes = 0;
+ LLTSCode status = LLTS_OK;
+
+ // Get the packetID for the next packet that we're transferring.
+ packet_id = tsp->getNextPacketID();
+ status = tsp->dataCallback(packet_id, DEFAULT_PACKET_SIZE, &datap, data_size, delete_data);
+
+ if (status == LLTS_SKIP)
+ {
+ // We don't have any data, but we're not done, just go on.
+ // This will presumably be used for streaming or async transfers that
+ // are stalled waiting for data from another source.
+ iter=next;
+ continue;
+ }
+
+ LLUUID *cb_uuid = new LLUUID(tsp->getID());
+ LLUUID transaction_id = tsp->getID();
+
+ // Send the data now, even if it's an error.
+ // The status code will tell the other end what to do.
+ gMessageSystem->newMessage("TransferPacket");
+ gMessageSystem->nextBlock("TransferData");
+ gMessageSystem->addUUID("TransferID", tsp->getID());
+ gMessageSystem->addS32("ChannelType", getChannelType());
+ gMessageSystem->addS32("Packet", packet_id); // HACK! Need to put in a REAL packet id
+ gMessageSystem->addS32("Status", status);
+ gMessageSystem->addBinaryData("Data", datap, data_size);
+ sent_bytes = gMessageSystem->getCurrentSendTotal();
+ gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, true, F32Seconds(0.f),
+ LLTransferManager::reliablePacketCallback, (void**)cb_uuid);
+
+ // Do bookkeeping for the throttle
+ done = tg.throttleOverflow(throttle_id, sent_bytes*8.f);
+ gTransferManager.addTransferBitsOut(mChannelType, sent_bytes*8);
+
+ // Clean up our temporary data.
+ if (delete_data)
+ {
+ delete[] datap;
+ datap = NULL;
+ }
+
+ if (findTransferSource(transaction_id) == NULL)
+ {
+ //Warning! In the case of an aborted transfer, the sendReliable call above calls
+ //AbortTransfer which in turn calls deleteTransfer which means that somewhere way
+ //down the chain our current iter can get invalidated resulting in an infrequent
+ //sim crash. This check gets us to a valid transfer source in this event.
+ iter=next;
+ continue;
+ }
+
+ // Update the packet counter
+ tsp->setLastPacketID(packet_id);
+
+ switch (status)
+ {
+ case LLTS_OK:
+ // We're OK, don't need to do anything. Keep sending data.
+ break;
+ case LLTS_ERROR:
+ LL_WARNS() << "Error in transfer dataCallback!" << LL_ENDL;
+ // fall through
+ case LLTS_DONE:
+ // We need to clean up this transfer source.
+ //LL_INFOS() << "LLTransferSourceChannel::updateTransfers() " << tsp->getID() << " done" << LL_ENDL;
+ tsp->completionCallback(status);
+ delete tsp;
+
+ mTransferSources.mMap.erase(iter);
+ iter = next;
+ break;
+ default:
+ LL_ERRS() << "Unknown transfer error code!" << LL_ENDL;
+ }
+
+ // At this point, we should do priority adjustment (since some transfers like
+ // streaming transfers will adjust priority based on how much they've sent and time,
+ // but I'm not going to bother yet. - djs.
+ }
+}
+
+
+void LLTransferSourceChannel::addTransferSource(LLTransferSource *sourcep)
+{
+ sourcep->mChannelp = this;
+ mTransferSources.push(sourcep->getPriority(), sourcep);
+}
+
+
+LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &transfer_id)
+{
+ LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
+ for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
+ {
+ LLTransferSource *tsp = iter->second;
+ if (tsp->getID() == transfer_id)
+ {
+ return tsp;
+ }
+ }
+ return NULL;
+}
+
+
+void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
+{
+ if (tsp)
+ {
+ LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
+ for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
+ {
+ if (iter->second == tsp)
+ {
+ delete tsp;
+ mTransferSources.mMap.erase(iter);
+ return;
+ }
+ }
+
+ LL_WARNS() << "Unable to find transfer source id "
+ << tsp->getID()
+ << " to delete!"
+ << LL_ENDL;
+ }
+}
+
+
+//
+// LLTransferTargetChannel implementation
+//
+
+LLTransferTargetChannel::LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host) :
+ mChannelType(channel_type),
+ mHost(host)
+{
+}
+
+LLTransferTargetChannel::~LLTransferTargetChannel()
+{
+ tt_iter iter;
+ for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
+ {
+ // Abort all of the current transfers
+ (*iter)->abortTransfer();
+ delete *iter;
+ }
+ mTransferTargets.clear();
+}
+
+
+void LLTransferTargetChannel::requestTransfer(
+ const LLTransferSourceParams& source_params,
+ const LLTransferTargetParams& target_params,
+ const F32 priority)
+{
+ LLUUID id;
+ id.generate();
+ LLTransferTarget* ttp = LLTransferTarget::createTarget(
+ target_params.getType(),
+ id,
+ source_params.getType());
+ if (!ttp)
+ {
+ LL_WARNS() << "LLTransferManager::requestTransfer aborting due to target creation failure!" << LL_ENDL;
+ return;
+ }
+
+ ttp->applyParams(target_params);
+ addTransferTarget(ttp);
+
+ sendTransferRequest(ttp, source_params, priority);
+}
+
+
+void LLTransferTargetChannel::sendTransferRequest(LLTransferTarget *targetp,
+ const LLTransferSourceParams &params,
+ const F32 priority)
+{
+ //
+ // Pack the message with data which explains how to get the source, and
+ // send it off to the source for this channel.
+ //
+ llassert(targetp);
+ llassert(targetp->getChannel() == this);
+
+ gMessageSystem->newMessage("TransferRequest");
+ gMessageSystem->nextBlock("TransferInfo");
+ gMessageSystem->addUUID("TransferID", targetp->getID());
+ gMessageSystem->addS32("SourceType", params.getType());
+ gMessageSystem->addS32("ChannelType", getChannelType());
+ gMessageSystem->addF32("Priority", priority);
+
+ U8 tmp[MAX_PARAMS_SIZE];
+ LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
+ params.packParams(dp);
+ S32 len = dp.getCurrentSize();
+ gMessageSystem->addBinaryData("Params", tmp, len);
+
+ gMessageSystem->sendReliable(mHost);
+}
+
+
+void LLTransferTargetChannel::addTransferTarget(LLTransferTarget *targetp)
+{
+ targetp->mChannelp = this;
+ mTransferTargets.push_back(targetp);
+}
+
+
+LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &transfer_id)
+{
+ tt_iter iter;
+ for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
+ {
+ LLTransferTarget *ttp = *iter;
+ if (ttp->getID() == transfer_id)
+ {
+ return ttp;
+ }
+ }
+ return NULL;
+}
+
+
+void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
+{
+ if (ttp)
+ {
+ tt_iter iter;
+ for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
+ {
+ if (*iter == ttp)
+ {
+ delete ttp;
+ mTransferTargets.erase(iter);
+ return;
+ }
+ }
+
+ LL_WARNS() << "Unable to find transfer target id "
+ << ttp->getID()
+ << " to delete!"
+ << LL_ENDL;
+ }
+}
+
+
+//
+// LLTransferSource implementation
+//
+
+LLTransferSource::LLTransferSource(const LLTransferSourceType type,
+ const LLUUID &transfer_id,
+ const F32 priority) :
+ mType(type),
+ mID(transfer_id),
+ mChannelp(NULL),
+ mPriority(priority),
+ mSize(0),
+ mLastPacketID(-1)
+{
+ setPriority(priority);
+}
+
+
+LLTransferSource::~LLTransferSource()
+{
+ // No actual cleanup of the transfer is done here, this is purely for
+ // memory cleanup. The completionCallback is guaranteed to get called
+ // before this happens.
+}
+
+
+void LLTransferSource::sendTransferStatus(LLTSCode status)
+{
+ gMessageSystem->newMessage("TransferInfo");
+ gMessageSystem->nextBlock("TransferInfo");
+ gMessageSystem->addUUID("TransferID", getID());
+ gMessageSystem->addS32("TargetType", LLTTT_UNKNOWN);
+ gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
+ gMessageSystem->addS32("Status", status);
+ gMessageSystem->addS32("Size", mSize);
+ U8 tmp[MAX_PARAMS_SIZE];
+ LLDataPackerBinaryBuffer dp(tmp, MAX_PARAMS_SIZE);
+ packParams(dp);
+ S32 len = dp.getCurrentSize();
+ gMessageSystem->addBinaryData("Params", tmp, len);
+ gMessageSystem->sendReliable(mChannelp->getHost());
+
+ // Abort if there was as asset system issue.
+ if (status != LLTS_OK)
+ {
+ completionCallback(status);
+ mChannelp->deleteTransfer(this);
+ }
+}
+
+
+// This should never be called directly, the transfer manager is responsible for
+// aborting the transfer from the channel. I might want to rethink this in the
+// future, though.
+void LLTransferSource::abortTransfer()
+{
+ // Send a message down, call the completion callback
+ LL_INFOS() << "LLTransferSource::Aborting transfer " << getID() << " to " << mChannelp->getHost() << LL_ENDL;
+ gMessageSystem->newMessage("TransferAbort");
+ gMessageSystem->nextBlock("TransferInfo");
+ gMessageSystem->addUUID("TransferID", getID());
+ gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
+ gMessageSystem->sendReliable(mChannelp->getHost());
+
+ completionCallback(LLTS_ABORT);
+}
+
+
+//static
+void LLTransferSource::registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc func)
+{
+ if (sSourceCreateMap.count(stype))
+ {
+ // Disallow changing what class handles a source type
+ // Unclear when you would want to do this, and whether it would work.
+ LL_ERRS() << "Reregistering source type " << stype << LL_ENDL;
+ }
+ else
+ {
+ sSourceCreateMap[stype] = func;
+ }
+}
+
+//static
+LLTransferSource *LLTransferSource::createSource(const LLTransferSourceType stype,
+ const LLUUID &id,
+ const F32 priority)
+{
+ switch (stype)
+ {
+ // *NOTE: The source file transfer mechanism is highly insecure and could
+ // lead to easy exploitation of a server process.
+ // I have removed all uses of it from the codebase. Phoenix.
+ //
+ //case LLTST_FILE:
+ // return new LLTransferSourceFile(id, priority);
+ case LLTST_ASSET:
+ return new LLTransferSourceAsset(id, priority);
+ default:
+ {
+ if (!sSourceCreateMap.count(stype))
+ {
+ // Use the callback to create the source type if it's not there.
+ LL_WARNS() << "Unknown transfer source type: " << stype << LL_ENDL;
+ return NULL;
+ }
+ return (sSourceCreateMap[stype])(id, priority);
+ }
+ }
+}
+
+
+// static
+void LLTransferSource::sSetPriority(LLTransferSource *&tsp, const F32 priority)
+{
+ tsp->setPriority(priority);
+}
+
+
+// static
+F32 LLTransferSource::sGetPriority(LLTransferSource *&tsp)
+{
+ return tsp->getPriority();
+}
+
+
+//
+// LLTransferPacket implementation
+//
+
+LLTransferPacket::LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size) :
+ mPacketID(packet_id),
+ mStatus(status),
+ mDatap(NULL),
+ mSize(size)
+{
+ if (size == 0)
+ {
+ return;
+ }
+
+ mDatap = new U8[size];
+ if (mDatap != NULL)
+ {
+ memcpy(mDatap, datap, size); /*Flawfinder: ignore*/
+ }
+}
+
+LLTransferPacket::~LLTransferPacket()
+{
+ delete[] mDatap;
+}
+
+//
+// LLTransferTarget implementation
+//
+
+LLTransferTarget::LLTransferTarget(
+ LLTransferTargetType type,
+ const LLUUID& transfer_id,
+ LLTransferSourceType source_type) :
+ mType(type),
+ mSourceType(source_type),
+ mID(transfer_id),
+ mChannelp(NULL),
+ mGotInfo(false),
+ mSize(0),
+ mLastPacketID(-1)
+{
+}
+
+LLTransferTarget::~LLTransferTarget()
+{
+ // No actual cleanup of the transfer is done here, this is purely for
+ // memory cleanup. The completionCallback is guaranteed to get called
+ // before this happens.
+ tpm_iter iter;
+ for (iter = mDelayedPacketMap.begin(); iter != mDelayedPacketMap.end(); iter++)
+ {
+ delete iter->second;
+ }
+ mDelayedPacketMap.clear();
+}
+
+// This should never be called directly, the transfer manager is responsible for
+// aborting the transfer from the channel. I might want to rethink this in the
+// future, though.
+void LLTransferTarget::abortTransfer()
+{
+ // Send a message up, call the completion callback
+ LL_INFOS() << "LLTransferTarget::Aborting transfer " << getID() << " from " << mChannelp->getHost() << LL_ENDL;
+ gMessageSystem->newMessage("TransferAbort");
+ gMessageSystem->nextBlock("TransferInfo");
+ gMessageSystem->addUUID("TransferID", getID());
+ gMessageSystem->addS32("ChannelType", mChannelp->getChannelType());
+ gMessageSystem->sendReliable(mChannelp->getHost());
+
+ completionCallback(LLTS_ABORT);
+}
+
+bool LLTransferTarget::addDelayedPacket(
+ const S32 packet_id,
+ const LLTSCode status,
+ U8* datap,
+ const S32 size)
+{
+ const transfer_packet_map::size_type LL_MAX_DELAYED_PACKETS = 100;
+ if(mDelayedPacketMap.size() > LL_MAX_DELAYED_PACKETS)
+ {
+ // too many delayed packets
+ return false;
+ }
+
+ LLTransferPacket* tpp = new LLTransferPacket(
+ packet_id,
+ status,
+ datap,
+ size);
+
+#ifdef _DEBUG
+ transfer_packet_map::iterator iter = mDelayedPacketMap.find(packet_id);
+ if (iter != mDelayedPacketMap.end())
+ {
+ if (!(iter->second->mSize == size) && !(iter->second->mDatap == datap))
+ {
+ LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL;
+ }
+ }
+#endif
+
+ mDelayedPacketMap[packet_id] = tpp;
+ return true;
+}
+
+
+LLTransferTarget* LLTransferTarget::createTarget(
+ LLTransferTargetType type,
+ const LLUUID& id,
+ LLTransferSourceType source_type)
+{
+ switch (type)
+ {
+ case LLTTT_FILE:
+ return new LLTransferTargetFile(id, source_type);
+ case LLTTT_VFILE:
+ return new LLTransferTargetVFile(id, source_type);
+ default:
+ LL_WARNS() << "Unknown transfer target type: " << type << LL_ENDL;
+ return NULL;
+ }
+}
+
+
+LLTransferSourceParamsInvItem::LLTransferSourceParamsInvItem() : LLTransferSourceParams(LLTST_SIM_INV_ITEM), mAssetType(LLAssetType::AT_NONE)
+{
+}
+
+
+void LLTransferSourceParamsInvItem::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
+{
+ mAgentID = agent_id;
+ mSessionID = session_id;
+}
+
+
+void LLTransferSourceParamsInvItem::setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id)
+{
+ mOwnerID = owner_id;
+ mTaskID = task_id;
+ mItemID = item_id;
+}
+
+
+void LLTransferSourceParamsInvItem::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
+{
+ mAssetID = asset_id;
+ mAssetType = asset_type;
+}
+
+
+void LLTransferSourceParamsInvItem::packParams(LLDataPacker &dp) const
+{
+ LL_DEBUGS() << "LLTransferSourceParamsInvItem::packParams()" << LL_ENDL;
+ dp.packUUID(mAgentID, "AgentID");
+ dp.packUUID(mSessionID, "SessionID");
+ dp.packUUID(mOwnerID, "OwnerID");
+ dp.packUUID(mTaskID, "TaskID");
+ dp.packUUID(mItemID, "ItemID");
+ dp.packUUID(mAssetID, "AssetID");
+ dp.packS32(mAssetType, "AssetType");
+}
+
+
+bool LLTransferSourceParamsInvItem::unpackParams(LLDataPacker &dp)
+{
+ S32 tmp_at;
+
+ dp.unpackUUID(mAgentID, "AgentID");
+ dp.unpackUUID(mSessionID, "SessionID");
+ dp.unpackUUID(mOwnerID, "OwnerID");
+ dp.unpackUUID(mTaskID, "TaskID");
+ dp.unpackUUID(mItemID, "ItemID");
+ dp.unpackUUID(mAssetID, "AssetID");
+ dp.unpackS32(tmp_at, "AssetType");
+
+ mAssetType = (LLAssetType::EType)tmp_at;
+
+ return true;
+}
+
+LLTransferSourceParamsEstate::LLTransferSourceParamsEstate() :
+ LLTransferSourceParams(LLTST_SIM_ESTATE),
+ mEstateAssetType(ET_NONE),
+ mAssetType(LLAssetType::AT_NONE)
+{
+}
+
+void LLTransferSourceParamsEstate::setAgentSession(const LLUUID &agent_id, const LLUUID &session_id)
+{
+ mAgentID = agent_id;
+ mSessionID = session_id;
+}
+
+void LLTransferSourceParamsEstate::setEstateAssetType(const EstateAssetType etype)
+{
+ mEstateAssetType = etype;
+}
+
+void LLTransferSourceParamsEstate::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
+{
+ mAssetID = asset_id;
+ mAssetType = asset_type;
+}
+
+void LLTransferSourceParamsEstate::packParams(LLDataPacker &dp) const
+{
+ dp.packUUID(mAgentID, "AgentID");
+ // *NOTE: We do not want to pass the session id from the server to
+ // the client, but I am not sure if anyone expects this value to
+ // be set on the client.
+ dp.packUUID(mSessionID, "SessionID");
+ dp.packS32(mEstateAssetType, "EstateAssetType");
+}
+
+
+bool LLTransferSourceParamsEstate::unpackParams(LLDataPacker &dp)
+{
+ S32 tmp_et;
+
+ dp.unpackUUID(mAgentID, "AgentID");
+ dp.unpackUUID(mSessionID, "SessionID");
+ dp.unpackS32(tmp_et, "EstateAssetType");
+
+ mEstateAssetType = (EstateAssetType)tmp_et;
+
+ return true;
+}
diff --git a/indra/llmessage/lltransfermanager.h b/indra/llmessage/lltransfermanager.h
index 15097642b4..184ff2563a 100644
--- a/indra/llmessage/lltransfermanager.h
+++ b/indra/llmessage/lltransfermanager.h
@@ -1,499 +1,499 @@
-/**
- * @file lltransfermanager.h
- * @brief Improved transfer mechanism for moving data through the
- * message system.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTRANSFERMANAGER_H
-#define LL_LLTRANSFERMANAGER_H
-
-#include <map>
-#include <list>
-
-#include "llhost.h"
-#include "lluuid.h"
-#include "llthrottle.h"
-#include "llpriqueuemap.h"
-#include "llassettype.h"
-
-//
-// Definition of the manager class for the new LLXfer replacement.
-// Provides prioritized, bandwidth-throttled transport of arbitrary
-// binary data between host/circuit combos
-//
-
-
-typedef enum e_transfer_channel_type
-{
- LLTCT_UNKNOWN = 0,
- LLTCT_MISC,
- LLTCT_ASSET,
- LLTCT_NUM_TYPES
-} LLTransferChannelType;
-
-
-typedef enum e_transfer_source_type
-{
- LLTST_UNKNOWN = 0,
- LLTST_FILE,
- LLTST_ASSET,
- LLTST_SIM_INV_ITEM, // Simulator specific, may not be handled
- LLTST_SIM_ESTATE, // Simulator specific, may not be handled
- LLTST_NUM_TYPES
-} LLTransferSourceType;
-
-
-typedef enum e_transfer_target_type
-{
- LLTTT_UNKNOWN = 0,
- LLTTT_FILE,
- LLTTT_VFILE,
- LLTTT_NUM_TYPES
-} LLTransferTargetType;
-
-
-// Errors are negative, expected values are positive.
-typedef enum e_status_codes
-{
- LLTS_OK = 0,
- LLTS_DONE = 1,
- LLTS_SKIP = 2,
- LLTS_ABORT = 3,
- LLTS_ERROR = -1,
- LLTS_UNKNOWN_SOURCE = -2, // Equivalent of a 404
- LLTS_INSUFFICIENT_PERMISSIONS = -3 // Not enough permissions
-} LLTSCode;
-
-// Types of requests for estate wide information
-typedef enum e_estate_type
-{
- ET_Covenant = 0,
- ET_NONE = -1
-} EstateAssetType;
-
-class LLMessageSystem;
-class LLDataPacker;
-
-class LLTransferConnection;
-class LLTransferSourceChannel;
-class LLTransferTargetChannel;
-class LLTransferSourceParams;
-class LLTransferTargetParams;
-class LLTransferSource;
-class LLTransferTarget;
-
-class LLTransferManager
-{
-public:
- LLTransferManager();
- virtual ~LLTransferManager();
-
- void init();
- void cleanup();
-
- void updateTransfers(); // Called per frame to push packets out on the various different channels.
- void cleanupConnection(const LLHost &host);
-
-
- LLTransferSourceChannel *getSourceChannel(const LLHost &host, const LLTransferChannelType stype);
- LLTransferTargetChannel *getTargetChannel(const LLHost &host, const LLTransferChannelType stype);
-
- LLTransferSource *findTransferSource(const LLUUID &transfer_id);
-
- bool isValid() const { return mValid; }
-
- static void processTransferRequest(LLMessageSystem *mesgsys, void **);
- static void processTransferInfo(LLMessageSystem *mesgsys, void **);
- static void processTransferPacket(LLMessageSystem *mesgsys, void **);
- static void processTransferAbort(LLMessageSystem *mesgsys, void **);
-
- static void reliablePacketCallback(void **, S32 result);
-
- S32 getTransferBitsIn(const LLTransferChannelType tctype) const { return mTransferBitsIn[tctype]; }
- S32 getTransferBitsOut(const LLTransferChannelType tctype) const { return mTransferBitsOut[tctype]; }
- void resetTransferBitsIn(const LLTransferChannelType tctype) { mTransferBitsIn[tctype] = 0; }
- void resetTransferBitsOut(const LLTransferChannelType tctype) { mTransferBitsOut[tctype] = 0; }
- void addTransferBitsIn(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsIn[tctype] += bits; }
- void addTransferBitsOut(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsOut[tctype] += bits; }
-protected:
- LLTransferConnection *getTransferConnection(const LLHost &host);
- bool removeTransferConnection(const LLHost &host);
-
-protected:
- // Convenient typedefs
- typedef std::map<LLHost, LLTransferConnection *> host_tc_map;
-
- bool mValid;
- LLHost mHost;
-
- S32 mTransferBitsIn[LLTTT_NUM_TYPES];
- S32 mTransferBitsOut[LLTTT_NUM_TYPES];
-
- // We keep a map between each host and LLTransferConnection.
- host_tc_map mTransferConnections;
-};
-
-
-//
-// Keeps tracks of all channels to/from a particular host.
-//
-class LLTransferConnection
-{
-public:
- LLTransferConnection(const LLHost &host);
- virtual ~LLTransferConnection();
-
- void updateTransfers();
-
- LLTransferSourceChannel *getSourceChannel(const LLTransferChannelType type);
- LLTransferTargetChannel *getTargetChannel(const LLTransferChannelType type);
-
- // Convenient typedefs
- typedef std::list<LLTransferSourceChannel *>::iterator tsc_iter;
- typedef std::list<LLTransferTargetChannel *>::iterator ttc_iter;
- friend class LLTransferManager;
-protected:
-
- LLHost mHost;
- std::list<LLTransferSourceChannel *> mTransferSourceChannels;
- std::list<LLTransferTargetChannel *> mTransferTargetChannels;
-
-};
-
-
-//
-// A channel which is pushing data out.
-//
-
-class LLTransferSourceChannel
-{
-public:
- LLTransferSourceChannel(const LLTransferChannelType channel_type,
- const LLHost &host);
- virtual ~LLTransferSourceChannel();
-
- void updateTransfers();
-
- void updatePriority(LLTransferSource *tsp, const F32 priority);
-
- void addTransferSource(LLTransferSource *sourcep);
- LLTransferSource *findTransferSource(const LLUUID &transfer_id);
- void deleteTransfer(LLTransferSource *tsp);
-
- void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; }
-
- LLTransferChannelType getChannelType() const { return mChannelType; }
- LLHost getHost() const { return mHost; }
-
-protected:
- typedef std::list<LLTransferSource *>::iterator ts_iter;
-
- LLTransferChannelType mChannelType;
- LLHost mHost;
- LLPriQueueMap<LLTransferSource*> mTransferSources;
-
- // The throttle that this source channel should use
- S32 mThrottleID;
-};
-
-
-//
-// A channel receiving data from a source.
-//
-class LLTransferTargetChannel
-{
-public:
- LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host);
- virtual ~LLTransferTargetChannel();
-
- void requestTransfer(const LLTransferSourceParams &source_params,
- const LLTransferTargetParams &target_params,
- const F32 priority);
-
- LLTransferTarget *findTransferTarget(const LLUUID &transfer_id);
- void deleteTransfer(LLTransferTarget *ttp);
-
-
- LLTransferChannelType getChannelType() const { return mChannelType; }
- LLHost getHost() const { return mHost; }
-
-protected:
- void sendTransferRequest(LLTransferTarget *targetp,
- const LLTransferSourceParams &params,
- const F32 priority);
-
- void addTransferTarget(LLTransferTarget *targetp);
-
- friend class LLTransferTarget;
- friend class LLTransferManager;
-protected:
- typedef std::list<LLTransferTarget *>::iterator tt_iter;
-
- LLTransferChannelType mChannelType;
- LLHost mHost;
- std::list<LLTransferTarget *> mTransferTargets;
-};
-
-
-class LLTransferSourceParams
-{
-public:
- LLTransferSourceParams(const LLTransferSourceType type) : mType(type) { }
- virtual ~LLTransferSourceParams();
-
- virtual void packParams(LLDataPacker &dp) const = 0;
- virtual bool unpackParams(LLDataPacker &dp) = 0;
-
- LLTransferSourceType getType() const { return mType; }
-
-protected:
- LLTransferSourceType mType;
-};
-
-
-//
-// LLTransferSource is an interface, all transfer sources should be derived from it.
-//
-typedef LLTransferSource *(*LLTransferSourceCreateFunc)(const LLUUID &id, const F32 priority);
-
-class LLTransferSource
-{
-public:
-
- LLUUID getID() { return mID; }
-
- friend class LLTransferManager;
- friend class LLTransferSourceChannel;
-
-protected:
- LLTransferSource(const LLTransferSourceType source_type,
- const LLUUID &request_id,
- const F32 priority);
- virtual ~LLTransferSource();
-
- void sendTransferStatus(LLTSCode status); // When you've figured out your transfer status, do this
-
- virtual void initTransfer() = 0;
- virtual F32 updatePriority() = 0;
- virtual LLTSCode dataCallback(const S32 packet_id,
- const S32 max_bytes,
- U8 **datap,
- S32 &returned_bytes,
- bool &delete_returned) = 0;
-
- // The completionCallback is GUARANTEED to be called before the destructor.
- virtual void completionCallback(const LLTSCode status) = 0;
-
- virtual void packParams(LLDataPacker& dp) const = 0;
- virtual bool unpackParams(LLDataPacker& dp) = 0;
-
- virtual S32 getNextPacketID() { return mLastPacketID + 1; }
- virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; }
-
-
- // For now, no self-induced priority changes
- F32 getPriority() { return mPriority; }
- void setPriority(const F32 pri) { mPriority = pri; }
-
- virtual void abortTransfer(); // DON'T USE THIS ONE, used internally by LLTransferManager
-
- static LLTransferSource *createSource(const LLTransferSourceType stype,
- const LLUUID &request_id,
- const F32 priority);
- static void registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc);
-
- static void sSetPriority(LLTransferSource *&tsp, const F32 priority);
- static F32 sGetPriority(LLTransferSource *&tsp);
-protected:
- typedef std::map<LLTransferSourceType, LLTransferSourceCreateFunc> stype_scfunc_map;
- static stype_scfunc_map sSourceCreateMap;
-
- LLTransferSourceType mType;
- LLUUID mID;
- LLTransferSourceChannel *mChannelp;
- F32 mPriority;
- S32 mSize;
- S32 mLastPacketID;
-};
-
-
-class LLTransferTargetParams
-{
-public:
- LLTransferTargetParams(const LLTransferTargetType type) : mType(type) {}
- LLTransferTargetType getType() const { return mType; }
-protected:
- LLTransferTargetType mType;
-};
-
-
-class LLTransferPacket
-{
- // Used for storing a packet that's being delivered later because it's out of order.
- // ONLY should be accessed by the following two classes, for now.
- friend class LLTransferTarget;
- friend class LLTransferManager;
-
-protected:
-
- LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size);
- virtual ~LLTransferPacket();
-
-protected:
- S32 mPacketID;
- LLTSCode mStatus;
- U8 *mDatap;
- S32 mSize;
-};
-
-
-class LLTransferTarget
-{
-public:
- LLTransferTarget(
- LLTransferTargetType target_type,
- const LLUUID& transfer_id,
- LLTransferSourceType source_type);
- virtual ~LLTransferTarget();
-
- // Accessors
- LLUUID getID() const { return mID; }
- LLTransferTargetType getType() const { return mType; }
- LLTransferTargetChannel *getChannel() const { return mChannelp; }
- LLTransferSourceType getSourceType() const { return mSourceType; }
-
- // Static functionality
- static LLTransferTarget* createTarget(
- LLTransferTargetType target_type,
- const LLUUID& request_id,
- LLTransferSourceType source_type);
-
- // friends
- friend class LLTransferManager;
- friend class LLTransferTargetChannel;
-
-protected:
- // Implementation
- virtual bool unpackParams(LLDataPacker& dp) = 0;
- virtual void applyParams(const LLTransferTargetParams &params) = 0;
- virtual LLTSCode dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size) = 0;
-
- // The completionCallback is GUARANTEED to be called before the destructor, so all handling
- // of errors/aborts should be done here.
- virtual void completionCallback(const LLTSCode status) = 0;
-
- void abortTransfer();
-
- virtual S32 getNextPacketID() { return mLastPacketID + 1; }
- virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; }
- void setSize(const S32 size) { mSize = size; }
- void setGotInfo(const bool got_info) { mGotInfo = got_info; }
- bool gotInfo() const { return mGotInfo; }
-
- bool addDelayedPacket(
- const S32 packet_id,
- const LLTSCode status,
- U8* datap,
- const S32 size);
-
-protected:
- typedef std::map<S32, LLTransferPacket *> transfer_packet_map;
- typedef std::map<S32, LLTransferPacket *>::iterator tpm_iter;
-
- LLTransferTargetType mType;
- LLTransferSourceType mSourceType;
- LLUUID mID;
- LLTransferTargetChannel *mChannelp;
- bool mGotInfo;
- S32 mSize;
- S32 mLastPacketID;
-
- transfer_packet_map mDelayedPacketMap; // Packets that are waiting because of missing/out of order issues
-};
-
-
-// Hack, here so it's publicly available even though LLTransferSourceInvItem is only available on the simulator
-class LLTransferSourceParamsInvItem: public LLTransferSourceParams
-{
-public:
- LLTransferSourceParamsInvItem();
- virtual ~LLTransferSourceParamsInvItem() {}
- /*virtual*/ void packParams(LLDataPacker &dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
- void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id);
- void setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id);
- void setAsset(const LLUUID &asset_id, const LLAssetType::EType at);
-
- LLUUID getAgentID() const { return mAgentID; }
- LLUUID getSessionID() const { return mSessionID; }
- LLUUID getOwnerID() const { return mOwnerID; }
- LLUUID getTaskID() const { return mTaskID; }
- LLUUID getItemID() const { return mItemID; }
- LLUUID getAssetID() const { return mAssetID; }
- LLAssetType::EType getAssetType() const { return mAssetType; }
-
-protected:
- LLUUID mAgentID;
- LLUUID mSessionID;
- LLUUID mOwnerID;
- LLUUID mTaskID;
- LLUUID mItemID;
- LLUUID mAssetID;
- LLAssetType::EType mAssetType;
-};
-
-
-// Hack, here so it's publicly available even though LLTransferSourceEstate is only available on the simulator
-class LLTransferSourceParamsEstate: public LLTransferSourceParams
-{
-public:
- LLTransferSourceParamsEstate();
- virtual ~LLTransferSourceParamsEstate() {}
- /*virtual*/ void packParams(LLDataPacker &dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
- void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id);
- void setEstateAssetType(const EstateAssetType etype);
- void setAsset(const LLUUID &asset_id, const LLAssetType::EType at);
-
- LLUUID getAgentID() const { return mAgentID; }
- LLUUID getSessionID() const { return mSessionID; }
- EstateAssetType getEstateAssetType() const { return mEstateAssetType; }
- LLUUID getAssetID() const { return mAssetID; }
- LLAssetType::EType getAssetType() const { return mAssetType; }
-
-protected:
- LLUUID mAgentID;
- LLUUID mSessionID;
- EstateAssetType mEstateAssetType;
- // these are set on the sim based on estateinfotype
- LLUUID mAssetID;
- LLAssetType::EType mAssetType;
-};
-
-
-extern LLTransferManager gTransferManager;
-
-#endif//LL_LLTRANSFERMANAGER_H
+/**
+ * @file lltransfermanager.h
+ * @brief Improved transfer mechanism for moving data through the
+ * message system.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRANSFERMANAGER_H
+#define LL_LLTRANSFERMANAGER_H
+
+#include <map>
+#include <list>
+
+#include "llhost.h"
+#include "lluuid.h"
+#include "llthrottle.h"
+#include "llpriqueuemap.h"
+#include "llassettype.h"
+
+//
+// Definition of the manager class for the new LLXfer replacement.
+// Provides prioritized, bandwidth-throttled transport of arbitrary
+// binary data between host/circuit combos
+//
+
+
+typedef enum e_transfer_channel_type
+{
+ LLTCT_UNKNOWN = 0,
+ LLTCT_MISC,
+ LLTCT_ASSET,
+ LLTCT_NUM_TYPES
+} LLTransferChannelType;
+
+
+typedef enum e_transfer_source_type
+{
+ LLTST_UNKNOWN = 0,
+ LLTST_FILE,
+ LLTST_ASSET,
+ LLTST_SIM_INV_ITEM, // Simulator specific, may not be handled
+ LLTST_SIM_ESTATE, // Simulator specific, may not be handled
+ LLTST_NUM_TYPES
+} LLTransferSourceType;
+
+
+typedef enum e_transfer_target_type
+{
+ LLTTT_UNKNOWN = 0,
+ LLTTT_FILE,
+ LLTTT_VFILE,
+ LLTTT_NUM_TYPES
+} LLTransferTargetType;
+
+
+// Errors are negative, expected values are positive.
+typedef enum e_status_codes
+{
+ LLTS_OK = 0,
+ LLTS_DONE = 1,
+ LLTS_SKIP = 2,
+ LLTS_ABORT = 3,
+ LLTS_ERROR = -1,
+ LLTS_UNKNOWN_SOURCE = -2, // Equivalent of a 404
+ LLTS_INSUFFICIENT_PERMISSIONS = -3 // Not enough permissions
+} LLTSCode;
+
+// Types of requests for estate wide information
+typedef enum e_estate_type
+{
+ ET_Covenant = 0,
+ ET_NONE = -1
+} EstateAssetType;
+
+class LLMessageSystem;
+class LLDataPacker;
+
+class LLTransferConnection;
+class LLTransferSourceChannel;
+class LLTransferTargetChannel;
+class LLTransferSourceParams;
+class LLTransferTargetParams;
+class LLTransferSource;
+class LLTransferTarget;
+
+class LLTransferManager
+{
+public:
+ LLTransferManager();
+ virtual ~LLTransferManager();
+
+ void init();
+ void cleanup();
+
+ void updateTransfers(); // Called per frame to push packets out on the various different channels.
+ void cleanupConnection(const LLHost &host);
+
+
+ LLTransferSourceChannel *getSourceChannel(const LLHost &host, const LLTransferChannelType stype);
+ LLTransferTargetChannel *getTargetChannel(const LLHost &host, const LLTransferChannelType stype);
+
+ LLTransferSource *findTransferSource(const LLUUID &transfer_id);
+
+ bool isValid() const { return mValid; }
+
+ static void processTransferRequest(LLMessageSystem *mesgsys, void **);
+ static void processTransferInfo(LLMessageSystem *mesgsys, void **);
+ static void processTransferPacket(LLMessageSystem *mesgsys, void **);
+ static void processTransferAbort(LLMessageSystem *mesgsys, void **);
+
+ static void reliablePacketCallback(void **, S32 result);
+
+ S32 getTransferBitsIn(const LLTransferChannelType tctype) const { return mTransferBitsIn[tctype]; }
+ S32 getTransferBitsOut(const LLTransferChannelType tctype) const { return mTransferBitsOut[tctype]; }
+ void resetTransferBitsIn(const LLTransferChannelType tctype) { mTransferBitsIn[tctype] = 0; }
+ void resetTransferBitsOut(const LLTransferChannelType tctype) { mTransferBitsOut[tctype] = 0; }
+ void addTransferBitsIn(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsIn[tctype] += bits; }
+ void addTransferBitsOut(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsOut[tctype] += bits; }
+protected:
+ LLTransferConnection *getTransferConnection(const LLHost &host);
+ bool removeTransferConnection(const LLHost &host);
+
+protected:
+ // Convenient typedefs
+ typedef std::map<LLHost, LLTransferConnection *> host_tc_map;
+
+ bool mValid;
+ LLHost mHost;
+
+ S32 mTransferBitsIn[LLTTT_NUM_TYPES];
+ S32 mTransferBitsOut[LLTTT_NUM_TYPES];
+
+ // We keep a map between each host and LLTransferConnection.
+ host_tc_map mTransferConnections;
+};
+
+
+//
+// Keeps tracks of all channels to/from a particular host.
+//
+class LLTransferConnection
+{
+public:
+ LLTransferConnection(const LLHost &host);
+ virtual ~LLTransferConnection();
+
+ void updateTransfers();
+
+ LLTransferSourceChannel *getSourceChannel(const LLTransferChannelType type);
+ LLTransferTargetChannel *getTargetChannel(const LLTransferChannelType type);
+
+ // Convenient typedefs
+ typedef std::list<LLTransferSourceChannel *>::iterator tsc_iter;
+ typedef std::list<LLTransferTargetChannel *>::iterator ttc_iter;
+ friend class LLTransferManager;
+protected:
+
+ LLHost mHost;
+ std::list<LLTransferSourceChannel *> mTransferSourceChannels;
+ std::list<LLTransferTargetChannel *> mTransferTargetChannels;
+
+};
+
+
+//
+// A channel which is pushing data out.
+//
+
+class LLTransferSourceChannel
+{
+public:
+ LLTransferSourceChannel(const LLTransferChannelType channel_type,
+ const LLHost &host);
+ virtual ~LLTransferSourceChannel();
+
+ void updateTransfers();
+
+ void updatePriority(LLTransferSource *tsp, const F32 priority);
+
+ void addTransferSource(LLTransferSource *sourcep);
+ LLTransferSource *findTransferSource(const LLUUID &transfer_id);
+ void deleteTransfer(LLTransferSource *tsp);
+
+ void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; }
+
+ LLTransferChannelType getChannelType() const { return mChannelType; }
+ LLHost getHost() const { return mHost; }
+
+protected:
+ typedef std::list<LLTransferSource *>::iterator ts_iter;
+
+ LLTransferChannelType mChannelType;
+ LLHost mHost;
+ LLPriQueueMap<LLTransferSource*> mTransferSources;
+
+ // The throttle that this source channel should use
+ S32 mThrottleID;
+};
+
+
+//
+// A channel receiving data from a source.
+//
+class LLTransferTargetChannel
+{
+public:
+ LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host);
+ virtual ~LLTransferTargetChannel();
+
+ void requestTransfer(const LLTransferSourceParams &source_params,
+ const LLTransferTargetParams &target_params,
+ const F32 priority);
+
+ LLTransferTarget *findTransferTarget(const LLUUID &transfer_id);
+ void deleteTransfer(LLTransferTarget *ttp);
+
+
+ LLTransferChannelType getChannelType() const { return mChannelType; }
+ LLHost getHost() const { return mHost; }
+
+protected:
+ void sendTransferRequest(LLTransferTarget *targetp,
+ const LLTransferSourceParams &params,
+ const F32 priority);
+
+ void addTransferTarget(LLTransferTarget *targetp);
+
+ friend class LLTransferTarget;
+ friend class LLTransferManager;
+protected:
+ typedef std::list<LLTransferTarget *>::iterator tt_iter;
+
+ LLTransferChannelType mChannelType;
+ LLHost mHost;
+ std::list<LLTransferTarget *> mTransferTargets;
+};
+
+
+class LLTransferSourceParams
+{
+public:
+ LLTransferSourceParams(const LLTransferSourceType type) : mType(type) { }
+ virtual ~LLTransferSourceParams();
+
+ virtual void packParams(LLDataPacker &dp) const = 0;
+ virtual bool unpackParams(LLDataPacker &dp) = 0;
+
+ LLTransferSourceType getType() const { return mType; }
+
+protected:
+ LLTransferSourceType mType;
+};
+
+
+//
+// LLTransferSource is an interface, all transfer sources should be derived from it.
+//
+typedef LLTransferSource *(*LLTransferSourceCreateFunc)(const LLUUID &id, const F32 priority);
+
+class LLTransferSource
+{
+public:
+
+ LLUUID getID() { return mID; }
+
+ friend class LLTransferManager;
+ friend class LLTransferSourceChannel;
+
+protected:
+ LLTransferSource(const LLTransferSourceType source_type,
+ const LLUUID &request_id,
+ const F32 priority);
+ virtual ~LLTransferSource();
+
+ void sendTransferStatus(LLTSCode status); // When you've figured out your transfer status, do this
+
+ virtual void initTransfer() = 0;
+ virtual F32 updatePriority() = 0;
+ virtual LLTSCode dataCallback(const S32 packet_id,
+ const S32 max_bytes,
+ U8 **datap,
+ S32 &returned_bytes,
+ bool &delete_returned) = 0;
+
+ // The completionCallback is GUARANTEED to be called before the destructor.
+ virtual void completionCallback(const LLTSCode status) = 0;
+
+ virtual void packParams(LLDataPacker& dp) const = 0;
+ virtual bool unpackParams(LLDataPacker& dp) = 0;
+
+ virtual S32 getNextPacketID() { return mLastPacketID + 1; }
+ virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; }
+
+
+ // For now, no self-induced priority changes
+ F32 getPriority() { return mPriority; }
+ void setPriority(const F32 pri) { mPriority = pri; }
+
+ virtual void abortTransfer(); // DON'T USE THIS ONE, used internally by LLTransferManager
+
+ static LLTransferSource *createSource(const LLTransferSourceType stype,
+ const LLUUID &request_id,
+ const F32 priority);
+ static void registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc);
+
+ static void sSetPriority(LLTransferSource *&tsp, const F32 priority);
+ static F32 sGetPriority(LLTransferSource *&tsp);
+protected:
+ typedef std::map<LLTransferSourceType, LLTransferSourceCreateFunc> stype_scfunc_map;
+ static stype_scfunc_map sSourceCreateMap;
+
+ LLTransferSourceType mType;
+ LLUUID mID;
+ LLTransferSourceChannel *mChannelp;
+ F32 mPriority;
+ S32 mSize;
+ S32 mLastPacketID;
+};
+
+
+class LLTransferTargetParams
+{
+public:
+ LLTransferTargetParams(const LLTransferTargetType type) : mType(type) {}
+ LLTransferTargetType getType() const { return mType; }
+protected:
+ LLTransferTargetType mType;
+};
+
+
+class LLTransferPacket
+{
+ // Used for storing a packet that's being delivered later because it's out of order.
+ // ONLY should be accessed by the following two classes, for now.
+ friend class LLTransferTarget;
+ friend class LLTransferManager;
+
+protected:
+
+ LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size);
+ virtual ~LLTransferPacket();
+
+protected:
+ S32 mPacketID;
+ LLTSCode mStatus;
+ U8 *mDatap;
+ S32 mSize;
+};
+
+
+class LLTransferTarget
+{
+public:
+ LLTransferTarget(
+ LLTransferTargetType target_type,
+ const LLUUID& transfer_id,
+ LLTransferSourceType source_type);
+ virtual ~LLTransferTarget();
+
+ // Accessors
+ LLUUID getID() const { return mID; }
+ LLTransferTargetType getType() const { return mType; }
+ LLTransferTargetChannel *getChannel() const { return mChannelp; }
+ LLTransferSourceType getSourceType() const { return mSourceType; }
+
+ // Static functionality
+ static LLTransferTarget* createTarget(
+ LLTransferTargetType target_type,
+ const LLUUID& request_id,
+ LLTransferSourceType source_type);
+
+ // friends
+ friend class LLTransferManager;
+ friend class LLTransferTargetChannel;
+
+protected:
+ // Implementation
+ virtual bool unpackParams(LLDataPacker& dp) = 0;
+ virtual void applyParams(const LLTransferTargetParams &params) = 0;
+ virtual LLTSCode dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size) = 0;
+
+ // The completionCallback is GUARANTEED to be called before the destructor, so all handling
+ // of errors/aborts should be done here.
+ virtual void completionCallback(const LLTSCode status) = 0;
+
+ void abortTransfer();
+
+ virtual S32 getNextPacketID() { return mLastPacketID + 1; }
+ virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; }
+ void setSize(const S32 size) { mSize = size; }
+ void setGotInfo(const bool got_info) { mGotInfo = got_info; }
+ bool gotInfo() const { return mGotInfo; }
+
+ bool addDelayedPacket(
+ const S32 packet_id,
+ const LLTSCode status,
+ U8* datap,
+ const S32 size);
+
+protected:
+ typedef std::map<S32, LLTransferPacket *> transfer_packet_map;
+ typedef std::map<S32, LLTransferPacket *>::iterator tpm_iter;
+
+ LLTransferTargetType mType;
+ LLTransferSourceType mSourceType;
+ LLUUID mID;
+ LLTransferTargetChannel *mChannelp;
+ bool mGotInfo;
+ S32 mSize;
+ S32 mLastPacketID;
+
+ transfer_packet_map mDelayedPacketMap; // Packets that are waiting because of missing/out of order issues
+};
+
+
+// Hack, here so it's publicly available even though LLTransferSourceInvItem is only available on the simulator
+class LLTransferSourceParamsInvItem: public LLTransferSourceParams
+{
+public:
+ LLTransferSourceParamsInvItem();
+ virtual ~LLTransferSourceParamsInvItem() {}
+ /*virtual*/ void packParams(LLDataPacker &dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+ void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id);
+ void setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id);
+ void setAsset(const LLUUID &asset_id, const LLAssetType::EType at);
+
+ LLUUID getAgentID() const { return mAgentID; }
+ LLUUID getSessionID() const { return mSessionID; }
+ LLUUID getOwnerID() const { return mOwnerID; }
+ LLUUID getTaskID() const { return mTaskID; }
+ LLUUID getItemID() const { return mItemID; }
+ LLUUID getAssetID() const { return mAssetID; }
+ LLAssetType::EType getAssetType() const { return mAssetType; }
+
+protected:
+ LLUUID mAgentID;
+ LLUUID mSessionID;
+ LLUUID mOwnerID;
+ LLUUID mTaskID;
+ LLUUID mItemID;
+ LLUUID mAssetID;
+ LLAssetType::EType mAssetType;
+};
+
+
+// Hack, here so it's publicly available even though LLTransferSourceEstate is only available on the simulator
+class LLTransferSourceParamsEstate: public LLTransferSourceParams
+{
+public:
+ LLTransferSourceParamsEstate();
+ virtual ~LLTransferSourceParamsEstate() {}
+ /*virtual*/ void packParams(LLDataPacker &dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+ void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id);
+ void setEstateAssetType(const EstateAssetType etype);
+ void setAsset(const LLUUID &asset_id, const LLAssetType::EType at);
+
+ LLUUID getAgentID() const { return mAgentID; }
+ LLUUID getSessionID() const { return mSessionID; }
+ EstateAssetType getEstateAssetType() const { return mEstateAssetType; }
+ LLUUID getAssetID() const { return mAssetID; }
+ LLAssetType::EType getAssetType() const { return mAssetType; }
+
+protected:
+ LLUUID mAgentID;
+ LLUUID mSessionID;
+ EstateAssetType mEstateAssetType;
+ // these are set on the sim based on estateinfotype
+ LLUUID mAssetID;
+ LLAssetType::EType mAssetType;
+};
+
+
+extern LLTransferManager gTransferManager;
+
+#endif//LL_LLTRANSFERMANAGER_H
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index 50956aeb6d..f09855aacd 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -1,254 +1,254 @@
-/**
- * @file lltransfersourceasset.cpp
- * @brief Transfer system for sending an asset.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltransfersourceasset.h"
-
-#include "llerror.h"
-#include "message.h"
-#include "lldatapacker.h"
-#include "lldir.h"
-#include "llfilesystem.h"
-
-LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) :
- LLTransferSource(LLTST_ASSET, request_id, priority),
- mGotResponse(false),
- mCurPos(0)
-{
-}
-
-LLTransferSourceAsset::~LLTransferSourceAsset()
-{
-}
-
-
-void LLTransferSourceAsset::initTransfer()
-{
- if (gAssetStorage)
- {
- // *HACK: asset transfers will only be coming from the viewer
- // to the simulator. This is subset of assets we allow to be
- // simply pulled straight from the asset system.
- LLUUID* tidp;
- if(LLAssetType::lookupIsAssetFetchByIDAllowed(mParams.getAssetType()))
- {
- tidp = new LLUUID(getID());
- gAssetStorage->getAssetData(
- mParams.getAssetID(),
- mParams.getAssetType(),
- LLTransferSourceAsset::responderCallback,
- tidp,
- false);
- }
- else
- {
- LL_WARNS() << "Attempted to request blocked asset "
- << mParams.getAssetID() << ":"
- << LLAssetType::lookupHumanReadable(mParams.getAssetType())
- << LL_ENDL;
- sendTransferStatus(LLTS_ERROR);
- }
- }
- else
- {
- LL_WARNS() << "Attempted to request asset " << mParams.getAssetID()
- << ":" << LLAssetType::lookupHumanReadable(mParams.getAssetType())
- << " without an asset system!" << LL_ENDL;
- sendTransferStatus(LLTS_ERROR);
- }
-}
-
-F32 LLTransferSourceAsset::updatePriority()
-{
- return 0.f;
-}
-
-LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id,
- const S32 max_bytes,
- U8 **data_handle,
- S32 &returned_bytes,
- bool &delete_returned)
-{
- //LL_INFOS() << "LLTransferSourceAsset::dataCallback" << LL_ENDL;
- if (!mGotResponse)
- {
- return LLTS_SKIP;
- }
-
- LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ);
-
- if (!vf.getSize())
- {
- // Something bad happened with the asset request!
- return LLTS_ERROR;
- }
-
- if (packet_id != mLastPacketID + 1)
- {
- LL_ERRS() << "Can't handle out of order file transfer yet!" << LL_ENDL;
- }
-
- // grab a buffer from the right place in the file
- if (!vf.seek(mCurPos, 0))
- {
- LL_WARNS() << "LLTransferSourceAsset Can't seek to " << mCurPos << " length " << vf.getSize() << LL_ENDL;
- LL_WARNS() << "While sending " << mParams.getAssetID() << LL_ENDL;
- return LLTS_ERROR;
- }
-
- delete_returned = true;
- U8 *tmpp = new U8[max_bytes];
- *data_handle = tmpp;
- if (!vf.read(tmpp, max_bytes)) /* Flawfinder: Ignore */
- {
- // Read failure, need to deal with it.
- delete[] tmpp;
- *data_handle = NULL;
- returned_bytes = 0;
- delete_returned = false;
- return LLTS_ERROR;
- }
-
- returned_bytes = vf.getLastBytesRead();
- mCurPos += returned_bytes;
-
-
- if (vf.eof())
- {
- if (!returned_bytes)
- {
- delete[] tmpp;
- *data_handle = NULL;
- returned_bytes = 0;
- delete_returned = false;
- }
- return LLTS_DONE;
- }
-
- return LLTS_OK;
-}
-
-void LLTransferSourceAsset::completionCallback(const LLTSCode status)
-{
- // No matter what happens, all we want to do is close the vfile if
- // we've got it open.
-}
-
-void LLTransferSourceAsset::packParams(LLDataPacker& dp) const
-{
- //LL_INFOS() << "LLTransferSourceAsset::packParams" << LL_ENDL;
- mParams.packParams(dp);
-}
-
-bool LLTransferSourceAsset::unpackParams(LLDataPacker &dp)
-{
- //LL_INFOS() << "LLTransferSourceAsset::unpackParams" << LL_ENDL;
- return mParams.unpackParams(dp);
-}
-
-
-void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::EType type,
- void *user_data, S32 result, LLExtStat ext_status )
-{
- LLUUID *tidp = ((LLUUID*) user_data);
- LLUUID transfer_id = *(tidp);
- delete tidp;
- tidp = NULL;
-
- LLTransferSourceAsset *tsap = (LLTransferSourceAsset *) gTransferManager.findTransferSource(transfer_id);
-
- if (!tsap)
- {
- LL_INFOS() << "Aborting transfer " << transfer_id << " callback, transfer source went away" << LL_ENDL;
- return;
- }
-
- if (result)
- {
- LL_INFOS() << "AssetStorage: Error " << gAssetStorage->getErrorString(result) << " downloading uuid " << uuid << LL_ENDL;
- }
-
- LLTSCode status;
-
- tsap->mGotResponse = true;
- if (LL_ERR_NOERR == result)
- {
- // Everything's OK.
- LLFileSystem vf(uuid, type, LLFileSystem::READ);
- tsap->mSize = vf.getSize();
- status = LLTS_OK;
- }
- else
- {
- // Uh oh, something bad happened when we tried to get this asset!
- switch (result)
- {
- case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
- status = LLTS_UNKNOWN_SOURCE;
- break;
- default:
- status = LLTS_ERROR;
- }
- }
-
- tsap->sendTransferStatus(status);
-}
-
-
-
-LLTransferSourceParamsAsset::LLTransferSourceParamsAsset()
- : LLTransferSourceParams(LLTST_ASSET),
-
- mAssetType(LLAssetType::AT_NONE)
-{
-}
-
-void LLTransferSourceParamsAsset::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
-{
- mAssetID = asset_id;
- mAssetType = asset_type;
-}
-
-void LLTransferSourceParamsAsset::packParams(LLDataPacker &dp) const
-{
- dp.packUUID(mAssetID, "AssetID");
- dp.packS32(mAssetType, "AssetType");
-}
-
-
-bool LLTransferSourceParamsAsset::unpackParams(LLDataPacker &dp)
-{
- S32 tmp_at;
-
- dp.unpackUUID(mAssetID, "AssetID");
- dp.unpackS32(tmp_at, "AssetType");
-
- mAssetType = (LLAssetType::EType)tmp_at;
-
- return true;
-}
-
+/**
+ * @file lltransfersourceasset.cpp
+ * @brief Transfer system for sending an asset.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltransfersourceasset.h"
+
+#include "llerror.h"
+#include "message.h"
+#include "lldatapacker.h"
+#include "lldir.h"
+#include "llfilesystem.h"
+
+LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) :
+ LLTransferSource(LLTST_ASSET, request_id, priority),
+ mGotResponse(false),
+ mCurPos(0)
+{
+}
+
+LLTransferSourceAsset::~LLTransferSourceAsset()
+{
+}
+
+
+void LLTransferSourceAsset::initTransfer()
+{
+ if (gAssetStorage)
+ {
+ // *HACK: asset transfers will only be coming from the viewer
+ // to the simulator. This is subset of assets we allow to be
+ // simply pulled straight from the asset system.
+ LLUUID* tidp;
+ if(LLAssetType::lookupIsAssetFetchByIDAllowed(mParams.getAssetType()))
+ {
+ tidp = new LLUUID(getID());
+ gAssetStorage->getAssetData(
+ mParams.getAssetID(),
+ mParams.getAssetType(),
+ LLTransferSourceAsset::responderCallback,
+ tidp,
+ false);
+ }
+ else
+ {
+ LL_WARNS() << "Attempted to request blocked asset "
+ << mParams.getAssetID() << ":"
+ << LLAssetType::lookupHumanReadable(mParams.getAssetType())
+ << LL_ENDL;
+ sendTransferStatus(LLTS_ERROR);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Attempted to request asset " << mParams.getAssetID()
+ << ":" << LLAssetType::lookupHumanReadable(mParams.getAssetType())
+ << " without an asset system!" << LL_ENDL;
+ sendTransferStatus(LLTS_ERROR);
+ }
+}
+
+F32 LLTransferSourceAsset::updatePriority()
+{
+ return 0.f;
+}
+
+LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id,
+ const S32 max_bytes,
+ U8 **data_handle,
+ S32 &returned_bytes,
+ bool &delete_returned)
+{
+ //LL_INFOS() << "LLTransferSourceAsset::dataCallback" << LL_ENDL;
+ if (!mGotResponse)
+ {
+ return LLTS_SKIP;
+ }
+
+ LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ);
+
+ if (!vf.getSize())
+ {
+ // Something bad happened with the asset request!
+ return LLTS_ERROR;
+ }
+
+ if (packet_id != mLastPacketID + 1)
+ {
+ LL_ERRS() << "Can't handle out of order file transfer yet!" << LL_ENDL;
+ }
+
+ // grab a buffer from the right place in the file
+ if (!vf.seek(mCurPos, 0))
+ {
+ LL_WARNS() << "LLTransferSourceAsset Can't seek to " << mCurPos << " length " << vf.getSize() << LL_ENDL;
+ LL_WARNS() << "While sending " << mParams.getAssetID() << LL_ENDL;
+ return LLTS_ERROR;
+ }
+
+ delete_returned = true;
+ U8 *tmpp = new U8[max_bytes];
+ *data_handle = tmpp;
+ if (!vf.read(tmpp, max_bytes)) /* Flawfinder: Ignore */
+ {
+ // Read failure, need to deal with it.
+ delete[] tmpp;
+ *data_handle = NULL;
+ returned_bytes = 0;
+ delete_returned = false;
+ return LLTS_ERROR;
+ }
+
+ returned_bytes = vf.getLastBytesRead();
+ mCurPos += returned_bytes;
+
+
+ if (vf.eof())
+ {
+ if (!returned_bytes)
+ {
+ delete[] tmpp;
+ *data_handle = NULL;
+ returned_bytes = 0;
+ delete_returned = false;
+ }
+ return LLTS_DONE;
+ }
+
+ return LLTS_OK;
+}
+
+void LLTransferSourceAsset::completionCallback(const LLTSCode status)
+{
+ // No matter what happens, all we want to do is close the vfile if
+ // we've got it open.
+}
+
+void LLTransferSourceAsset::packParams(LLDataPacker& dp) const
+{
+ //LL_INFOS() << "LLTransferSourceAsset::packParams" << LL_ENDL;
+ mParams.packParams(dp);
+}
+
+bool LLTransferSourceAsset::unpackParams(LLDataPacker &dp)
+{
+ //LL_INFOS() << "LLTransferSourceAsset::unpackParams" << LL_ENDL;
+ return mParams.unpackParams(dp);
+}
+
+
+void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::EType type,
+ void *user_data, S32 result, LLExtStat ext_status )
+{
+ LLUUID *tidp = ((LLUUID*) user_data);
+ LLUUID transfer_id = *(tidp);
+ delete tidp;
+ tidp = NULL;
+
+ LLTransferSourceAsset *tsap = (LLTransferSourceAsset *) gTransferManager.findTransferSource(transfer_id);
+
+ if (!tsap)
+ {
+ LL_INFOS() << "Aborting transfer " << transfer_id << " callback, transfer source went away" << LL_ENDL;
+ return;
+ }
+
+ if (result)
+ {
+ LL_INFOS() << "AssetStorage: Error " << gAssetStorage->getErrorString(result) << " downloading uuid " << uuid << LL_ENDL;
+ }
+
+ LLTSCode status;
+
+ tsap->mGotResponse = true;
+ if (LL_ERR_NOERR == result)
+ {
+ // Everything's OK.
+ LLFileSystem vf(uuid, type, LLFileSystem::READ);
+ tsap->mSize = vf.getSize();
+ status = LLTS_OK;
+ }
+ else
+ {
+ // Uh oh, something bad happened when we tried to get this asset!
+ switch (result)
+ {
+ case LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE:
+ status = LLTS_UNKNOWN_SOURCE;
+ break;
+ default:
+ status = LLTS_ERROR;
+ }
+ }
+
+ tsap->sendTransferStatus(status);
+}
+
+
+
+LLTransferSourceParamsAsset::LLTransferSourceParamsAsset()
+ : LLTransferSourceParams(LLTST_ASSET),
+
+ mAssetType(LLAssetType::AT_NONE)
+{
+}
+
+void LLTransferSourceParamsAsset::setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type)
+{
+ mAssetID = asset_id;
+ mAssetType = asset_type;
+}
+
+void LLTransferSourceParamsAsset::packParams(LLDataPacker &dp) const
+{
+ dp.packUUID(mAssetID, "AssetID");
+ dp.packS32(mAssetType, "AssetType");
+}
+
+
+bool LLTransferSourceParamsAsset::unpackParams(LLDataPacker &dp)
+{
+ S32 tmp_at;
+
+ dp.unpackUUID(mAssetID, "AssetID");
+ dp.unpackS32(tmp_at, "AssetType");
+
+ mAssetType = (LLAssetType::EType)tmp_at;
+
+ return true;
+}
+
diff --git a/indra/llmessage/lltransfersourceasset.h b/indra/llmessage/lltransfersourceasset.h
index f2a5dc214e..50755d65ad 100644
--- a/indra/llmessage/lltransfersourceasset.h
+++ b/indra/llmessage/lltransfersourceasset.h
@@ -1,81 +1,81 @@
-/**
- * @file lltransfersourceasset.h
- * @brief Transfer system for sending an asset.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTRANSFERSOURCEASSET_H
-#define LL_LLTRANSFERSOURCEASSET_H
-
-#include "lltransfermanager.h"
-#include "llassetstorage.h"
-
-class LLFileSystem;
-
-class LLTransferSourceParamsAsset : public LLTransferSourceParams
-{
-public:
- LLTransferSourceParamsAsset();
- virtual ~LLTransferSourceParamsAsset() {}
- /*virtual*/ void packParams(LLDataPacker &dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
- void setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type);
-
- LLUUID getAssetID() const { return mAssetID; }
- LLAssetType::EType getAssetType() const { return mAssetType; }
-
-protected:
- LLUUID mAssetID;
- LLAssetType::EType mAssetType;
-};
-
-class LLTransferSourceAsset : public LLTransferSource
-{
-public:
- LLTransferSourceAsset(const LLUUID &request_id, const F32 priority);
- virtual ~LLTransferSourceAsset();
-
- static void responderCallback(const LLUUID& uuid, LLAssetType::EType type,
- void *user_data, S32 result, LLExtStat ext_status );
-protected:
- /*virtual*/ void initTransfer();
- /*virtual*/ F32 updatePriority();
- /*virtual*/ LLTSCode dataCallback(const S32 packet_id,
- const S32 max_bytes,
- U8 **datap,
- S32 &returned_bytes,
- bool &delete_returned);
- /*virtual*/ void completionCallback(const LLTSCode status);
-
- virtual void packParams(LLDataPacker& dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
-protected:
- LLTransferSourceParamsAsset mParams;
- bool mGotResponse;
-
- S32 mCurPos;
-};
-
-#endif // LL_LLTRANSFERSOURCEASSET_H
+/**
+ * @file lltransfersourceasset.h
+ * @brief Transfer system for sending an asset.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRANSFERSOURCEASSET_H
+#define LL_LLTRANSFERSOURCEASSET_H
+
+#include "lltransfermanager.h"
+#include "llassetstorage.h"
+
+class LLFileSystem;
+
+class LLTransferSourceParamsAsset : public LLTransferSourceParams
+{
+public:
+ LLTransferSourceParamsAsset();
+ virtual ~LLTransferSourceParamsAsset() {}
+ /*virtual*/ void packParams(LLDataPacker &dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+ void setAsset(const LLUUID &asset_id, const LLAssetType::EType asset_type);
+
+ LLUUID getAssetID() const { return mAssetID; }
+ LLAssetType::EType getAssetType() const { return mAssetType; }
+
+protected:
+ LLUUID mAssetID;
+ LLAssetType::EType mAssetType;
+};
+
+class LLTransferSourceAsset : public LLTransferSource
+{
+public:
+ LLTransferSourceAsset(const LLUUID &request_id, const F32 priority);
+ virtual ~LLTransferSourceAsset();
+
+ static void responderCallback(const LLUUID& uuid, LLAssetType::EType type,
+ void *user_data, S32 result, LLExtStat ext_status );
+protected:
+ /*virtual*/ void initTransfer();
+ /*virtual*/ F32 updatePriority();
+ /*virtual*/ LLTSCode dataCallback(const S32 packet_id,
+ const S32 max_bytes,
+ U8 **datap,
+ S32 &returned_bytes,
+ bool &delete_returned);
+ /*virtual*/ void completionCallback(const LLTSCode status);
+
+ virtual void packParams(LLDataPacker& dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+protected:
+ LLTransferSourceParamsAsset mParams;
+ bool mGotResponse;
+
+ S32 mCurPos;
+};
+
+#endif // LL_LLTRANSFERSOURCEASSET_H
diff --git a/indra/llmessage/lltransfersourcefile.cpp b/indra/llmessage/lltransfersourcefile.cpp
index ccf0dd7fe0..97d5716ca4 100644
--- a/indra/llmessage/lltransfersourcefile.cpp
+++ b/indra/llmessage/lltransfersourcefile.cpp
@@ -1,174 +1,174 @@
-/**
- * @file lltransfersourcefile.cpp
- * @brief Transfer system for sending a file.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltransfersourcefile.h"
-
-#include "llerror.h"
-#include "message.h"
-#include "lldatapacker.h"
-#include "lldir.h"
-
-LLTransferSourceFile::LLTransferSourceFile(const LLUUID &request_id, const F32 priority) :
- LLTransferSource(LLTST_FILE, request_id, priority),
- mFP(NULL)
-{
-}
-
-LLTransferSourceFile::~LLTransferSourceFile()
-{
- if (mFP)
- {
- LL_ERRS() << "Destructor called without the completion callback being called!" << LL_ENDL;
- }
-}
-
-void LLTransferSourceFile::initTransfer()
-{
- std::string filename = mParams.getFilename();
- std::string delimiter = gDirUtilp->getDirDelimiter();
-
- if((filename == ".")
- || (filename == "..")
- || (filename.find(delimiter[0]) != std::string::npos))
- {
- LL_WARNS() << "Attempting to transfer file " << filename << " with path delimiter, aborting!" << LL_ENDL;
-
- sendTransferStatus(LLTS_ERROR);
- return;
- }
- // Look for the file.
- mFP = LLFile::fopen(mParams.getFilename(), "rb"); /* Flawfinder: ignore */
- if (!mFP)
- {
- sendTransferStatus(LLTS_ERROR);
- return;
- }
-
- // Get the size of the file using the hack from
- fseek(mFP,0,SEEK_END);
- mSize = ftell(mFP);
- fseek(mFP,0,SEEK_SET);
-
- sendTransferStatus(LLTS_OK);
-}
-
-F32 LLTransferSourceFile::updatePriority()
-{
- return 0.f;
-}
-
-LLTSCode LLTransferSourceFile::dataCallback(const S32 packet_id,
- const S32 max_bytes,
- U8 **data_handle,
- S32 &returned_bytes,
- bool &delete_returned)
-{
- //LL_INFOS() << "LLTransferSourceFile::dataCallback" << LL_ENDL;
-
- if (!mFP)
- {
- LL_ERRS() << "Data callback without file set!" << LL_ENDL;
- return LLTS_ERROR;
- }
-
- if (packet_id != mLastPacketID + 1)
- {
- LL_ERRS() << "Can't handle out of order file transfer yet!" << LL_ENDL;
- }
-
- // Grab up until the max number of bytes from the file.
- delete_returned = true;
- U8 *tmpp = new U8[max_bytes];
- *data_handle = tmpp;
- returned_bytes = (S32)fread(tmpp, 1, max_bytes, mFP);
- if (!returned_bytes)
- {
- delete[] tmpp;
- *data_handle = NULL;
- returned_bytes = 0;
- delete_returned = false;
- return LLTS_DONE;
- }
-
- return LLTS_OK;
-}
-
-void LLTransferSourceFile::completionCallback(const LLTSCode status)
-{
- // No matter what happens, all we want to do is close the file pointer if
- // we've got it open.
- if (mFP)
- {
- fclose(mFP);
- mFP = NULL;
-
- }
- // Delete the file iff the filename begins with "TEMP"
- if (mParams.getDeleteOnCompletion() && mParams.getFilename().substr(0, 4) == "TEMP")
- {
- LLFile::remove(mParams.getFilename());
- }
-}
-
-void LLTransferSourceFile::packParams(LLDataPacker& dp) const
-{
- //LL_INFOS() << "LLTransferSourceFile::packParams" << LL_ENDL;
- mParams.packParams(dp);
-}
-
-bool LLTransferSourceFile::unpackParams(LLDataPacker &dp)
-{
- //LL_INFOS() << "LLTransferSourceFile::unpackParams" << LL_ENDL;
- return mParams.unpackParams(dp);
-}
-
-
-LLTransferSourceParamsFile::LLTransferSourceParamsFile() :
- LLTransferSourceParams(LLTST_FILE),
- mDeleteOnCompletion(false)
-{
-}
-
-
-void LLTransferSourceParamsFile::packParams(LLDataPacker &dp) const
-{
- dp.packString(mFilename, "Filename");
- dp.packU8((U8)mDeleteOnCompletion, "Delete");
-}
-
-
-bool LLTransferSourceParamsFile::unpackParams(LLDataPacker &dp)
-{
- dp.unpackString(mFilename, "Filename");
- U8 delete_flag;
- dp.unpackU8(delete_flag, "Delete");
- mDeleteOnCompletion = delete_flag;
-
- LL_INFOS() << "Unpacked filename: " << mFilename << LL_ENDL;
- return true;
-}
+/**
+ * @file lltransfersourcefile.cpp
+ * @brief Transfer system for sending a file.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltransfersourcefile.h"
+
+#include "llerror.h"
+#include "message.h"
+#include "lldatapacker.h"
+#include "lldir.h"
+
+LLTransferSourceFile::LLTransferSourceFile(const LLUUID &request_id, const F32 priority) :
+ LLTransferSource(LLTST_FILE, request_id, priority),
+ mFP(NULL)
+{
+}
+
+LLTransferSourceFile::~LLTransferSourceFile()
+{
+ if (mFP)
+ {
+ LL_ERRS() << "Destructor called without the completion callback being called!" << LL_ENDL;
+ }
+}
+
+void LLTransferSourceFile::initTransfer()
+{
+ std::string filename = mParams.getFilename();
+ std::string delimiter = gDirUtilp->getDirDelimiter();
+
+ if((filename == ".")
+ || (filename == "..")
+ || (filename.find(delimiter[0]) != std::string::npos))
+ {
+ LL_WARNS() << "Attempting to transfer file " << filename << " with path delimiter, aborting!" << LL_ENDL;
+
+ sendTransferStatus(LLTS_ERROR);
+ return;
+ }
+ // Look for the file.
+ mFP = LLFile::fopen(mParams.getFilename(), "rb"); /* Flawfinder: ignore */
+ if (!mFP)
+ {
+ sendTransferStatus(LLTS_ERROR);
+ return;
+ }
+
+ // Get the size of the file using the hack from
+ fseek(mFP,0,SEEK_END);
+ mSize = ftell(mFP);
+ fseek(mFP,0,SEEK_SET);
+
+ sendTransferStatus(LLTS_OK);
+}
+
+F32 LLTransferSourceFile::updatePriority()
+{
+ return 0.f;
+}
+
+LLTSCode LLTransferSourceFile::dataCallback(const S32 packet_id,
+ const S32 max_bytes,
+ U8 **data_handle,
+ S32 &returned_bytes,
+ bool &delete_returned)
+{
+ //LL_INFOS() << "LLTransferSourceFile::dataCallback" << LL_ENDL;
+
+ if (!mFP)
+ {
+ LL_ERRS() << "Data callback without file set!" << LL_ENDL;
+ return LLTS_ERROR;
+ }
+
+ if (packet_id != mLastPacketID + 1)
+ {
+ LL_ERRS() << "Can't handle out of order file transfer yet!" << LL_ENDL;
+ }
+
+ // Grab up until the max number of bytes from the file.
+ delete_returned = true;
+ U8 *tmpp = new U8[max_bytes];
+ *data_handle = tmpp;
+ returned_bytes = (S32)fread(tmpp, 1, max_bytes, mFP);
+ if (!returned_bytes)
+ {
+ delete[] tmpp;
+ *data_handle = NULL;
+ returned_bytes = 0;
+ delete_returned = false;
+ return LLTS_DONE;
+ }
+
+ return LLTS_OK;
+}
+
+void LLTransferSourceFile::completionCallback(const LLTSCode status)
+{
+ // No matter what happens, all we want to do is close the file pointer if
+ // we've got it open.
+ if (mFP)
+ {
+ fclose(mFP);
+ mFP = NULL;
+
+ }
+ // Delete the file iff the filename begins with "TEMP"
+ if (mParams.getDeleteOnCompletion() && mParams.getFilename().substr(0, 4) == "TEMP")
+ {
+ LLFile::remove(mParams.getFilename());
+ }
+}
+
+void LLTransferSourceFile::packParams(LLDataPacker& dp) const
+{
+ //LL_INFOS() << "LLTransferSourceFile::packParams" << LL_ENDL;
+ mParams.packParams(dp);
+}
+
+bool LLTransferSourceFile::unpackParams(LLDataPacker &dp)
+{
+ //LL_INFOS() << "LLTransferSourceFile::unpackParams" << LL_ENDL;
+ return mParams.unpackParams(dp);
+}
+
+
+LLTransferSourceParamsFile::LLTransferSourceParamsFile() :
+ LLTransferSourceParams(LLTST_FILE),
+ mDeleteOnCompletion(false)
+{
+}
+
+
+void LLTransferSourceParamsFile::packParams(LLDataPacker &dp) const
+{
+ dp.packString(mFilename, "Filename");
+ dp.packU8((U8)mDeleteOnCompletion, "Delete");
+}
+
+
+bool LLTransferSourceParamsFile::unpackParams(LLDataPacker &dp)
+{
+ dp.unpackString(mFilename, "Filename");
+ U8 delete_flag;
+ dp.unpackU8(delete_flag, "Delete");
+ mDeleteOnCompletion = delete_flag;
+
+ LL_INFOS() << "Unpacked filename: " << mFilename << LL_ENDL;
+ return true;
+}
diff --git a/indra/llmessage/lltransfersourcefile.h b/indra/llmessage/lltransfersourcefile.h
index 60100e5a65..3b9cd7231c 100644
--- a/indra/llmessage/lltransfersourcefile.h
+++ b/indra/llmessage/lltransfersourcefile.h
@@ -1,75 +1,75 @@
-/**
- * @file lltransfersourcefile.h
- * @brief Transfer system for sending a file.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTRANSFERSOURCEFILE_H
-#define LL_LLTRANSFERSOURCEFILE_H
-
-#include "lltransfermanager.h"
-
-class LLTransferSourceParamsFile : public LLTransferSourceParams
-{
-public:
- LLTransferSourceParamsFile();
- virtual ~LLTransferSourceParamsFile() {}
- /*virtual*/ void packParams(LLDataPacker &dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
- void setFilename(const std::string &filename) { mFilename = filename; }
- std::string getFilename() const { return mFilename; }
-
- void setDeleteOnCompletion(bool enabled) { mDeleteOnCompletion = enabled; }
- bool getDeleteOnCompletion() { return mDeleteOnCompletion; }
-protected:
- std::string mFilename;
- // ONLY DELETE THINGS OFF THE SIM IF THE FILENAME BEGINS IN 'TEMP'
- bool mDeleteOnCompletion;
-};
-
-class LLTransferSourceFile : public LLTransferSource
-{
-public:
- LLTransferSourceFile(const LLUUID &transfer_id, const F32 priority);
- virtual ~LLTransferSourceFile();
-
-protected:
- /*virtual*/ void initTransfer();
- /*virtual*/ F32 updatePriority();
- /*virtual*/ LLTSCode dataCallback(const S32 packet_id,
- const S32 max_bytes,
- U8 **datap,
- S32 &returned_bytes,
- bool &delete_returned);
- /*virtual*/ void completionCallback(const LLTSCode status);
-
- virtual void packParams(LLDataPacker& dp) const;
- /*virtual*/ bool unpackParams(LLDataPacker &dp);
-
-protected:
- LLTransferSourceParamsFile mParams;
- LLFILE *mFP;
-};
-
-#endif // LL_LLTRANSFERSOURCEFILE_H
+/**
+ * @file lltransfersourcefile.h
+ * @brief Transfer system for sending a file.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRANSFERSOURCEFILE_H
+#define LL_LLTRANSFERSOURCEFILE_H
+
+#include "lltransfermanager.h"
+
+class LLTransferSourceParamsFile : public LLTransferSourceParams
+{
+public:
+ LLTransferSourceParamsFile();
+ virtual ~LLTransferSourceParamsFile() {}
+ /*virtual*/ void packParams(LLDataPacker &dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+ void setFilename(const std::string &filename) { mFilename = filename; }
+ std::string getFilename() const { return mFilename; }
+
+ void setDeleteOnCompletion(bool enabled) { mDeleteOnCompletion = enabled; }
+ bool getDeleteOnCompletion() { return mDeleteOnCompletion; }
+protected:
+ std::string mFilename;
+ // ONLY DELETE THINGS OFF THE SIM IF THE FILENAME BEGINS IN 'TEMP'
+ bool mDeleteOnCompletion;
+};
+
+class LLTransferSourceFile : public LLTransferSource
+{
+public:
+ LLTransferSourceFile(const LLUUID &transfer_id, const F32 priority);
+ virtual ~LLTransferSourceFile();
+
+protected:
+ /*virtual*/ void initTransfer();
+ /*virtual*/ F32 updatePriority();
+ /*virtual*/ LLTSCode dataCallback(const S32 packet_id,
+ const S32 max_bytes,
+ U8 **datap,
+ S32 &returned_bytes,
+ bool &delete_returned);
+ /*virtual*/ void completionCallback(const LLTSCode status);
+
+ virtual void packParams(LLDataPacker& dp) const;
+ /*virtual*/ bool unpackParams(LLDataPacker &dp);
+
+protected:
+ LLTransferSourceParamsFile mParams;
+ LLFILE *mFP;
+};
+
+#endif // LL_LLTRANSFERSOURCEFILE_H
diff --git a/indra/llmessage/lltransfertargetfile.cpp b/indra/llmessage/lltransfertargetfile.cpp
index ca0318a2d6..6d8b69fa6f 100644
--- a/indra/llmessage/lltransfertargetfile.cpp
+++ b/indra/llmessage/lltransfertargetfile.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltransfertargetfile.cpp
* @brief Transfer system for receiving a file.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,99 +33,99 @@
LLTransferTargetFile::LLTransferTargetFile(
- const LLUUID& uuid,
- LLTransferSourceType src_type) :
- LLTransferTarget(LLTTT_FILE, uuid, src_type),
- mFP(NULL)
+ const LLUUID& uuid,
+ LLTransferSourceType src_type) :
+ LLTransferTarget(LLTTT_FILE, uuid, src_type),
+ mFP(NULL)
{
}
LLTransferTargetFile::~LLTransferTargetFile()
{
- if (mFP)
- {
- LL_ERRS() << "LLTransferTargetFile::~LLTransferTargetFile - Should have been cleaned up in completion callback" << LL_ENDL;
- fclose(mFP);
- mFP = NULL;
- }
+ if (mFP)
+ {
+ LL_ERRS() << "LLTransferTargetFile::~LLTransferTargetFile - Should have been cleaned up in completion callback" << LL_ENDL;
+ fclose(mFP);
+ mFP = NULL;
+ }
}
// virtual
bool LLTransferTargetFile::unpackParams(LLDataPacker& dp)
{
- // we can safely ignore this call
- return true;
+ // we can safely ignore this call
+ return true;
}
void LLTransferTargetFile::applyParams(const LLTransferTargetParams &params)
{
- if (params.getType() != mType)
- {
- LL_WARNS() << "Target parameter type doesn't match!" << LL_ENDL;
- return;
- }
-
- mParams = (LLTransferTargetParamsFile &)params;
+ if (params.getType() != mType)
+ {
+ LL_WARNS() << "Target parameter type doesn't match!" << LL_ENDL;
+ return;
+ }
+
+ mParams = (LLTransferTargetParamsFile &)params;
}
LLTSCode LLTransferTargetFile::dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size)
{
- //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL;
- //LL_INFOS() << "Packet: " << packet_id << LL_ENDL;
-
- if (!mFP)
- {
- mFP = LLFile::fopen(mParams.mFilename, "wb"); /* Flawfinder: ignore */
-
- if (!mFP)
- {
- LL_WARNS() << "Failure opening " << mParams.mFilename << " for write by LLTransferTargetFile" << LL_ENDL;
- return LLTS_ERROR;
- }
- }
- if (!in_size)
- {
- return LLTS_OK;
- }
-
- S32 count = (S32)fwrite(in_datap, 1, in_size, mFP);
- if (count != in_size)
- {
- LL_WARNS() << "Failure in LLTransferTargetFile::dataCallback!" << LL_ENDL;
- return LLTS_ERROR;
- }
- return LLTS_OK;
+ //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL;
+ //LL_INFOS() << "Packet: " << packet_id << LL_ENDL;
+
+ if (!mFP)
+ {
+ mFP = LLFile::fopen(mParams.mFilename, "wb"); /* Flawfinder: ignore */
+
+ if (!mFP)
+ {
+ LL_WARNS() << "Failure opening " << mParams.mFilename << " for write by LLTransferTargetFile" << LL_ENDL;
+ return LLTS_ERROR;
+ }
+ }
+ if (!in_size)
+ {
+ return LLTS_OK;
+ }
+
+ S32 count = (S32)fwrite(in_datap, 1, in_size, mFP);
+ if (count != in_size)
+ {
+ LL_WARNS() << "Failure in LLTransferTargetFile::dataCallback!" << LL_ENDL;
+ return LLTS_ERROR;
+ }
+ return LLTS_OK;
}
void LLTransferTargetFile::completionCallback(const LLTSCode status)
{
- LL_INFOS() << "LLTransferTargetFile::completionCallback" << LL_ENDL;
- if (mFP)
- {
- fclose(mFP);
- }
-
- // Still need to gracefully handle error conditions.
- switch (status)
- {
- case LLTS_DONE:
- break;
- case LLTS_ABORT:
- case LLTS_ERROR:
- // We're aborting this transfer, we don't want to keep this file.
- LL_WARNS() << "Aborting file transfer for " << mParams.mFilename << LL_ENDL;
- if (mFP)
- {
- // Only need to remove file if we successfully opened it.
- LLFile::remove(mParams.mFilename);
- }
- default:
- break;
- }
-
- mFP = NULL;
- if (mParams.mCompleteCallback)
- {
- mParams.mCompleteCallback(status, mParams.mUserData);
- }
+ LL_INFOS() << "LLTransferTargetFile::completionCallback" << LL_ENDL;
+ if (mFP)
+ {
+ fclose(mFP);
+ }
+
+ // Still need to gracefully handle error conditions.
+ switch (status)
+ {
+ case LLTS_DONE:
+ break;
+ case LLTS_ABORT:
+ case LLTS_ERROR:
+ // We're aborting this transfer, we don't want to keep this file.
+ LL_WARNS() << "Aborting file transfer for " << mParams.mFilename << LL_ENDL;
+ if (mFP)
+ {
+ // Only need to remove file if we successfully opened it.
+ LLFile::remove(mParams.mFilename);
+ }
+ default:
+ break;
+ }
+
+ mFP = NULL;
+ if (mParams.mCompleteCallback)
+ {
+ mParams.mCompleteCallback(status, mParams.mUserData);
+ }
}
diff --git a/indra/llmessage/lltransfertargetfile.h b/indra/llmessage/lltransfertargetfile.h
index 6d03ff2d2e..43189eb388 100644
--- a/indra/llmessage/lltransfertargetfile.h
+++ b/indra/llmessage/lltransfertargetfile.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltransfertargetfile.h
* @brief Transfer system for receiving a file.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,42 +34,42 @@ typedef void (*LLTTFCompleteCallback)(const LLTSCode status, void *user_data);
class LLTransferTargetParamsFile : public LLTransferTargetParams
{
public:
- LLTransferTargetParamsFile()
- : LLTransferTargetParams(LLTTT_FILE),
+ LLTransferTargetParamsFile()
+ : LLTransferTargetParams(LLTTT_FILE),
- mCompleteCallback(NULL),
- mUserData(NULL)
- {}
- void setFilename(const std::string& filename) { mFilename = filename; }
- void setCallback(LLTTFCompleteCallback cb, void *user_data) { mCompleteCallback = cb; mUserData = user_data; }
+ mCompleteCallback(NULL),
+ mUserData(NULL)
+ {}
+ void setFilename(const std::string& filename) { mFilename = filename; }
+ void setCallback(LLTTFCompleteCallback cb, void *user_data) { mCompleteCallback = cb; mUserData = user_data; }
- friend class LLTransferTargetFile;
+ friend class LLTransferTargetFile;
protected:
- std::string mFilename;
- LLTTFCompleteCallback mCompleteCallback;
- void * mUserData;
+ std::string mFilename;
+ LLTTFCompleteCallback mCompleteCallback;
+ void * mUserData;
};
class LLTransferTargetFile : public LLTransferTarget
{
public:
- LLTransferTargetFile(const LLUUID& uuid, LLTransferSourceType src_type);
- virtual ~LLTransferTargetFile();
+ LLTransferTargetFile(const LLUUID& uuid, LLTransferSourceType src_type);
+ virtual ~LLTransferTargetFile();
- static void requestTransfer(LLTransferTargetChannel *channelp,
- const char *local_filename,
- const LLTransferSourceParams &source_params,
- LLTTFCompleteCallback callback);
+ static void requestTransfer(LLTransferTargetChannel *channelp,
+ const char *local_filename,
+ const LLTransferSourceParams &source_params,
+ LLTTFCompleteCallback callback);
protected:
- virtual bool unpackParams(LLDataPacker& dp);
- /*virtual*/ void applyParams(const LLTransferTargetParams &params);
- /*virtual*/ LLTSCode dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size);
- /*virtual*/ void completionCallback(const LLTSCode status);
+ virtual bool unpackParams(LLDataPacker& dp);
+ /*virtual*/ void applyParams(const LLTransferTargetParams &params);
+ /*virtual*/ LLTSCode dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size);
+ /*virtual*/ void completionCallback(const LLTSCode status);
- LLTransferTargetParamsFile mParams;
+ LLTransferTargetParamsFile mParams;
- LLFILE *mFP;
+ LLFILE *mFP;
};
#endif // LL_LLTRANSFERTARGETFILE_H
diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp
index 2806e08ebd..dbf377bfa2 100644
--- a/indra/llmessage/lltransfertargetvfile.cpp
+++ b/indra/llmessage/lltransfertargetvfile.cpp
@@ -1,234 +1,234 @@
-/**
- * @file lltransfertargetvfile.cpp
- * @brief Transfer system for receiving a vfile.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltransfertargetvfile.h"
-
-#include "lldatapacker.h"
-#include "llerror.h"
-#include "llfilesystem.h"
-
-//static
-void LLTransferTargetVFile::updateQueue(bool shutdown)
-{
-}
-
-
-LLTransferTargetParamsVFile::LLTransferTargetParamsVFile() :
- LLTransferTargetParams(LLTTT_VFILE),
- mAssetType(LLAssetType::AT_NONE),
- mCompleteCallback(NULL),
- mRequestDatap(NULL),
- mErrCode(0)
-{
-}
-
-void LLTransferTargetParamsVFile::setAsset(
- const LLUUID& asset_id,
- LLAssetType::EType asset_type)
-{
- mAssetID = asset_id;
- mAssetType = asset_type;
-}
-
-void LLTransferTargetParamsVFile::setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request)
-{
- mCompleteCallback = cb;
- if (mRequestDatap)
- {
- delete mRequestDatap;
- }
- mRequestDatap = request.getCopy();
-}
-
-bool LLTransferTargetParamsVFile::unpackParams(LLDataPacker& dp)
-{
- // if the source provided a new key, assign that to the asset id.
- if(dp.hasNext())
- {
- LLUUID dummy_id;
- dp.unpackUUID(dummy_id, "AgentID");
- dp.unpackUUID(dummy_id, "SessionID");
- dp.unpackUUID(dummy_id, "OwnerID");
- dp.unpackUUID(dummy_id, "TaskID");
- dp.unpackUUID(dummy_id, "ItemID");
- dp.unpackUUID(mAssetID, "AssetID");
- S32 dummy_type;
- dp.unpackS32(dummy_type, "AssetType");
- }
-
- // if we never got an asset id, this will always fail.
- if(mAssetID.isNull())
- {
- return false;
- }
- return true;
-}
-
-
-LLTransferTargetVFile::LLTransferTargetVFile(
- const LLUUID& uuid,
- LLTransferSourceType src_type) :
- LLTransferTarget(LLTTT_VFILE, uuid, src_type),
- mNeedsCreate(true)
-{
- mTempID.generate();
-}
-
-
-LLTransferTargetVFile::~LLTransferTargetVFile()
-{
- if (mParams.mRequestDatap)
- {
- // TODO: Consider doing it in LLTransferTargetParamsVFile's destructor
- delete mParams.mRequestDatap;
- mParams.mRequestDatap = NULL;
- }
-}
-
-
-// virtual
-bool LLTransferTargetVFile::unpackParams(LLDataPacker& dp)
-{
- if(LLTST_SIM_INV_ITEM == mSourceType)
- {
- return mParams.unpackParams(dp);
- }
- return true;
-}
-
-void LLTransferTargetVFile::applyParams(const LLTransferTargetParams &params)
-{
- if (params.getType() != mType)
- {
- LL_WARNS() << "Target parameter type doesn't match!" << LL_ENDL;
- return;
- }
-
- mParams = (LLTransferTargetParamsVFile &)params;
-}
-
-
-LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size)
-{
- //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL;
- //LL_INFOS() << "Packet: " << packet_id << LL_ENDL;
-
- LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
- if (mNeedsCreate)
- {
- mNeedsCreate = false;
- }
-
- if (!in_size)
- {
- return LLTS_OK;
- }
-
- if (!vf.write(in_datap, in_size))
- {
- LL_WARNS() << "Failure in LLTransferTargetVFile::dataCallback!" << LL_ENDL;
- return LLTS_ERROR;
- }
- return LLTS_OK;
-}
-
-
-void LLTransferTargetVFile::completionCallback(const LLTSCode status)
-{
- //LL_INFOS() << "LLTransferTargetVFile::completionCallback" << LL_ENDL;
-
- if (!gAssetStorage)
- {
- LL_WARNS() << "Aborting vfile transfer after asset storage shut down!" << LL_ENDL;
- return;
- }
-
- // Still need to gracefully handle error conditions.
- S32 err_code = 0;
- switch (status)
- {
- case LLTS_DONE:
- if (!mNeedsCreate)
- {
- LLFileSystem file(mTempID, mParams.getAssetType(), LLFileSystem::WRITE);
- if (!file.rename(mParams.getAssetID(), mParams.getAssetType()))
- {
- LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL;
- }
- }
- err_code = LL_ERR_NOERR;
- LL_DEBUGS() << "LLTransferTargetVFile::completionCallback for "
- << mParams.getAssetID() << ","
- << LLAssetType::lookup(mParams.getAssetType())
- << " with temp id " << mTempID << LL_ENDL;
- break;
- case LLTS_ERROR:
- case LLTS_ABORT:
- case LLTS_UNKNOWN_SOURCE:
- default:
- {
- // We're aborting this transfer, we don't want to keep this file.
- LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL;
- LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
- vf.remove();
- }
- break;
- }
-
- switch (status)
- {
- case LLTS_DONE:
- err_code = LL_ERR_NOERR;
- break;
- case LLTS_UNKNOWN_SOURCE:
- err_code = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
- break;
- case LLTS_INSUFFICIENT_PERMISSIONS:
- err_code = LL_ERR_INSUFFICIENT_PERMISSIONS;
- break;
- case LLTS_ERROR:
- case LLTS_ABORT:
- default:
- err_code = LL_ERR_ASSET_REQUEST_FAILED;
- break;
- }
-
- if (mParams.mRequestDatap)
- {
- if (mParams.mCompleteCallback)
- {
- mParams.mCompleteCallback(err_code,
- mParams.getAssetID(),
- mParams.getAssetType(),
- mParams.mRequestDatap,
- LLExtStat::NONE);
- }
- delete mParams.mRequestDatap;
- mParams.mRequestDatap = NULL;
- }
-}
+/**
+ * @file lltransfertargetvfile.cpp
+ * @brief Transfer system for receiving a vfile.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltransfertargetvfile.h"
+
+#include "lldatapacker.h"
+#include "llerror.h"
+#include "llfilesystem.h"
+
+//static
+void LLTransferTargetVFile::updateQueue(bool shutdown)
+{
+}
+
+
+LLTransferTargetParamsVFile::LLTransferTargetParamsVFile() :
+ LLTransferTargetParams(LLTTT_VFILE),
+ mAssetType(LLAssetType::AT_NONE),
+ mCompleteCallback(NULL),
+ mRequestDatap(NULL),
+ mErrCode(0)
+{
+}
+
+void LLTransferTargetParamsVFile::setAsset(
+ const LLUUID& asset_id,
+ LLAssetType::EType asset_type)
+{
+ mAssetID = asset_id;
+ mAssetType = asset_type;
+}
+
+void LLTransferTargetParamsVFile::setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request)
+{
+ mCompleteCallback = cb;
+ if (mRequestDatap)
+ {
+ delete mRequestDatap;
+ }
+ mRequestDatap = request.getCopy();
+}
+
+bool LLTransferTargetParamsVFile::unpackParams(LLDataPacker& dp)
+{
+ // if the source provided a new key, assign that to the asset id.
+ if(dp.hasNext())
+ {
+ LLUUID dummy_id;
+ dp.unpackUUID(dummy_id, "AgentID");
+ dp.unpackUUID(dummy_id, "SessionID");
+ dp.unpackUUID(dummy_id, "OwnerID");
+ dp.unpackUUID(dummy_id, "TaskID");
+ dp.unpackUUID(dummy_id, "ItemID");
+ dp.unpackUUID(mAssetID, "AssetID");
+ S32 dummy_type;
+ dp.unpackS32(dummy_type, "AssetType");
+ }
+
+ // if we never got an asset id, this will always fail.
+ if(mAssetID.isNull())
+ {
+ return false;
+ }
+ return true;
+}
+
+
+LLTransferTargetVFile::LLTransferTargetVFile(
+ const LLUUID& uuid,
+ LLTransferSourceType src_type) :
+ LLTransferTarget(LLTTT_VFILE, uuid, src_type),
+ mNeedsCreate(true)
+{
+ mTempID.generate();
+}
+
+
+LLTransferTargetVFile::~LLTransferTargetVFile()
+{
+ if (mParams.mRequestDatap)
+ {
+ // TODO: Consider doing it in LLTransferTargetParamsVFile's destructor
+ delete mParams.mRequestDatap;
+ mParams.mRequestDatap = NULL;
+ }
+}
+
+
+// virtual
+bool LLTransferTargetVFile::unpackParams(LLDataPacker& dp)
+{
+ if(LLTST_SIM_INV_ITEM == mSourceType)
+ {
+ return mParams.unpackParams(dp);
+ }
+ return true;
+}
+
+void LLTransferTargetVFile::applyParams(const LLTransferTargetParams &params)
+{
+ if (params.getType() != mType)
+ {
+ LL_WARNS() << "Target parameter type doesn't match!" << LL_ENDL;
+ return;
+ }
+
+ mParams = (LLTransferTargetParamsVFile &)params;
+}
+
+
+LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size)
+{
+ //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL;
+ //LL_INFOS() << "Packet: " << packet_id << LL_ENDL;
+
+ LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
+ if (mNeedsCreate)
+ {
+ mNeedsCreate = false;
+ }
+
+ if (!in_size)
+ {
+ return LLTS_OK;
+ }
+
+ if (!vf.write(in_datap, in_size))
+ {
+ LL_WARNS() << "Failure in LLTransferTargetVFile::dataCallback!" << LL_ENDL;
+ return LLTS_ERROR;
+ }
+ return LLTS_OK;
+}
+
+
+void LLTransferTargetVFile::completionCallback(const LLTSCode status)
+{
+ //LL_INFOS() << "LLTransferTargetVFile::completionCallback" << LL_ENDL;
+
+ if (!gAssetStorage)
+ {
+ LL_WARNS() << "Aborting vfile transfer after asset storage shut down!" << LL_ENDL;
+ return;
+ }
+
+ // Still need to gracefully handle error conditions.
+ S32 err_code = 0;
+ switch (status)
+ {
+ case LLTS_DONE:
+ if (!mNeedsCreate)
+ {
+ LLFileSystem file(mTempID, mParams.getAssetType(), LLFileSystem::WRITE);
+ if (!file.rename(mParams.getAssetID(), mParams.getAssetType()))
+ {
+ LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL;
+ }
+ }
+ err_code = LL_ERR_NOERR;
+ LL_DEBUGS() << "LLTransferTargetVFile::completionCallback for "
+ << mParams.getAssetID() << ","
+ << LLAssetType::lookup(mParams.getAssetType())
+ << " with temp id " << mTempID << LL_ENDL;
+ break;
+ case LLTS_ERROR:
+ case LLTS_ABORT:
+ case LLTS_UNKNOWN_SOURCE:
+ default:
+ {
+ // We're aborting this transfer, we don't want to keep this file.
+ LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL;
+ LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
+ vf.remove();
+ }
+ break;
+ }
+
+ switch (status)
+ {
+ case LLTS_DONE:
+ err_code = LL_ERR_NOERR;
+ break;
+ case LLTS_UNKNOWN_SOURCE:
+ err_code = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
+ break;
+ case LLTS_INSUFFICIENT_PERMISSIONS:
+ err_code = LL_ERR_INSUFFICIENT_PERMISSIONS;
+ break;
+ case LLTS_ERROR:
+ case LLTS_ABORT:
+ default:
+ err_code = LL_ERR_ASSET_REQUEST_FAILED;
+ break;
+ }
+
+ if (mParams.mRequestDatap)
+ {
+ if (mParams.mCompleteCallback)
+ {
+ mParams.mCompleteCallback(err_code,
+ mParams.getAssetID(),
+ mParams.getAssetType(),
+ mParams.mRequestDatap,
+ LLExtStat::NONE);
+ }
+ delete mParams.mRequestDatap;
+ mParams.mRequestDatap = NULL;
+ }
+}
diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h
index 2e6e5a8d40..e1d48ce73d 100644
--- a/indra/llmessage/lltransfertargetvfile.h
+++ b/indra/llmessage/lltransfertargetvfile.h
@@ -1,93 +1,93 @@
-/**
- * @file lltransfertargetvfile.h
- * @brief Transfer system for receiving a vfile.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTRANSFERTARGETVFILE_H
-#define LL_LLTRANSFERTARGETVFILE_H
-
-#include "lltransfermanager.h"
-#include "llassetstorage.h"
-#include "llfilesystem.h"
-
-class LLFileSystem;
-
-// Lame, an S32 for now until I figure out the deal with how we want to do
-// error codes.
-typedef void (*LLTTVFCompleteCallback)(
- S32 status,
- const LLUUID& file_id,
- LLAssetType::EType file_type,
- LLBaseDownloadRequest* user_data, LLExtStat ext_status );
-
-class LLTransferTargetParamsVFile : public LLTransferTargetParams
-{
-public:
- LLTransferTargetParamsVFile();
-
- void setAsset(const LLUUID& asset_id, LLAssetType::EType asset_type);
- void setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request);
-
- LLUUID getAssetID() const { return mAssetID; }
- LLAssetType::EType getAssetType() const { return mAssetType; }
-
- friend class LLTransferTargetVFile;
-protected:
- bool unpackParams(LLDataPacker& dp);
-
- LLUUID mAssetID;
- LLAssetType::EType mAssetType;
-
- LLTTVFCompleteCallback mCompleteCallback;
- LLBaseDownloadRequest* mRequestDatap;
- S32 mErrCode;
-};
-
-
-class LLTransferTargetVFile : public LLTransferTarget
-{
-public:
- LLTransferTargetVFile(const LLUUID& uuid, LLTransferSourceType src_type);
- virtual ~LLTransferTargetVFile();
-
- //static void requestTransfer(LLTransferTargetChannel* channelp,
- // const char* local_filename,
- // const LLTransferSourceParams& source_params,
- // LLTTVFCompleteCallback callback);
-
- static void updateQueue(bool shutdown = false);
-
-protected:
- virtual bool unpackParams(LLDataPacker& dp);
- /*virtual*/ void applyParams(const LLTransferTargetParams& params);
- /*virtual*/ LLTSCode dataCallback(const S32 packet_id, U8* in_datap, const S32 in_size);
- /*virtual*/ void completionCallback(const LLTSCode status);
-
- LLTransferTargetParamsVFile mParams;
-
- bool mNeedsCreate;
- LLUUID mTempID;
-};
-
-#endif // LL_LLTRANSFERTARGETFILE_H
+/**
+ * @file lltransfertargetvfile.h
+ * @brief Transfer system for receiving a vfile.
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRANSFERTARGETVFILE_H
+#define LL_LLTRANSFERTARGETVFILE_H
+
+#include "lltransfermanager.h"
+#include "llassetstorage.h"
+#include "llfilesystem.h"
+
+class LLFileSystem;
+
+// Lame, an S32 for now until I figure out the deal with how we want to do
+// error codes.
+typedef void (*LLTTVFCompleteCallback)(
+ S32 status,
+ const LLUUID& file_id,
+ LLAssetType::EType file_type,
+ LLBaseDownloadRequest* user_data, LLExtStat ext_status );
+
+class LLTransferTargetParamsVFile : public LLTransferTargetParams
+{
+public:
+ LLTransferTargetParamsVFile();
+
+ void setAsset(const LLUUID& asset_id, LLAssetType::EType asset_type);
+ void setCallback(LLTTVFCompleteCallback cb, LLBaseDownloadRequest& request);
+
+ LLUUID getAssetID() const { return mAssetID; }
+ LLAssetType::EType getAssetType() const { return mAssetType; }
+
+ friend class LLTransferTargetVFile;
+protected:
+ bool unpackParams(LLDataPacker& dp);
+
+ LLUUID mAssetID;
+ LLAssetType::EType mAssetType;
+
+ LLTTVFCompleteCallback mCompleteCallback;
+ LLBaseDownloadRequest* mRequestDatap;
+ S32 mErrCode;
+};
+
+
+class LLTransferTargetVFile : public LLTransferTarget
+{
+public:
+ LLTransferTargetVFile(const LLUUID& uuid, LLTransferSourceType src_type);
+ virtual ~LLTransferTargetVFile();
+
+ //static void requestTransfer(LLTransferTargetChannel* channelp,
+ // const char* local_filename,
+ // const LLTransferSourceParams& source_params,
+ // LLTTVFCompleteCallback callback);
+
+ static void updateQueue(bool shutdown = false);
+
+protected:
+ virtual bool unpackParams(LLDataPacker& dp);
+ /*virtual*/ void applyParams(const LLTransferTargetParams& params);
+ /*virtual*/ LLTSCode dataCallback(const S32 packet_id, U8* in_datap, const S32 in_size);
+ /*virtual*/ void completionCallback(const LLTSCode status);
+
+ LLTransferTargetParamsVFile mParams;
+
+ bool mNeedsCreate;
+ LLUUID mTempID;
+};
+
+#endif // LL_LLTRANSFERTARGETFILE_H
diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp
index 33944f7883..4591a49dce 100644
--- a/indra/llmessage/lltrustedmessageservice.cpp
+++ b/indra/llmessage/lltrustedmessageservice.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,50 +36,50 @@
bool LLTrustedMessageService::validate(const std::string& name, LLSD& context)
const
{
- return true;
+ return true;
}
void LLTrustedMessageService::post(LLHTTPNode::ResponsePtr response,
- const LLSD& context,
- const LLSD& input) const
+ const LLSD& context,
+ const LLSD& input) const
{
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
- std::string senderIP = context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST];
- std::string senderPort = context[CONTEXT_REQUEST][CONTEXT_HEADERS]
- ["x-secondlife-udp-listen-port"];
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
+ std::string senderIP = context[CONTEXT_REQUEST][CONTEXT_REMOTE_HOST];
+ std::string senderPort = context[CONTEXT_REQUEST][CONTEXT_HEADERS]
+ ["x-secondlife-udp-listen-port"];
+
+ LLSD message_data;
+ std::string sender = senderIP + ":" + senderPort;
+ message_data["sender"] = sender;
+ message_data["body"] = input;
- LLSD message_data;
- std::string sender = senderIP + ":" + senderPort;
- message_data["sender"] = sender;
- message_data["body"] = input;
-
- // untrusted senders should not have access to the trusted message
- // service, but this can happen in development, so check and warn
- LLMessageConfig::SenderTrust trust =
- LLMessageConfig::getSenderTrustedness(name);
- if ((trust == LLMessageConfig::TRUSTED ||
- (trust == LLMessageConfig::NOT_SET &&
- gMessageSystem->isTrustedMessage(name)))
- && !gMessageSystem->isTrustedSender(LLHost(sender)))
- {
- LL_WARNS("Messaging") << "trusted message POST to /trusted-message/"
- << name << " from unknown or untrusted sender "
- << sender << LL_ENDL;
- response->status(HTTP_FORBIDDEN, "Unknown or untrusted sender");
- }
- else
- {
- gMessageSystem->receivedMessageFromTrustedSender();
- if (input.has("binary-template-data"))
- {
- LL_INFOS() << "Dispatching template: " << input << LL_ENDL;
- // try and send this message using udp dispatch
- LLMessageSystem::dispatchTemplate(name, message_data, response);
- }
- else
- {
- LL_INFOS() << "Dispatching without template: " << input << LL_ENDL;
- LLMessageSystem::dispatch(name, message_data, response);
- }
- }
+ // untrusted senders should not have access to the trusted message
+ // service, but this can happen in development, so check and warn
+ LLMessageConfig::SenderTrust trust =
+ LLMessageConfig::getSenderTrustedness(name);
+ if ((trust == LLMessageConfig::TRUSTED ||
+ (trust == LLMessageConfig::NOT_SET &&
+ gMessageSystem->isTrustedMessage(name)))
+ && !gMessageSystem->isTrustedSender(LLHost(sender)))
+ {
+ LL_WARNS("Messaging") << "trusted message POST to /trusted-message/"
+ << name << " from unknown or untrusted sender "
+ << sender << LL_ENDL;
+ response->status(HTTP_FORBIDDEN, "Unknown or untrusted sender");
+ }
+ else
+ {
+ gMessageSystem->receivedMessageFromTrustedSender();
+ if (input.has("binary-template-data"))
+ {
+ LL_INFOS() << "Dispatching template: " << input << LL_ENDL;
+ // try and send this message using udp dispatch
+ LLMessageSystem::dispatchTemplate(name, message_data, response);
+ }
+ else
+ {
+ LL_INFOS() << "Dispatching without template: " << input << LL_ENDL;
+ LLMessageSystem::dispatch(name, message_data, response);
+ }
+ }
}
diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h
index 12a37bb535..c47987a217 100644
--- a/indra/llmessage/lltrustedmessageservice.h
+++ b/indra/llmessage/lltrustedmessageservice.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,7 +30,7 @@
#include "linden_common.h"
#include "llhttpnode.h"
-// These are defined in lliosocket.h/lliosocket.cpp
+// These are defined in lliosocket.h/lliosocket.cpp
extern const std::string CONTEXT_REMOTE_HOST;
extern const std::string CONTEXT_REMOTE_PORT;
@@ -40,11 +40,11 @@ class LLTrustedMessageService
{
public:
- bool validate(const std::string& name, LLSD& context) const;
-
- void post(LLHTTPNode::ResponsePtr response,
- const LLSD& context,
- const LLSD& input) const;
+ bool validate(const std::string& name, LLSD& context) const;
+
+ void post(LLHTTPNode::ResponsePtr response,
+ const LLSD& context,
+ const LLSD& input) const;
};
#endif // LLTRUSTEDMESSAGESERVICE_H
diff --git a/indra/llmessage/lluseroperation.cpp b/indra/llmessage/lluseroperation.cpp
index 6b0cc63686..f7897f9754 100644
--- a/indra/llmessage/lluseroperation.cpp
+++ b/indra/llmessage/lluseroperation.cpp
@@ -1,190 +1,190 @@
-/**
- * @file lluseroperation.cpp
- * @brief LLUserOperation class definition.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lluseroperation.h"
-
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-LLUserOperationMgr* gUserOperationMgr = NULL;
-
-///----------------------------------------------------------------------------
-/// Class LLUserOperation
-///----------------------------------------------------------------------------
-
-LLUserOperation::LLUserOperation(const LLUUID& agent_id)
-: mAgentID(agent_id),
- mTimer(),
- mNoExpire(false)
-{
- mTransactionID.generate();
-}
-
-LLUserOperation::LLUserOperation(const LLUUID& agent_id,
- const LLUUID& transaction_id) :
- mAgentID(agent_id),
- mTransactionID(transaction_id),
- mTimer(),
- mNoExpire(false)
-{
-}
-
-// protected constructor which is used by base classes that determine
-// transaction, agent, et. after construction.
-LLUserOperation::LLUserOperation() :
- mTimer(),
- mNoExpire(false)
-{
-}
-
-LLUserOperation::~LLUserOperation()
-{
-}
-
-void LLUserOperation::SetNoExpireFlag(const bool flag)
-{
- mNoExpire = flag;
-}
-
-bool LLUserOperation::isExpired()
-{
- if (!mNoExpire)
- {
- const F32 EXPIRE_TIME_SECS = 10.f;
- return mTimer.getElapsedTimeF32() > EXPIRE_TIME_SECS;
- }
- return false;
-}
-
-void LLUserOperation::expire()
-{
- // by default, do do anything.
-}
-
-///----------------------------------------------------------------------------
-/// Class LLUserOperationMgr
-///----------------------------------------------------------------------------
-
-LLUserOperationMgr::LLUserOperationMgr()
-{
-}
-
-
-LLUserOperationMgr::~LLUserOperationMgr()
-{
- if (mUserOperationList.size() > 0)
- {
- LL_WARNS() << "Exiting with user operations pending." << LL_ENDL;
- }
-}
-
-
-void LLUserOperationMgr::addOperation(LLUserOperation* op)
-{
- if(!op)
- {
- LL_WARNS() << "Tried to add null op" << LL_ENDL;
- return;
- }
- LLUUID id = op->getTransactionID();
- llassert(mUserOperationList.count(id) == 0);
- mUserOperationList[id] = op;
-}
-
-
-LLUserOperation* LLUserOperationMgr::findOperation(const LLUUID& tid)
-{
- user_operation_list_t::iterator iter = mUserOperationList.find(tid);
- if (iter != mUserOperationList.end())
- return iter->second;
- else
- return NULL;
-}
-
-
-bool LLUserOperationMgr::deleteOperation(LLUserOperation* op)
-{
- size_t rv = 0;
- if(op)
- {
- LLUUID id = op->getTransactionID();
- rv = mUserOperationList.erase(id);
- delete op;
- op = NULL;
- }
- return rv != 0;
-}
-
-void LLUserOperationMgr::deleteExpiredOperations()
-{
- const S32 MAX_OPS_CONSIDERED = 2000;
- S32 ops_left = MAX_OPS_CONSIDERED;
- LLUserOperation* op = NULL;
- user_operation_list_t::iterator it;
- if(mLastOperationConsidered.isNull())
- {
- it = mUserOperationList.begin();
- }
- else
- {
- it = mUserOperationList.lower_bound(mLastOperationConsidered);
- }
- while((ops_left--) && (it != mUserOperationList.end()))
- {
- op = (*it).second;
- if(op && op->isExpired())
- {
- LL_DEBUGS() << "expiring: " << (*it).first << LL_ENDL;
- op->expire();
- mUserOperationList.erase(it++);
- delete op;
- }
- else if(op)
- {
- ++it;
- }
- else
- {
- mUserOperationList.erase(it++);
- }
- }
- if(it != mUserOperationList.end())
- {
- mLastOperationConsidered = (*it).first;
- }
- else
- {
- mLastOperationConsidered.setNull();
- }
-}
-
-
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
+/**
+ * @file lluseroperation.cpp
+ * @brief LLUserOperation class definition.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lluseroperation.h"
+
+///----------------------------------------------------------------------------
+/// Local function declarations, constants, enums, and typedefs
+///----------------------------------------------------------------------------
+
+LLUserOperationMgr* gUserOperationMgr = NULL;
+
+///----------------------------------------------------------------------------
+/// Class LLUserOperation
+///----------------------------------------------------------------------------
+
+LLUserOperation::LLUserOperation(const LLUUID& agent_id)
+: mAgentID(agent_id),
+ mTimer(),
+ mNoExpire(false)
+{
+ mTransactionID.generate();
+}
+
+LLUserOperation::LLUserOperation(const LLUUID& agent_id,
+ const LLUUID& transaction_id) :
+ mAgentID(agent_id),
+ mTransactionID(transaction_id),
+ mTimer(),
+ mNoExpire(false)
+{
+}
+
+// protected constructor which is used by base classes that determine
+// transaction, agent, et. after construction.
+LLUserOperation::LLUserOperation() :
+ mTimer(),
+ mNoExpire(false)
+{
+}
+
+LLUserOperation::~LLUserOperation()
+{
+}
+
+void LLUserOperation::SetNoExpireFlag(const bool flag)
+{
+ mNoExpire = flag;
+}
+
+bool LLUserOperation::isExpired()
+{
+ if (!mNoExpire)
+ {
+ const F32 EXPIRE_TIME_SECS = 10.f;
+ return mTimer.getElapsedTimeF32() > EXPIRE_TIME_SECS;
+ }
+ return false;
+}
+
+void LLUserOperation::expire()
+{
+ // by default, do do anything.
+}
+
+///----------------------------------------------------------------------------
+/// Class LLUserOperationMgr
+///----------------------------------------------------------------------------
+
+LLUserOperationMgr::LLUserOperationMgr()
+{
+}
+
+
+LLUserOperationMgr::~LLUserOperationMgr()
+{
+ if (mUserOperationList.size() > 0)
+ {
+ LL_WARNS() << "Exiting with user operations pending." << LL_ENDL;
+ }
+}
+
+
+void LLUserOperationMgr::addOperation(LLUserOperation* op)
+{
+ if(!op)
+ {
+ LL_WARNS() << "Tried to add null op" << LL_ENDL;
+ return;
+ }
+ LLUUID id = op->getTransactionID();
+ llassert(mUserOperationList.count(id) == 0);
+ mUserOperationList[id] = op;
+}
+
+
+LLUserOperation* LLUserOperationMgr::findOperation(const LLUUID& tid)
+{
+ user_operation_list_t::iterator iter = mUserOperationList.find(tid);
+ if (iter != mUserOperationList.end())
+ return iter->second;
+ else
+ return NULL;
+}
+
+
+bool LLUserOperationMgr::deleteOperation(LLUserOperation* op)
+{
+ size_t rv = 0;
+ if(op)
+ {
+ LLUUID id = op->getTransactionID();
+ rv = mUserOperationList.erase(id);
+ delete op;
+ op = NULL;
+ }
+ return rv != 0;
+}
+
+void LLUserOperationMgr::deleteExpiredOperations()
+{
+ const S32 MAX_OPS_CONSIDERED = 2000;
+ S32 ops_left = MAX_OPS_CONSIDERED;
+ LLUserOperation* op = NULL;
+ user_operation_list_t::iterator it;
+ if(mLastOperationConsidered.isNull())
+ {
+ it = mUserOperationList.begin();
+ }
+ else
+ {
+ it = mUserOperationList.lower_bound(mLastOperationConsidered);
+ }
+ while((ops_left--) && (it != mUserOperationList.end()))
+ {
+ op = (*it).second;
+ if(op && op->isExpired())
+ {
+ LL_DEBUGS() << "expiring: " << (*it).first << LL_ENDL;
+ op->expire();
+ mUserOperationList.erase(it++);
+ delete op;
+ }
+ else if(op)
+ {
+ ++it;
+ }
+ else
+ {
+ mUserOperationList.erase(it++);
+ }
+ }
+ if(it != mUserOperationList.end())
+ {
+ mLastOperationConsidered = (*it).first;
+ }
+ else
+ {
+ mLastOperationConsidered.setNull();
+ }
+}
+
+
+///----------------------------------------------------------------------------
+/// Local function definitions
+///----------------------------------------------------------------------------
diff --git a/indra/llmessage/lluseroperation.h b/indra/llmessage/lluseroperation.h
index 9d0f4d04d1..384978571c 100644
--- a/indra/llmessage/lluseroperation.h
+++ b/indra/llmessage/lluseroperation.h
@@ -1,97 +1,97 @@
-/**
- * @file lluseroperation.h
- * @brief LLUserOperation class header file - used for message based
- * transaction. For example, L$ transactions.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLUSEROPERATION_H
-#define LL_LLUSEROPERATION_H
-
-#include "lluuid.h"
-#include "llframetimer.h"
-
-#include <map>
-
-class LLUserOperation
-{
-public:
- LLUserOperation(const LLUUID& agent_id);
- LLUserOperation(const LLUUID& agent_id, const LLUUID& transaction_id);
- virtual ~LLUserOperation();
-
- const LLUUID& getTransactionID() const { return mTransactionID; }
- const LLUUID& getAgentID() const { return mAgentID; }
-
- // Operation never got necessary data, so expired
- virtual bool isExpired();
-
- // ability to mark this operation as never expiring.
- void SetNoExpireFlag(const bool flag);
-
- // Send request to the dataserver
- virtual void sendRequest() = 0;
-
- // Run the operation. This will only be called in the case of an
- // actual success or failure of the operation.
- virtual bool execute(bool transaction_success) = 0;
-
- // This method is called when the user op has expired, and is
- // about to be deleted by the manager. This gives the user op the
- // ability to nack someone when the user op is never evaluated
- virtual void expire();
-
-protected:
- LLUserOperation();
-
-protected:
- LLUUID mAgentID;
- LLUUID mTransactionID;
- LLFrameTimer mTimer;
- bool mNoExpire; // this is used for operations that expect an answer and will wait till it gets one.
-};
-
-
-class LLUserOperationMgr
-{
-public:
- LLUserOperationMgr();
- ~LLUserOperationMgr();
-
- void addOperation(LLUserOperation* op);
- LLUserOperation* findOperation(const LLUUID& transaction_id);
- bool deleteOperation(LLUserOperation* op);
-
- // Call this method every once in a while to clean up old
- // transactions.
- void deleteExpiredOperations();
-
-private:
- typedef std::map<LLUUID, LLUserOperation*> user_operation_list_t;
- user_operation_list_t mUserOperationList;
- LLUUID mLastOperationConsidered;
-};
-
-extern LLUserOperationMgr* gUserOperationMgr;
-
-#endif // LL_LLUSEROPERATION_H
+/**
+ * @file lluseroperation.h
+ * @brief LLUserOperation class header file - used for message based
+ * transaction. For example, L$ transactions.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUSEROPERATION_H
+#define LL_LLUSEROPERATION_H
+
+#include "lluuid.h"
+#include "llframetimer.h"
+
+#include <map>
+
+class LLUserOperation
+{
+public:
+ LLUserOperation(const LLUUID& agent_id);
+ LLUserOperation(const LLUUID& agent_id, const LLUUID& transaction_id);
+ virtual ~LLUserOperation();
+
+ const LLUUID& getTransactionID() const { return mTransactionID; }
+ const LLUUID& getAgentID() const { return mAgentID; }
+
+ // Operation never got necessary data, so expired
+ virtual bool isExpired();
+
+ // ability to mark this operation as never expiring.
+ void SetNoExpireFlag(const bool flag);
+
+ // Send request to the dataserver
+ virtual void sendRequest() = 0;
+
+ // Run the operation. This will only be called in the case of an
+ // actual success or failure of the operation.
+ virtual bool execute(bool transaction_success) = 0;
+
+ // This method is called when the user op has expired, and is
+ // about to be deleted by the manager. This gives the user op the
+ // ability to nack someone when the user op is never evaluated
+ virtual void expire();
+
+protected:
+ LLUserOperation();
+
+protected:
+ LLUUID mAgentID;
+ LLUUID mTransactionID;
+ LLFrameTimer mTimer;
+ bool mNoExpire; // this is used for operations that expect an answer and will wait till it gets one.
+};
+
+
+class LLUserOperationMgr
+{
+public:
+ LLUserOperationMgr();
+ ~LLUserOperationMgr();
+
+ void addOperation(LLUserOperation* op);
+ LLUserOperation* findOperation(const LLUUID& transaction_id);
+ bool deleteOperation(LLUserOperation* op);
+
+ // Call this method every once in a while to clean up old
+ // transactions.
+ void deleteExpiredOperations();
+
+private:
+ typedef std::map<LLUUID, LLUserOperation*> user_operation_list_t;
+ user_operation_list_t mUserOperationList;
+ LLUUID mLastOperationConsidered;
+};
+
+extern LLUserOperationMgr* gUserOperationMgr;
+
+#endif // LL_LLUSEROPERATION_H
diff --git a/indra/llmessage/llvehicleparams.h b/indra/llmessage/llvehicleparams.h
index f34df7744e..fe4b68e3bf 100644
--- a/indra/llmessage/llvehicleparams.h
+++ b/indra/llmessage/llvehicleparams.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llvehicleparams.h
* @brief For parameter names that must be shared between the
* scripting language and the LLVehicleAction class on the simulator.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -28,72 +28,72 @@
#ifndef LL_VEHICLE_PARAMS_H
#define LL_VEHICLE_PARAMS_H
-/**
+/**
* The idea is that the various parameters that control vehicle
* behavior can be tweeked by name using general-purpose script calls.
*/
typedef enum e_vehicle_param
{
- VEHICLE_TYPE_NONE, // TYPE_0
- VEHICLE_TYPE_SLED,
- VEHICLE_TYPE_CAR,
- VEHICLE_TYPE_BOAT,
- VEHICLE_TYPE_AIRPLANE,
- VEHICLE_TYPE_BALLOON, // TYPE_5
- VEHICLE_TYPE_6,
- VEHICLE_TYPE_7,
- VEHICLE_TYPE_8,
- VEHICLE_TYPE_9,
- VEHICLE_TYPE_10,
- VEHICLE_TYPE_11,
- VEHICLE_TYPE_12,
- VEHICLE_TYPE_13,
- VEHICLE_TYPE_14,
- VEHICLE_TYPE_15,
-
- // vector parameters
- VEHICLE_LINEAR_FRICTION_TIMESCALE,
- VEHICLE_ANGULAR_FRICTION_TIMESCALE,
- VEHICLE_LINEAR_MOTOR_DIRECTION,
- VEHICLE_ANGULAR_MOTOR_DIRECTION,
- VEHICLE_LINEAR_MOTOR_OFFSET,
- VEHICLE_VECTOR_PARAM_5,
- VEHICLE_VECTOR_PARAM_6,
- VEHICLE_VECTOR_PARAM_7,
-
- // floating point parameters
- VEHICLE_HOVER_HEIGHT,
- VEHICLE_HOVER_EFFICIENCY,
- VEHICLE_HOVER_TIMESCALE,
- VEHICLE_BUOYANCY,
-
- VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,
- VEHICLE_LINEAR_DEFLECTION_TIMESCALE,
- VEHICLE_LINEAR_MOTOR_TIMESCALE,
- VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE,
-
- VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY,
- VEHICLE_ANGULAR_DEFLECTION_TIMESCALE,
- VEHICLE_ANGULAR_MOTOR_TIMESCALE,
- VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE,
-
- VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY,
- VEHICLE_VERTICAL_ATTRACTION_TIMESCALE,
-
- VEHICLE_BANKING_EFFICIENCY,
- VEHICLE_BANKING_MIX,
- VEHICLE_BANKING_TIMESCALE,
-
- VEHICLE_FLOAT_PARAM_17,
- VEHICLE_FLOAT_PARAM_18,
- VEHICLE_FLOAT_PARAM_19,
-
- // rotation parameters
- VEHICLE_REFERENCE_FRAME,
- VEHICLE_ROTATION_PARAM_1,
- VEHICLE_ROTATION_PARAM_2,
- VEHICLE_ROTATION_PARAM_3,
+ VEHICLE_TYPE_NONE, // TYPE_0
+ VEHICLE_TYPE_SLED,
+ VEHICLE_TYPE_CAR,
+ VEHICLE_TYPE_BOAT,
+ VEHICLE_TYPE_AIRPLANE,
+ VEHICLE_TYPE_BALLOON, // TYPE_5
+ VEHICLE_TYPE_6,
+ VEHICLE_TYPE_7,
+ VEHICLE_TYPE_8,
+ VEHICLE_TYPE_9,
+ VEHICLE_TYPE_10,
+ VEHICLE_TYPE_11,
+ VEHICLE_TYPE_12,
+ VEHICLE_TYPE_13,
+ VEHICLE_TYPE_14,
+ VEHICLE_TYPE_15,
+
+ // vector parameters
+ VEHICLE_LINEAR_FRICTION_TIMESCALE,
+ VEHICLE_ANGULAR_FRICTION_TIMESCALE,
+ VEHICLE_LINEAR_MOTOR_DIRECTION,
+ VEHICLE_ANGULAR_MOTOR_DIRECTION,
+ VEHICLE_LINEAR_MOTOR_OFFSET,
+ VEHICLE_VECTOR_PARAM_5,
+ VEHICLE_VECTOR_PARAM_6,
+ VEHICLE_VECTOR_PARAM_7,
+
+ // floating point parameters
+ VEHICLE_HOVER_HEIGHT,
+ VEHICLE_HOVER_EFFICIENCY,
+ VEHICLE_HOVER_TIMESCALE,
+ VEHICLE_BUOYANCY,
+
+ VEHICLE_LINEAR_DEFLECTION_EFFICIENCY,
+ VEHICLE_LINEAR_DEFLECTION_TIMESCALE,
+ VEHICLE_LINEAR_MOTOR_TIMESCALE,
+ VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE,
+
+ VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY,
+ VEHICLE_ANGULAR_DEFLECTION_TIMESCALE,
+ VEHICLE_ANGULAR_MOTOR_TIMESCALE,
+ VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE,
+
+ VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY,
+ VEHICLE_VERTICAL_ATTRACTION_TIMESCALE,
+
+ VEHICLE_BANKING_EFFICIENCY,
+ VEHICLE_BANKING_MIX,
+ VEHICLE_BANKING_TIMESCALE,
+
+ VEHICLE_FLOAT_PARAM_17,
+ VEHICLE_FLOAT_PARAM_18,
+ VEHICLE_FLOAT_PARAM_19,
+
+ // rotation parameters
+ VEHICLE_REFERENCE_FRAME,
+ VEHICLE_ROTATION_PARAM_1,
+ VEHICLE_ROTATION_PARAM_2,
+ VEHICLE_ROTATION_PARAM_3,
} EVehicleParam;
@@ -104,20 +104,20 @@ typedef enum e_vehicle_param
const U32 VEHICLE_FLAG_NO_DEFLECTION_UP = 1 << 0;
// spring-loads roll only
-const U32 VEHICLE_FLAG_LIMIT_ROLL_ONLY = 1 << 1;
+const U32 VEHICLE_FLAG_LIMIT_ROLL_ONLY = 1 << 1;
// hover flags
-const U32 VEHICLE_FLAG_HOVER_WATER_ONLY = 1 << 2;
-const U32 VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 1 << 3;
-const U32 VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 1 << 4;
-const U32 VEHICLE_FLAG_HOVER_UP_ONLY = 1 << 5;
+const U32 VEHICLE_FLAG_HOVER_WATER_ONLY = 1 << 2;
+const U32 VEHICLE_FLAG_HOVER_TERRAIN_ONLY = 1 << 3;
+const U32 VEHICLE_FLAG_HOVER_GLOBAL_HEIGHT = 1 << 4;
+const U32 VEHICLE_FLAG_HOVER_UP_ONLY = 1 << 5;
-// caps world-z component of linear motor to prevent
+// caps world-z component of linear motor to prevent
// climbing up into the sky
-const U32 VEHICLE_FLAG_LIMIT_MOTOR_UP = 1 << 6;
+const U32 VEHICLE_FLAG_LIMIT_MOTOR_UP = 1 << 6;
-const U32 VEHICLE_FLAG_MOUSELOOK_STEER = 1 << 7;
-const U32 VEHICLE_FLAG_MOUSELOOK_BANK = 1 << 8;
-const U32 VEHICLE_FLAG_CAMERA_DECOUPLED = 1 << 9;
+const U32 VEHICLE_FLAG_MOUSELOOK_STEER = 1 << 7;
+const U32 VEHICLE_FLAG_MOUSELOOK_BANK = 1 << 8;
+const U32 VEHICLE_FLAG_CAMERA_DECOUPLED = 1 << 9;
#endif
diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp
index 58e85b49b4..057f4de0ab 100644
--- a/indra/llmessage/llxfer.cpp
+++ b/indra/llmessage/llxfer.cpp
@@ -1,388 +1,388 @@
-/**
- * @file llxfer.cpp
- * @brief implementation of LLXfer class for a single xfer.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llxfer.h"
-#include "lluuid.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "u64.h"
-
-//number of bytes sent in each message
-const U32 LL_XFER_CHUNK_SIZE = 1000;
-
-const U32 LLXfer::XFER_FILE = 1;
-const U32 LLXfer::XFER_VFILE = 2;
-const U32 LLXfer::XFER_MEM = 3;
-
-///////////////////////////////////////////////////////////
-
-LLXfer::LLXfer (S32 chunk_size)
-{
- init(chunk_size);
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer::~LLXfer ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::init (S32 chunk_size)
-{
- mID = 0;
-
- mPacketNum = -1; // there's a preincrement before sending the zeroth packet
- mXferSize = 0;
-
- mStatus = e_LL_XFER_UNINITIALIZED;
- mWaitingForACK = false;
-
- mCallback = NULL;
- mCallbackDataHandle = NULL;
- mCallbackResult = 0;
-
- mBufferContainsEOF = false;
- mBuffer = NULL;
- mBufferLength = 0;
- mBufferStartOffset = 0;
-
- mRetries = 0;
-
- if (chunk_size < 1)
- {
- chunk_size = LL_XFER_CHUNK_SIZE;
- }
- mChunkSize = chunk_size;
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::cleanup ()
-{
- if (mBuffer)
- {
- delete[] mBuffer;
- mBuffer = NULL;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::startSend (U64 xfer_id, const LLHost &remote_host)
-{
- LL_WARNS("Xfer") << "unexpected call to base class LLXfer::startSend for " << getFileName() << LL_ENDL;
- return (-1);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::closeFileHandle()
-{
- LL_WARNS("Xfer") << "unexpected call to base class LLXfer::closeFileHandle for " << getFileName() << LL_ENDL;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::reopenFileHandle()
-{
- LL_WARNS("Xfer") << "unexpected call to base class LLXfer::reopenFileHandle for " << getFileName() << LL_ENDL;
- return (-1);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::setXferSize (S32 xfer_size)
-{
- mXferSize = xfer_size;
-// cout << "starting transfer of size: " << xfer_size << endl;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::startDownload()
-{
- LL_WARNS("Xfer") << "undifferentiated LLXfer::startDownload for " << getFileName()
- << LL_ENDL;
- return (-1);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::receiveData (char *datap, S32 data_size)
-{
- S32 retval = 0;
-
- if (((S32) mBufferLength + data_size) > getMaxBufferSize())
- { // Write existing data to disk if it's larger than the buffer size
- retval = flush();
- }
-
- if (!retval)
- {
- if (datap != NULL)
- { // Append new data to mBuffer
- memcpy(&mBuffer[mBufferLength],datap,data_size); /*Flawfinder: ignore*/
- mBufferLength += data_size;
- }
- else
- {
- LL_ERRS("Xfer") << "NULL data passed in receiveData" << LL_ENDL;
- }
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::flush()
-{
- // only files have somewhere to flush to
- // if we get called with a flush it means we've blown past our
- // allocated buffer size
-
- return (-1);
-}
-
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::suck(S32 start_position)
-{
- LL_WARNS("Xfer") << "Attempted to send a packet outside the buffer bounds in LLXfer::suck()" << LL_ENDL;
- return (-1);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::sendPacket(S32 packet_num)
-{
- char fdata_buf[LL_XFER_LARGE_PAYLOAD+4]; /* Flawfinder: ignore */
- S32 fdata_size = mChunkSize;
- bool last_packet = false;
- S32 num_copy = 0;
-
- // if the desired packet is not in our current buffered excerpt from the file. . .
- if (((U32)packet_num*fdata_size < mBufferStartOffset)
- || ((U32)llmin((U32)mXferSize,(U32)((U32)(packet_num+1)*fdata_size)) > mBufferStartOffset + mBufferLength))
-
- {
- if (suck(packet_num*fdata_size)) // returns non-zero on failure
- {
- abort(LL_ERR_EOF);
- return;
- }
- }
-
- S32 desired_read_position = 0;
-
- desired_read_position = packet_num * fdata_size - mBufferStartOffset;
-
- fdata_size = llmin((S32)mBufferLength-desired_read_position, mChunkSize);
-
- if (fdata_size < 0)
- {
- LL_WARNS("Xfer") << "negative data size in xfer send, aborting" << LL_ENDL;
- abort(LL_ERR_EOF);
- return;
- }
-
- if (((U32)(desired_read_position + fdata_size) >= (U32)mBufferLength) && (mBufferContainsEOF))
- {
- last_packet = true;
- }
-
- if (packet_num)
- {
- num_copy = llmin(fdata_size, (S32)sizeof(fdata_buf));
- num_copy = llmin(num_copy, (S32)(mBufferLength - desired_read_position));
- if (num_copy > 0)
- {
- memcpy(fdata_buf,&mBuffer[desired_read_position],num_copy); /*Flawfinder: ignore*/
- }
- }
- else
- {
- // if we're the first packet, encode size as an additional S32
- // at start of data.
- num_copy = llmin(fdata_size, (S32)(sizeof(fdata_buf)-sizeof(S32)));
- num_copy = llmin(
- num_copy,
- (S32)(mBufferLength - desired_read_position));
- if (num_copy > 0)
- {
- memcpy( /*Flawfinder: ignore*/
- fdata_buf + sizeof(S32),
- &mBuffer[desired_read_position],
- num_copy);
- }
- fdata_size += sizeof(S32);
- htolememcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
- }
-
- S32 encoded_packetnum = encodePacketNum(packet_num,last_packet);
-
- if (fdata_size)
- {
- // send the packet
- gMessageSystem->newMessageFast(_PREHASH_SendXferPacket);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
-
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addU32Fast(_PREHASH_Packet, encoded_packetnum);
-
- gMessageSystem->nextBlockFast(_PREHASH_DataPacket);
- gMessageSystem->addBinaryDataFast(_PREHASH_Data, &fdata_buf,fdata_size);
-
- S32 sent_something = gMessageSystem->sendMessage(mRemoteHost);
- if (sent_something == 0)
- {
- abort(LL_ERR_CIRCUIT_GONE);
- return;
- }
-
- ACKTimer.reset();
- mWaitingForACK = true;
- }
- if (last_packet)
- {
- mStatus = e_LL_XFER_COMPLETE;
- }
- else
- {
- mStatus = e_LL_XFER_IN_PROGRESS;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::sendNextPacket()
-{
- mRetries = 0;
- sendPacket(++mPacketNum);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::resendLastPacket()
-{
- mRetries++;
- sendPacket(mPacketNum);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::processEOF()
-{
- S32 retval = 0;
-
- mStatus = e_LL_XFER_COMPLETE;
-
- if (LL_ERR_NOERR == mCallbackResult)
- {
- LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " complete: " << getFileName()
- << LL_ENDL;
- }
- else
- {
- LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " failed, code "
- << mCallbackResult << ": " << getFileName() << LL_ENDL;
- }
-
- if (mCallback)
- {
- mCallback(mCallbackDataHandle,mCallbackResult, LLExtStat::NONE);
- }
-
- return(retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::encodePacketNum(S32 packet_num, bool is_EOF)
-{
- if (is_EOF)
- {
- packet_num |= 0x80000000;
- }
- return packet_num;
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer::abort (S32 result_code)
-{
- mCallbackResult = result_code;
-
- LL_INFOS("Xfer") << "Aborting xfer from " << mRemoteHost << " named " << getFileName()
- << " - error: " << result_code << LL_ENDL;
-
- if (result_code != LL_ERR_CIRCUIT_GONE)
- {
- gMessageSystem->newMessageFast(_PREHASH_AbortXfer);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addS32Fast(_PREHASH_Result, result_code);
-
- gMessageSystem->sendMessage(mRemoteHost);
- }
-
- mStatus = e_LL_XFER_ABORTED;
-}
-
-
-///////////////////////////////////////////////////////////
-
-std::string LLXfer::getFileName()
-{
- return U64_to_str(mID);
-}
-
-///////////////////////////////////////////////////////////
-
-U32 LLXfer::getXferTypeTag()
-{
- return 0;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer::getMaxBufferSize ()
-{
- return(mXferSize);
-}
-
-
-std::ostream& operator<< (std::ostream& os, LLXfer &hh)
-{
- os << hh.getFileName() ;
- return os;
-}
+/**
+ * @file llxfer.cpp
+ * @brief implementation of LLXfer class for a single xfer.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxfer.h"
+#include "lluuid.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "u64.h"
+
+//number of bytes sent in each message
+const U32 LL_XFER_CHUNK_SIZE = 1000;
+
+const U32 LLXfer::XFER_FILE = 1;
+const U32 LLXfer::XFER_VFILE = 2;
+const U32 LLXfer::XFER_MEM = 3;
+
+///////////////////////////////////////////////////////////
+
+LLXfer::LLXfer (S32 chunk_size)
+{
+ init(chunk_size);
+}
+
+///////////////////////////////////////////////////////////
+
+LLXfer::~LLXfer ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::init (S32 chunk_size)
+{
+ mID = 0;
+
+ mPacketNum = -1; // there's a preincrement before sending the zeroth packet
+ mXferSize = 0;
+
+ mStatus = e_LL_XFER_UNINITIALIZED;
+ mWaitingForACK = false;
+
+ mCallback = NULL;
+ mCallbackDataHandle = NULL;
+ mCallbackResult = 0;
+
+ mBufferContainsEOF = false;
+ mBuffer = NULL;
+ mBufferLength = 0;
+ mBufferStartOffset = 0;
+
+ mRetries = 0;
+
+ if (chunk_size < 1)
+ {
+ chunk_size = LL_XFER_CHUNK_SIZE;
+ }
+ mChunkSize = chunk_size;
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::cleanup ()
+{
+ if (mBuffer)
+ {
+ delete[] mBuffer;
+ mBuffer = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::startSend (U64 xfer_id, const LLHost &remote_host)
+{
+ LL_WARNS("Xfer") << "unexpected call to base class LLXfer::startSend for " << getFileName() << LL_ENDL;
+ return (-1);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::closeFileHandle()
+{
+ LL_WARNS("Xfer") << "unexpected call to base class LLXfer::closeFileHandle for " << getFileName() << LL_ENDL;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::reopenFileHandle()
+{
+ LL_WARNS("Xfer") << "unexpected call to base class LLXfer::reopenFileHandle for " << getFileName() << LL_ENDL;
+ return (-1);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::setXferSize (S32 xfer_size)
+{
+ mXferSize = xfer_size;
+// cout << "starting transfer of size: " << xfer_size << endl;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::startDownload()
+{
+ LL_WARNS("Xfer") << "undifferentiated LLXfer::startDownload for " << getFileName()
+ << LL_ENDL;
+ return (-1);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::receiveData (char *datap, S32 data_size)
+{
+ S32 retval = 0;
+
+ if (((S32) mBufferLength + data_size) > getMaxBufferSize())
+ { // Write existing data to disk if it's larger than the buffer size
+ retval = flush();
+ }
+
+ if (!retval)
+ {
+ if (datap != NULL)
+ { // Append new data to mBuffer
+ memcpy(&mBuffer[mBufferLength],datap,data_size); /*Flawfinder: ignore*/
+ mBufferLength += data_size;
+ }
+ else
+ {
+ LL_ERRS("Xfer") << "NULL data passed in receiveData" << LL_ENDL;
+ }
+ }
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::flush()
+{
+ // only files have somewhere to flush to
+ // if we get called with a flush it means we've blown past our
+ // allocated buffer size
+
+ return (-1);
+}
+
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::suck(S32 start_position)
+{
+ LL_WARNS("Xfer") << "Attempted to send a packet outside the buffer bounds in LLXfer::suck()" << LL_ENDL;
+ return (-1);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::sendPacket(S32 packet_num)
+{
+ char fdata_buf[LL_XFER_LARGE_PAYLOAD+4]; /* Flawfinder: ignore */
+ S32 fdata_size = mChunkSize;
+ bool last_packet = false;
+ S32 num_copy = 0;
+
+ // if the desired packet is not in our current buffered excerpt from the file. . .
+ if (((U32)packet_num*fdata_size < mBufferStartOffset)
+ || ((U32)llmin((U32)mXferSize,(U32)((U32)(packet_num+1)*fdata_size)) > mBufferStartOffset + mBufferLength))
+
+ {
+ if (suck(packet_num*fdata_size)) // returns non-zero on failure
+ {
+ abort(LL_ERR_EOF);
+ return;
+ }
+ }
+
+ S32 desired_read_position = 0;
+
+ desired_read_position = packet_num * fdata_size - mBufferStartOffset;
+
+ fdata_size = llmin((S32)mBufferLength-desired_read_position, mChunkSize);
+
+ if (fdata_size < 0)
+ {
+ LL_WARNS("Xfer") << "negative data size in xfer send, aborting" << LL_ENDL;
+ abort(LL_ERR_EOF);
+ return;
+ }
+
+ if (((U32)(desired_read_position + fdata_size) >= (U32)mBufferLength) && (mBufferContainsEOF))
+ {
+ last_packet = true;
+ }
+
+ if (packet_num)
+ {
+ num_copy = llmin(fdata_size, (S32)sizeof(fdata_buf));
+ num_copy = llmin(num_copy, (S32)(mBufferLength - desired_read_position));
+ if (num_copy > 0)
+ {
+ memcpy(fdata_buf,&mBuffer[desired_read_position],num_copy); /*Flawfinder: ignore*/
+ }
+ }
+ else
+ {
+ // if we're the first packet, encode size as an additional S32
+ // at start of data.
+ num_copy = llmin(fdata_size, (S32)(sizeof(fdata_buf)-sizeof(S32)));
+ num_copy = llmin(
+ num_copy,
+ (S32)(mBufferLength - desired_read_position));
+ if (num_copy > 0)
+ {
+ memcpy( /*Flawfinder: ignore*/
+ fdata_buf + sizeof(S32),
+ &mBuffer[desired_read_position],
+ num_copy);
+ }
+ fdata_size += sizeof(S32);
+ htolememcpy(fdata_buf,&mXferSize, MVT_S32, sizeof(S32));
+ }
+
+ S32 encoded_packetnum = encodePacketNum(packet_num,last_packet);
+
+ if (fdata_size)
+ {
+ // send the packet
+ gMessageSystem->newMessageFast(_PREHASH_SendXferPacket);
+ gMessageSystem->nextBlockFast(_PREHASH_XferID);
+
+ gMessageSystem->addU64Fast(_PREHASH_ID, mID);
+ gMessageSystem->addU32Fast(_PREHASH_Packet, encoded_packetnum);
+
+ gMessageSystem->nextBlockFast(_PREHASH_DataPacket);
+ gMessageSystem->addBinaryDataFast(_PREHASH_Data, &fdata_buf,fdata_size);
+
+ S32 sent_something = gMessageSystem->sendMessage(mRemoteHost);
+ if (sent_something == 0)
+ {
+ abort(LL_ERR_CIRCUIT_GONE);
+ return;
+ }
+
+ ACKTimer.reset();
+ mWaitingForACK = true;
+ }
+ if (last_packet)
+ {
+ mStatus = e_LL_XFER_COMPLETE;
+ }
+ else
+ {
+ mStatus = e_LL_XFER_IN_PROGRESS;
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::sendNextPacket()
+{
+ mRetries = 0;
+ sendPacket(++mPacketNum);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::resendLastPacket()
+{
+ mRetries++;
+ sendPacket(mPacketNum);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::processEOF()
+{
+ S32 retval = 0;
+
+ mStatus = e_LL_XFER_COMPLETE;
+
+ if (LL_ERR_NOERR == mCallbackResult)
+ {
+ LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " complete: " << getFileName()
+ << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("Xfer") << "xfer from " << mRemoteHost << " failed, code "
+ << mCallbackResult << ": " << getFileName() << LL_ENDL;
+ }
+
+ if (mCallback)
+ {
+ mCallback(mCallbackDataHandle,mCallbackResult, LLExtStat::NONE);
+ }
+
+ return(retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::encodePacketNum(S32 packet_num, bool is_EOF)
+{
+ if (is_EOF)
+ {
+ packet_num |= 0x80000000;
+ }
+ return packet_num;
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer::abort (S32 result_code)
+{
+ mCallbackResult = result_code;
+
+ LL_INFOS("Xfer") << "Aborting xfer from " << mRemoteHost << " named " << getFileName()
+ << " - error: " << result_code << LL_ENDL;
+
+ if (result_code != LL_ERR_CIRCUIT_GONE)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_AbortXfer);
+ gMessageSystem->nextBlockFast(_PREHASH_XferID);
+ gMessageSystem->addU64Fast(_PREHASH_ID, mID);
+ gMessageSystem->addS32Fast(_PREHASH_Result, result_code);
+
+ gMessageSystem->sendMessage(mRemoteHost);
+ }
+
+ mStatus = e_LL_XFER_ABORTED;
+}
+
+
+///////////////////////////////////////////////////////////
+
+std::string LLXfer::getFileName()
+{
+ return U64_to_str(mID);
+}
+
+///////////////////////////////////////////////////////////
+
+U32 LLXfer::getXferTypeTag()
+{
+ return 0;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer::getMaxBufferSize ()
+{
+ return(mXferSize);
+}
+
+
+std::ostream& operator<< (std::ostream& os, LLXfer &hh)
+{
+ os << hh.getFileName() ;
+ return os;
+}
diff --git a/indra/llmessage/llxfer.h b/indra/llmessage/llxfer.h
index 6b236df1a5..22cf05ba5a 100644
--- a/indra/llmessage/llxfer.h
+++ b/indra/llmessage/llxfer.h
@@ -1,123 +1,123 @@
-/**
- * @file llxfer.h
- * @brief definition of LLXfer class for a single xfer
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLXFER_H
-#define LL_LLXFER_H
-
-#include "message.h"
-#include "lltimer.h"
-#include "llextendedstatus.h"
-
-const S32 LL_XFER_LARGE_PAYLOAD = 7680;
-const S32 LL_ERR_FILE_EMPTY = -44;
-const int LL_ERR_FILE_NOT_FOUND = -43;
-const int LL_ERR_CANNOT_OPEN_FILE = -42;
-const int LL_ERR_EOF = -39;
-
-typedef enum ELLXferStatus {
- e_LL_XFER_UNINITIALIZED,
- e_LL_XFER_REGISTERED, // a buffer which has been registered as available for a request
- e_LL_XFER_PENDING, // a transfer which has been requested but is waiting for a free slot
- e_LL_XFER_IN_PROGRESS,
- e_LL_XFER_COMPLETE,
- e_LL_XFER_ABORTED,
- e_LL_XFER_NONE
-} ELLXferStatus;
-
-class LLXfer
-{
- private:
- protected:
- S32 mChunkSize;
-
- public:
- U64 mID;
- S32 mPacketNum;
-
- LLHost mRemoteHost;
- S32 mXferSize;
-
- char *mBuffer;
- U32 mBufferLength; // Size of valid data, not actual allocated buffer size
- U32 mBufferStartOffset;
- bool mBufferContainsEOF;
-
- ELLXferStatus mStatus;
-
- bool mWaitingForACK;
-
- void (*mCallback)(void **,S32,LLExtStat);
- void **mCallbackDataHandle;
- S32 mCallbackResult;
-
- LLTimer ACKTimer;
- S32 mRetries;
-
- static const U32 XFER_FILE;
- static const U32 XFER_VFILE;
- static const U32 XFER_MEM;
-
- private:
- protected:
- public:
- LLXfer (S32 chunk_size);
- virtual ~LLXfer();
-
- void init(S32 chunk_size);
- virtual void cleanup();
-
- virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
- virtual void closeFileHandle();
- virtual S32 reopenFileHandle();
- virtual void sendPacket(S32 packet_num);
- virtual void sendNextPacket();
- virtual void resendLastPacket();
- virtual S32 processEOF();
- virtual S32 startDownload();
- virtual S32 receiveData (char *datap, S32 data_size);
- virtual void abort(S32);
-
- virtual S32 suck(S32 start_position);
- virtual S32 flush();
-
- virtual S32 encodePacketNum(S32 packet_num, bool is_eof);
- virtual void setXferSize (S32 data_size);
- virtual S32 getMaxBufferSize();
-
- virtual std::string getFileName();
-
- virtual U32 getXferTypeTag();
-
- friend std::ostream& operator<< (std::ostream& os, LLXfer &hh);
-
-};
-
-#endif
-
-
-
-
-
+/**
+ * @file llxfer.h
+ * @brief definition of LLXfer class for a single xfer
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLXFER_H
+#define LL_LLXFER_H
+
+#include "message.h"
+#include "lltimer.h"
+#include "llextendedstatus.h"
+
+const S32 LL_XFER_LARGE_PAYLOAD = 7680;
+const S32 LL_ERR_FILE_EMPTY = -44;
+const int LL_ERR_FILE_NOT_FOUND = -43;
+const int LL_ERR_CANNOT_OPEN_FILE = -42;
+const int LL_ERR_EOF = -39;
+
+typedef enum ELLXferStatus {
+ e_LL_XFER_UNINITIALIZED,
+ e_LL_XFER_REGISTERED, // a buffer which has been registered as available for a request
+ e_LL_XFER_PENDING, // a transfer which has been requested but is waiting for a free slot
+ e_LL_XFER_IN_PROGRESS,
+ e_LL_XFER_COMPLETE,
+ e_LL_XFER_ABORTED,
+ e_LL_XFER_NONE
+} ELLXferStatus;
+
+class LLXfer
+{
+ private:
+ protected:
+ S32 mChunkSize;
+
+ public:
+ U64 mID;
+ S32 mPacketNum;
+
+ LLHost mRemoteHost;
+ S32 mXferSize;
+
+ char *mBuffer;
+ U32 mBufferLength; // Size of valid data, not actual allocated buffer size
+ U32 mBufferStartOffset;
+ bool mBufferContainsEOF;
+
+ ELLXferStatus mStatus;
+
+ bool mWaitingForACK;
+
+ void (*mCallback)(void **,S32,LLExtStat);
+ void **mCallbackDataHandle;
+ S32 mCallbackResult;
+
+ LLTimer ACKTimer;
+ S32 mRetries;
+
+ static const U32 XFER_FILE;
+ static const U32 XFER_VFILE;
+ static const U32 XFER_MEM;
+
+ private:
+ protected:
+ public:
+ LLXfer (S32 chunk_size);
+ virtual ~LLXfer();
+
+ void init(S32 chunk_size);
+ virtual void cleanup();
+
+ virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
+ virtual void closeFileHandle();
+ virtual S32 reopenFileHandle();
+ virtual void sendPacket(S32 packet_num);
+ virtual void sendNextPacket();
+ virtual void resendLastPacket();
+ virtual S32 processEOF();
+ virtual S32 startDownload();
+ virtual S32 receiveData (char *datap, S32 data_size);
+ virtual void abort(S32);
+
+ virtual S32 suck(S32 start_position);
+ virtual S32 flush();
+
+ virtual S32 encodePacketNum(S32 packet_num, bool is_eof);
+ virtual void setXferSize (S32 data_size);
+ virtual S32 getMaxBufferSize();
+
+ virtual std::string getFileName();
+
+ virtual U32 getXferTypeTag();
+
+ friend std::ostream& operator<< (std::ostream& os, LLXfer &hh);
+
+};
+
+#endif
+
+
+
+
+
diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp
index ef2915ede3..a9450f725b 100644
--- a/indra/llmessage/llxfer_file.cpp
+++ b/indra/llmessage/llxfer_file.cpp
@@ -1,475 +1,475 @@
-/**
- * @file llxfer_file.cpp
- * @brief implementation of LLXfer_File class for a single xfer (file)
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#if !LL_WINDOWS
-#include <errno.h>
-#include <unistd.h>
-#endif
-
-#include "llxfer_file.h"
-#include "lluuid.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "llstring.h"
-#include "lldir.h"
-
-// size of chunks read from/written to disk
-const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
-
-// local function to copy a file
-S32 copy_file(const std::string& from, const std::string& to);
-
-///////////////////////////////////////////////////////////
-
-LLXfer_File::LLXfer_File (S32 chunk_size)
-: LLXfer(chunk_size)
-{
- init(LLStringUtil::null, false, chunk_size);
-}
-
-LLXfer_File::LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
-: LLXfer(chunk_size)
-{
- init(local_filename, delete_local_on_completion, chunk_size);
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer_File::~LLXfer_File ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_File::init (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
-{
-
- mFp = NULL;
- mLocalFilename.clear();
- mRemoteFilename.clear();
- mRemotePath = LL_PATH_NONE;
- mTempFilename.clear();
- mDeleteLocalOnCompletion = false;
- mDeleteRemoteOnCompletion = false;
-
- if (!local_filename.empty())
- {
- mLocalFilename = local_filename.substr(0,LL_MAX_PATH-1);
-
- // You can only automatically delete .tmp file as a safeguard against nasty messages.
- std::string exten = mLocalFilename.substr(mLocalFilename.length()-4, 4);
- mDeleteLocalOnCompletion = (delete_local_on_completion && exten == ".tmp");
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_File::cleanup ()
-{
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-
- LLFile::remove(mTempFilename, ENOENT);
-
- if (mDeleteLocalOnCompletion)
- {
- LL_DEBUGS("Xfer") << "Removing file: " << mLocalFilename << LL_ENDL;
- LLFile::remove(mLocalFilename, ENOENT);
- }
- else
- {
- LL_DEBUGS("Xfer") << "Keeping local file: " << mLocalFilename << LL_ENDL;
- }
-
- LLXfer::cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::initializeRequest(U64 xfer_id,
- const std::string& local_filename,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data)
-{
- S32 retval = 0; // presume success
-
- mID = xfer_id;
- mLocalFilename = local_filename;
- mRemoteFilename = remote_filename;
- mRemotePath = remote_path;
- mRemoteHost = remote_host;
- mDeleteRemoteOnCompletion = delete_remote_on_completion;
-
- mTempFilename = gDirUtilp->getTempFilename();
-
- mCallback = callback;
- mCallbackDataHandle = user_data;
- mCallbackResult = LL_ERR_NOERR;
-
- LL_INFOS("Xfer") << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL;
-
- if (mBuffer)
- {
- delete(mBuffer);
- mBuffer = NULL;
- }
-
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
- mBufferLength = 0;
-
- mPacketNum = 0;
-
- mStatus = e_LL_XFER_PENDING;
- return retval;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::startDownload()
-{
- S32 retval = 0; // presume success
- mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
-
- // tbd - is it premature to send this message if the queue is backed up?
- gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
- gMessageSystem->addU8("FilePath", (U8) mRemotePath);
- gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
- gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
- gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
- gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
-
- gMessageSystem->sendReliable(mRemoteHost);
- mStatus = e_LL_XFER_IN_PROGRESS;
- }
- else
- {
- LL_WARNS("Xfer") << "Couldn't create file to be received!" << LL_ENDL;
- retval = -1;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host)
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- mRemoteHost = remote_host;
- mID = xfer_id;
- mPacketNum = -1;
-
-// cout << "Sending file: " << mLocalFilename << endl;
-
- delete [] mBuffer;
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
-
- mBufferLength = 0;
- mBufferStartOffset = 0;
-
- // We leave the file open, assuming we'll start reading and sending soon
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
- if (mFp)
- {
- fseek(mFp,0,SEEK_END);
-
- S32 file_size = ftell(mFp);
- if (file_size <= 0)
- {
- return LL_ERR_FILE_EMPTY;
- }
- setXferSize(file_size);
-
- fseek(mFp,0,SEEK_SET);
- }
- else
- {
- LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found." << LL_ENDL;
- return (LL_ERR_FILE_NOT_FOUND);
- }
-
- mStatus = e_LL_XFER_PENDING;
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-void LLXfer_File::closeFileHandle()
-{
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::reopenFileHandle()
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- if (mFp == NULL)
- {
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
- if (mFp == NULL)
- {
- LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL;
- retval = LL_ERR_FILE_NOT_FOUND;
- }
- }
-
- return retval;
-}
-
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::getMaxBufferSize ()
-{
- return(LL_MAX_XFER_FILE_BUFFER);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::suck(S32 start_position)
-{
- S32 retval = 0;
-
- if (mFp)
- {
- // grab a buffer from the right place in the file
- fseek (mFp,start_position,SEEK_SET);
-
- mBufferLength = (U32)fread(mBuffer,1,LL_MAX_XFER_FILE_BUFFER,mFp);
- mBufferStartOffset = start_position;
-
- if (feof(mFp))
- {
- mBufferContainsEOF = true;
- }
- else
- {
- mBufferContainsEOF = false;
- }
- }
- else
- {
- retval = -1;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::flush()
-{
- S32 retval = 0;
- if (mBufferLength)
- {
- if (mFp)
- {
- LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL;
- }
- mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */
-
- if (mFp)
- {
- S32 write_size = fwrite(mBuffer,1,mBufferLength,mFp);
- if (write_size != mBufferLength)
- {
- LL_WARNS("Xfer") << "Non-matching write size, requested " << mBufferLength
- << " but wrote " << write_size
- << LL_ENDL;
- }
-
-// LL_INFOS("Xfer") << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL;
- fclose(mFp);
- mFp = NULL;
-
- mBufferLength = 0;
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL;
- retval = LL_ERR_CANNOT_OPEN_FILE;
- }
- }
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_File::processEOF()
-{
- S32 retval = 0;
- mStatus = e_LL_XFER_COMPLETE;
-
- S32 flushval = flush();
-
- // If we have no other errors, our error becomes the error generated by
- // flush.
- if (!mCallbackResult)
- {
- mCallbackResult = flushval;
- }
-
- LLFile::remove(mLocalFilename, ENOENT);
-
- if (!mCallbackResult)
- {
- if (LLFile::rename(mTempFilename,mLocalFilename))
- {
-#if !LL_WINDOWS
- S32 error_number = errno;
- LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - "
- << mTempFilename << " to " << mLocalFilename << LL_ENDL;
- if(EXDEV == error_number)
- {
- if(copy_file(mTempFilename, mLocalFilename) == 0)
- {
- LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL;
- unlink(mTempFilename.c_str());
- }
- else
- {
- LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to "
- << mLocalFilename << LL_ENDL;
- }
- }
- else
- {
- //LLFILE* fp = LLFile::fopen(mTempFilename, "r");
- //LL_WARNS() << "File " << mTempFilename << " does "
- // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
- //if(fp) fclose(fp);
- //fp = LLFile::fopen(mLocalFilename, "r");
- //LL_WARNS() << "File " << mLocalFilename << " does "
- // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
- //if(fp) fclose(fp);
- LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV ("
- << EXDEV << ")" << LL_ENDL;
- }
-#else
- LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to "
- << mLocalFilename << LL_ENDL;
-#endif
- }
- }
-
- if (mFp)
- {
- fclose(mFp);
- mFp = NULL;
- }
-
- retval = LLXfer::processEOF();
-
- return(retval);
-}
-
-///////////////////////////////////////////////////////////
-
-bool LLXfer_File::matchesLocalFilename(const std::string& filename)
-{
- return (filename == mLocalFilename);
-}
-
-///////////////////////////////////////////////////////////
-
-bool LLXfer_File::matchesRemoteFilename(const std::string& filename, ELLPath remote_path)
-{
- return ((filename == mRemoteFilename) && (remote_path == mRemotePath));
-}
-
-
-///////////////////////////////////////////////////////////
-
-std::string LLXfer_File::getFileName()
-{
- return mLocalFilename;
-}
-
-///////////////////////////////////////////////////////////
-
-// hacky - doesn't matter what this is
-// as long as it's different from the other classes
-U32 LLXfer_File::getXferTypeTag()
-{
- return LLXfer::XFER_FILE;
-}
-
-///////////////////////////////////////////////////////////
-
-#if !LL_WINDOWS
-
-// This is really close to, but not quite a general purpose copy
-// function. It does not really spam enough information, but is useful
-// for this cpp file, because this should never be called in a
-// production environment.
-S32 copy_file(const std::string& from, const std::string& to)
-{
- S32 rv = 0;
- LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/
- LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/
- if(in && out)
- {
- S32 read = 0;
- const S32 COPY_BUFFER_SIZE = 16384;
- U8 buffer[COPY_BUFFER_SIZE];
- while(((read = fread(buffer, 1, sizeof(buffer), in)) > 0)
- && (fwrite(buffer, 1, read, out) == (U32)read)); /* Flawfinder : ignore */
- if(ferror(in) || ferror(out)) rv = -2;
- }
- else
- {
- rv = -1;
- }
- if(in) fclose(in);
- if(out) fclose(out);
- return rv;
-}
-#endif
-
+/**
+ * @file llxfer_file.cpp
+ * @brief implementation of LLXfer_File class for a single xfer (file)
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#if !LL_WINDOWS
+#include <errno.h>
+#include <unistd.h>
+#endif
+
+#include "llxfer_file.h"
+#include "lluuid.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "llstring.h"
+#include "lldir.h"
+
+// size of chunks read from/written to disk
+const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
+
+// local function to copy a file
+S32 copy_file(const std::string& from, const std::string& to);
+
+///////////////////////////////////////////////////////////
+
+LLXfer_File::LLXfer_File (S32 chunk_size)
+: LLXfer(chunk_size)
+{
+ init(LLStringUtil::null, false, chunk_size);
+}
+
+LLXfer_File::LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
+: LLXfer(chunk_size)
+{
+ init(local_filename, delete_local_on_completion, chunk_size);
+}
+
+///////////////////////////////////////////////////////////
+
+LLXfer_File::~LLXfer_File ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_File::init (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size)
+{
+
+ mFp = NULL;
+ mLocalFilename.clear();
+ mRemoteFilename.clear();
+ mRemotePath = LL_PATH_NONE;
+ mTempFilename.clear();
+ mDeleteLocalOnCompletion = false;
+ mDeleteRemoteOnCompletion = false;
+
+ if (!local_filename.empty())
+ {
+ mLocalFilename = local_filename.substr(0,LL_MAX_PATH-1);
+
+ // You can only automatically delete .tmp file as a safeguard against nasty messages.
+ std::string exten = mLocalFilename.substr(mLocalFilename.length()-4, 4);
+ mDeleteLocalOnCompletion = (delete_local_on_completion && exten == ".tmp");
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_File::cleanup ()
+{
+ if (mFp)
+ {
+ fclose(mFp);
+ mFp = NULL;
+ }
+
+ LLFile::remove(mTempFilename, ENOENT);
+
+ if (mDeleteLocalOnCompletion)
+ {
+ LL_DEBUGS("Xfer") << "Removing file: " << mLocalFilename << LL_ENDL;
+ LLFile::remove(mLocalFilename, ENOENT);
+ }
+ else
+ {
+ LL_DEBUGS("Xfer") << "Keeping local file: " << mLocalFilename << LL_ENDL;
+ }
+
+ LLXfer::cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::initializeRequest(U64 xfer_id,
+ const std::string& local_filename,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void**,S32,LLExtStat),
+ void** user_data)
+{
+ S32 retval = 0; // presume success
+
+ mID = xfer_id;
+ mLocalFilename = local_filename;
+ mRemoteFilename = remote_filename;
+ mRemotePath = remote_path;
+ mRemoteHost = remote_host;
+ mDeleteRemoteOnCompletion = delete_remote_on_completion;
+
+ mTempFilename = gDirUtilp->getTempFilename();
+
+ mCallback = callback;
+ mCallbackDataHandle = user_data;
+ mCallbackResult = LL_ERR_NOERR;
+
+ LL_INFOS("Xfer") << "Requesting xfer from " << remote_host << " for file: " << mLocalFilename << LL_ENDL;
+
+ if (mBuffer)
+ {
+ delete(mBuffer);
+ mBuffer = NULL;
+ }
+
+ mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
+ mBufferLength = 0;
+
+ mPacketNum = 0;
+
+ mStatus = e_LL_XFER_PENDING;
+ return retval;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::startDownload()
+{
+ S32 retval = 0; // presume success
+ mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */
+ if (mFp)
+ {
+ fclose(mFp);
+ mFp = NULL;
+
+ // tbd - is it premature to send this message if the queue is backed up?
+ gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
+ gMessageSystem->nextBlockFast(_PREHASH_XferID);
+ gMessageSystem->addU64Fast(_PREHASH_ID, mID);
+ gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
+ gMessageSystem->addU8("FilePath", (U8) mRemotePath);
+ gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
+ gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
+ gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
+ gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
+
+ gMessageSystem->sendReliable(mRemoteHost);
+ mStatus = e_LL_XFER_IN_PROGRESS;
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "Couldn't create file to be received!" << LL_ENDL;
+ retval = -1;
+ }
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host)
+{
+ S32 retval = LL_ERR_NOERR; // presume success
+
+ mRemoteHost = remote_host;
+ mID = xfer_id;
+ mPacketNum = -1;
+
+// cout << "Sending file: " << mLocalFilename << endl;
+
+ delete [] mBuffer;
+ mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
+
+ mBufferLength = 0;
+ mBufferStartOffset = 0;
+
+ // We leave the file open, assuming we'll start reading and sending soon
+ mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
+ if (mFp)
+ {
+ fseek(mFp,0,SEEK_END);
+
+ S32 file_size = ftell(mFp);
+ if (file_size <= 0)
+ {
+ return LL_ERR_FILE_EMPTY;
+ }
+ setXferSize(file_size);
+
+ fseek(mFp,0,SEEK_SET);
+ }
+ else
+ {
+ LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found." << LL_ENDL;
+ return (LL_ERR_FILE_NOT_FOUND);
+ }
+
+ mStatus = e_LL_XFER_PENDING;
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+void LLXfer_File::closeFileHandle()
+{
+ if (mFp)
+ {
+ fclose(mFp);
+ mFp = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::reopenFileHandle()
+{
+ S32 retval = LL_ERR_NOERR; // presume success
+
+ if (mFp == NULL)
+ {
+ mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
+ if (mFp == NULL)
+ {
+ LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL;
+ retval = LL_ERR_FILE_NOT_FOUND;
+ }
+ }
+
+ return retval;
+}
+
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::getMaxBufferSize ()
+{
+ return(LL_MAX_XFER_FILE_BUFFER);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::suck(S32 start_position)
+{
+ S32 retval = 0;
+
+ if (mFp)
+ {
+ // grab a buffer from the right place in the file
+ fseek (mFp,start_position,SEEK_SET);
+
+ mBufferLength = (U32)fread(mBuffer,1,LL_MAX_XFER_FILE_BUFFER,mFp);
+ mBufferStartOffset = start_position;
+
+ if (feof(mFp))
+ {
+ mBufferContainsEOF = true;
+ }
+ else
+ {
+ mBufferContainsEOF = false;
+ }
+ }
+ else
+ {
+ retval = -1;
+ }
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::flush()
+{
+ S32 retval = 0;
+ if (mBufferLength)
+ {
+ if (mFp)
+ {
+ LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL;
+ }
+ mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */
+
+ if (mFp)
+ {
+ S32 write_size = fwrite(mBuffer,1,mBufferLength,mFp);
+ if (write_size != mBufferLength)
+ {
+ LL_WARNS("Xfer") << "Non-matching write size, requested " << mBufferLength
+ << " but wrote " << write_size
+ << LL_ENDL;
+ }
+
+// LL_INFOS("Xfer") << "******* wrote " << mBufferLength << " bytes of file xfer" << LL_ENDL;
+ fclose(mFp);
+ mFp = NULL;
+
+ mBufferLength = 0;
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXfer_File::flush() unable to open " << mTempFilename << " for writing!" << LL_ENDL;
+ retval = LL_ERR_CANNOT_OPEN_FILE;
+ }
+ }
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_File::processEOF()
+{
+ S32 retval = 0;
+ mStatus = e_LL_XFER_COMPLETE;
+
+ S32 flushval = flush();
+
+ // If we have no other errors, our error becomes the error generated by
+ // flush.
+ if (!mCallbackResult)
+ {
+ mCallbackResult = flushval;
+ }
+
+ LLFile::remove(mLocalFilename, ENOENT);
+
+ if (!mCallbackResult)
+ {
+ if (LLFile::rename(mTempFilename,mLocalFilename))
+ {
+#if !LL_WINDOWS
+ S32 error_number = errno;
+ LL_INFOS("Xfer") << "Rename failure (" << error_number << ") - "
+ << mTempFilename << " to " << mLocalFilename << LL_ENDL;
+ if(EXDEV == error_number)
+ {
+ if(copy_file(mTempFilename, mLocalFilename) == 0)
+ {
+ LL_INFOS("Xfer") << "Rename across mounts; copying+unlinking the file instead." << LL_ENDL;
+ unlink(mTempFilename.c_str());
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "Copy failure - " << mTempFilename << " to "
+ << mLocalFilename << LL_ENDL;
+ }
+ }
+ else
+ {
+ //LLFILE* fp = LLFile::fopen(mTempFilename, "r");
+ //LL_WARNS() << "File " << mTempFilename << " does "
+ // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
+ //if(fp) fclose(fp);
+ //fp = LLFile::fopen(mLocalFilename, "r");
+ //LL_WARNS() << "File " << mLocalFilename << " does "
+ // << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
+ //if(fp) fclose(fp);
+ LL_WARNS("Xfer") << "Rename fatally failed, can only handle EXDEV ("
+ << EXDEV << ")" << LL_ENDL;
+ }
+#else
+ LL_WARNS("Xfer") << "Rename failure - " << mTempFilename << " to "
+ << mLocalFilename << LL_ENDL;
+#endif
+ }
+ }
+
+ if (mFp)
+ {
+ fclose(mFp);
+ mFp = NULL;
+ }
+
+ retval = LLXfer::processEOF();
+
+ return(retval);
+}
+
+///////////////////////////////////////////////////////////
+
+bool LLXfer_File::matchesLocalFilename(const std::string& filename)
+{
+ return (filename == mLocalFilename);
+}
+
+///////////////////////////////////////////////////////////
+
+bool LLXfer_File::matchesRemoteFilename(const std::string& filename, ELLPath remote_path)
+{
+ return ((filename == mRemoteFilename) && (remote_path == mRemotePath));
+}
+
+
+///////////////////////////////////////////////////////////
+
+std::string LLXfer_File::getFileName()
+{
+ return mLocalFilename;
+}
+
+///////////////////////////////////////////////////////////
+
+// hacky - doesn't matter what this is
+// as long as it's different from the other classes
+U32 LLXfer_File::getXferTypeTag()
+{
+ return LLXfer::XFER_FILE;
+}
+
+///////////////////////////////////////////////////////////
+
+#if !LL_WINDOWS
+
+// This is really close to, but not quite a general purpose copy
+// function. It does not really spam enough information, but is useful
+// for this cpp file, because this should never be called in a
+// production environment.
+S32 copy_file(const std::string& from, const std::string& to)
+{
+ S32 rv = 0;
+ LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/
+ LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/
+ if(in && out)
+ {
+ S32 read = 0;
+ const S32 COPY_BUFFER_SIZE = 16384;
+ U8 buffer[COPY_BUFFER_SIZE];
+ while(((read = fread(buffer, 1, sizeof(buffer), in)) > 0)
+ && (fwrite(buffer, 1, read, out) == (U32)read)); /* Flawfinder : ignore */
+ if(ferror(in) || ferror(out)) rv = -2;
+ }
+ else
+ {
+ rv = -1;
+ }
+ if(in) fclose(in);
+ if(out) fclose(out);
+ return rv;
+}
+#endif
+
diff --git a/indra/llmessage/llxfer_file.h b/indra/llmessage/llxfer_file.h
index 24bfd993bd..baf57753ae 100644
--- a/indra/llmessage/llxfer_file.h
+++ b/indra/llmessage/llxfer_file.h
@@ -1,87 +1,87 @@
-/**
- * @file llxfer_file.h
- * @brief definition of LLXfer_File class for a single xfer_file.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLXFER_FILE_H
-#define LL_LLXFER_FILE_H
-
-#include "llxfer.h"
-#include "lldir.h"
-
-class LLXfer_File : public LLXfer
-{
- protected:
- LLFILE *mFp;
- std::string mLocalFilename;
- std::string mRemoteFilename;
- ELLPath mRemotePath;
- std::string mTempFilename;
-
- bool mDeleteLocalOnCompletion;
- bool mDeleteRemoteOnCompletion;
-
- public:
- LLXfer_File (S32 chunk_size);
- LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size);
- virtual ~LLXfer_File();
-
- virtual void init(const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size);
- virtual void cleanup();
-
- virtual S32 initializeRequest(U64 xfer_id,
- const std::string& local_filename,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data);
- virtual S32 startDownload();
-
- virtual S32 processEOF();
-
- virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
- virtual void closeFileHandle();
- virtual S32 reopenFileHandle();
-
- virtual S32 suck(S32 start_position);
- virtual S32 flush();
-
- virtual bool matchesLocalFilename(const std::string& filename);
- virtual bool matchesRemoteFilename(const std::string& filename, ELLPath remote_path);
-
- virtual S32 getMaxBufferSize();
-
- virtual U32 getXferTypeTag();
-
- virtual std::string getFileName();
-};
-
-#endif
-
-
-
-
-
+/**
+ * @file llxfer_file.h
+ * @brief definition of LLXfer_File class for a single xfer_file.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLXFER_FILE_H
+#define LL_LLXFER_FILE_H
+
+#include "llxfer.h"
+#include "lldir.h"
+
+class LLXfer_File : public LLXfer
+{
+ protected:
+ LLFILE *mFp;
+ std::string mLocalFilename;
+ std::string mRemoteFilename;
+ ELLPath mRemotePath;
+ std::string mTempFilename;
+
+ bool mDeleteLocalOnCompletion;
+ bool mDeleteRemoteOnCompletion;
+
+ public:
+ LLXfer_File (S32 chunk_size);
+ LLXfer_File (const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size);
+ virtual ~LLXfer_File();
+
+ virtual void init(const std::string& local_filename, bool delete_local_on_completion, S32 chunk_size);
+ virtual void cleanup();
+
+ virtual S32 initializeRequest(U64 xfer_id,
+ const std::string& local_filename,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void**,S32,LLExtStat),
+ void** user_data);
+ virtual S32 startDownload();
+
+ virtual S32 processEOF();
+
+ virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
+ virtual void closeFileHandle();
+ virtual S32 reopenFileHandle();
+
+ virtual S32 suck(S32 start_position);
+ virtual S32 flush();
+
+ virtual bool matchesLocalFilename(const std::string& filename);
+ virtual bool matchesRemoteFilename(const std::string& filename, ELLPath remote_path);
+
+ virtual S32 getMaxBufferSize();
+
+ virtual U32 getXferTypeTag();
+
+ virtual std::string getFileName();
+};
+
+#endif
+
+
+
+
+
diff --git a/indra/llmessage/llxfer_mem.cpp b/indra/llmessage/llxfer_mem.cpp
index 42afaad93b..825bff3820 100644
--- a/indra/llmessage/llxfer_mem.cpp
+++ b/indra/llmessage/llxfer_mem.cpp
@@ -1,196 +1,196 @@
-/**
- * @file llxfer_mem.cpp
- * @brief implementation of LLXfer_Mem class for a single xfer
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llxfer_mem.h"
-#include "lluuid.h"
-#include "llerror.h"
-#include "llmath.h"
-
-///////////////////////////////////////////////////////////
-
-LLXfer_Mem::LLXfer_Mem ()
-: LLXfer(-1)
-{
- init();
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer_Mem::~LLXfer_Mem ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_Mem::init ()
-{
- mRemoteFilename.clear();
- mRemotePath = LL_PATH_NONE;
- mDeleteRemoteOnCompletion = false;
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_Mem::cleanup ()
-{
- LLXfer::cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_Mem::setXferSize (S32 xfer_size)
-{
- mXferSize = xfer_size;
-
- delete[] mBuffer;
- mBuffer = new char[xfer_size];
-
- mBufferLength = 0;
- mBufferStartOffset = 0;
- mBufferContainsEOF = true;
-
-// cout << "starting transfer of size: " << xfer_size << endl;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_Mem::startSend (U64 xfer_id, const LLHost &remote_host)
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- if (mXferSize <= 0)
- {
- return LL_ERR_FILE_EMPTY;
- }
-
- mRemoteHost = remote_host;
- mID = xfer_id;
- mPacketNum = -1;
-
-// cout << "Sending file: " << getFileName() << endl;
-
- mStatus = e_LL_XFER_PENDING;
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_Mem::processEOF()
-{
- S32 retval = 0;
-
- mStatus = e_LL_XFER_COMPLETE;
-
- LL_INFOS() << "xfer complete: " << getFileName() << LL_ENDL;
-
- if (mCallback)
- {
- mCallback((void *)mBuffer,mBufferLength,mCallbackDataHandle,mCallbackResult, LLExtStat::NONE);
- }
-
- return(retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_Mem::initializeRequest(U64 xfer_id,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void*,S32,void**,S32,LLExtStat),
- void** user_data)
-{
- S32 retval = 0; // presume success
-
- mRemoteHost = remote_host;
-
- // create a temp filename string using a GUID
- mID = xfer_id;
- mCallback = callback;
- mCallbackDataHandle = user_data;
- mCallbackResult = LL_ERR_NOERR;
-
- mRemoteFilename = remote_filename;
- mRemotePath = remote_path;
- mDeleteRemoteOnCompletion = delete_remote_on_completion;
-
- LL_INFOS() << "Requesting file: " << remote_filename << LL_ENDL;
-
- delete [] mBuffer;
- mBuffer = NULL;
-
- mBufferLength = 0;
- mPacketNum = 0;
- mStatus = e_LL_XFER_PENDING;
- return retval;
-}
-
-//////////////////////////////////////////////////////////
-
-S32 LLXfer_Mem::startDownload()
-{
- S32 retval = 0; // presume success
- gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
- gMessageSystem->addU8("FilePath", (U8) mRemotePath);
- gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
- gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
- gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
- gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
-
- gMessageSystem->sendReliable(mRemoteHost);
- mStatus = e_LL_XFER_IN_PROGRESS;
-
- return (retval);
-}
-
-//////////////////////////////////////////////////////////
-
-U32 LLXfer_Mem::getXferTypeTag()
-{
- return LLXfer::XFER_MEM;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+/**
+ * @file llxfer_mem.cpp
+ * @brief implementation of LLXfer_Mem class for a single xfer
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxfer_mem.h"
+#include "lluuid.h"
+#include "llerror.h"
+#include "llmath.h"
+
+///////////////////////////////////////////////////////////
+
+LLXfer_Mem::LLXfer_Mem ()
+: LLXfer(-1)
+{
+ init();
+}
+
+///////////////////////////////////////////////////////////
+
+LLXfer_Mem::~LLXfer_Mem ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_Mem::init ()
+{
+ mRemoteFilename.clear();
+ mRemotePath = LL_PATH_NONE;
+ mDeleteRemoteOnCompletion = false;
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_Mem::cleanup ()
+{
+ LLXfer::cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_Mem::setXferSize (S32 xfer_size)
+{
+ mXferSize = xfer_size;
+
+ delete[] mBuffer;
+ mBuffer = new char[xfer_size];
+
+ mBufferLength = 0;
+ mBufferStartOffset = 0;
+ mBufferContainsEOF = true;
+
+// cout << "starting transfer of size: " << xfer_size << endl;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_Mem::startSend (U64 xfer_id, const LLHost &remote_host)
+{
+ S32 retval = LL_ERR_NOERR; // presume success
+
+ if (mXferSize <= 0)
+ {
+ return LL_ERR_FILE_EMPTY;
+ }
+
+ mRemoteHost = remote_host;
+ mID = xfer_id;
+ mPacketNum = -1;
+
+// cout << "Sending file: " << getFileName() << endl;
+
+ mStatus = e_LL_XFER_PENDING;
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_Mem::processEOF()
+{
+ S32 retval = 0;
+
+ mStatus = e_LL_XFER_COMPLETE;
+
+ LL_INFOS() << "xfer complete: " << getFileName() << LL_ENDL;
+
+ if (mCallback)
+ {
+ mCallback((void *)mBuffer,mBufferLength,mCallbackDataHandle,mCallbackResult, LLExtStat::NONE);
+ }
+
+ return(retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_Mem::initializeRequest(U64 xfer_id,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void*,S32,void**,S32,LLExtStat),
+ void** user_data)
+{
+ S32 retval = 0; // presume success
+
+ mRemoteHost = remote_host;
+
+ // create a temp filename string using a GUID
+ mID = xfer_id;
+ mCallback = callback;
+ mCallbackDataHandle = user_data;
+ mCallbackResult = LL_ERR_NOERR;
+
+ mRemoteFilename = remote_filename;
+ mRemotePath = remote_path;
+ mDeleteRemoteOnCompletion = delete_remote_on_completion;
+
+ LL_INFOS() << "Requesting file: " << remote_filename << LL_ENDL;
+
+ delete [] mBuffer;
+ mBuffer = NULL;
+
+ mBufferLength = 0;
+ mPacketNum = 0;
+ mStatus = e_LL_XFER_PENDING;
+ return retval;
+}
+
+//////////////////////////////////////////////////////////
+
+S32 LLXfer_Mem::startDownload()
+{
+ S32 retval = 0; // presume success
+ gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
+ gMessageSystem->nextBlockFast(_PREHASH_XferID);
+ gMessageSystem->addU64Fast(_PREHASH_ID, mID);
+ gMessageSystem->addStringFast(_PREHASH_Filename, mRemoteFilename);
+ gMessageSystem->addU8("FilePath", (U8) mRemotePath);
+ gMessageSystem->addBOOL("DeleteOnCompletion", mDeleteRemoteOnCompletion);
+ gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
+ gMessageSystem->addUUIDFast(_PREHASH_VFileID, LLUUID::null);
+ gMessageSystem->addS16Fast(_PREHASH_VFileType, -1);
+
+ gMessageSystem->sendReliable(mRemoteHost);
+ mStatus = e_LL_XFER_IN_PROGRESS;
+
+ return (retval);
+}
+
+//////////////////////////////////////////////////////////
+
+U32 LLXfer_Mem::getXferTypeTag()
+{
+ return LLXfer::XFER_MEM;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/indra/llmessage/llxfer_mem.h b/indra/llmessage/llxfer_mem.h
index 25bd363235..49c3e8d20d 100644
--- a/indra/llmessage/llxfer_mem.h
+++ b/indra/llmessage/llxfer_mem.h
@@ -1,77 +1,77 @@
-/**
- * @file llxfer_mem.h
- * @brief definition of LLXfer_Mem class for a single xfer
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLXFER_MEM_H
-#define LL_LLXFER_MEM_H
-
-#include "message.h"
-#include "lltimer.h"
-#include "llxfer.h"
-#include "lldir.h"
-
-class LLXfer_Mem : public LLXfer
-{
- private:
- protected:
- void (*mCallback)(void *, S32, void **, S32, LLExtStat);
- std::string mRemoteFilename;
- ELLPath mRemotePath;
- bool mDeleteRemoteOnCompletion;
-
- public:
-
- private:
- protected:
- public:
- LLXfer_Mem ();
- virtual ~LLXfer_Mem();
-
- virtual void init();
- virtual void cleanup();
-
- virtual S32 startSend (U64 xfer_id, const LLHost &remote_host);
- virtual void setXferSize (S32 data_size);
-
- virtual S32 initializeRequest(U64 xfer_id,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void*,S32,void**,S32,LLExtStat),
- void** user_data);
- virtual S32 startDownload();
-
- virtual S32 processEOF();
-
- virtual U32 getXferTypeTag();
-};
-
-#endif
-
-
-
-
-
+/**
+ * @file llxfer_mem.h
+ * @brief definition of LLXfer_Mem class for a single xfer
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLXFER_MEM_H
+#define LL_LLXFER_MEM_H
+
+#include "message.h"
+#include "lltimer.h"
+#include "llxfer.h"
+#include "lldir.h"
+
+class LLXfer_Mem : public LLXfer
+{
+ private:
+ protected:
+ void (*mCallback)(void *, S32, void **, S32, LLExtStat);
+ std::string mRemoteFilename;
+ ELLPath mRemotePath;
+ bool mDeleteRemoteOnCompletion;
+
+ public:
+
+ private:
+ protected:
+ public:
+ LLXfer_Mem ();
+ virtual ~LLXfer_Mem();
+
+ virtual void init();
+ virtual void cleanup();
+
+ virtual S32 startSend (U64 xfer_id, const LLHost &remote_host);
+ virtual void setXferSize (S32 data_size);
+
+ virtual S32 initializeRequest(U64 xfer_id,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void*,S32,void**,S32,LLExtStat),
+ void** user_data);
+ virtual S32 startDownload();
+
+ virtual S32 processEOF();
+
+ virtual U32 getXferTypeTag();
+};
+
+#endif
+
+
+
+
+
diff --git a/indra/llmessage/llxfer_vfile.cpp b/indra/llmessage/llxfer_vfile.cpp
index 3322188694..c37ee1ca2d 100644
--- a/indra/llmessage/llxfer_vfile.cpp
+++ b/indra/llmessage/llxfer_vfile.cpp
@@ -1,397 +1,397 @@
-/**
- * @file llxfer_vfile.cpp
- * @brief implementation of LLXfer_VFile class for a single xfer (vfile).
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llxfer_vfile.h"
-#include "lluuid.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "llfilesystem.h"
-#include "lldir.h"
-
-// size of chunks read from/written to disk
-const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
-
-///////////////////////////////////////////////////////////
-
-LLXfer_VFile::LLXfer_VFile ()
-: LLXfer(-1)
-{
- init(LLUUID::null, LLAssetType::AT_NONE);
-}
-
-LLXfer_VFile::LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type)
-: LLXfer(-1)
-{
- init(local_id, type);
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer_VFile::~LLXfer_VFile ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_VFile::init (const LLUUID &local_id, LLAssetType::EType type)
-{
- mLocalID = local_id;
- mType = type;
-
- mVFile = NULL;
-
- std::string id_string;
- mLocalID.toString(id_string);
-
- mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_VFile::cleanup ()
-{
- if (mTempID.notNull() &&
- mDeleteTempFile)
- {
- if (LLFileSystem::getExists(mTempID, mType))
- {
- LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
- file.remove();
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_VFile::cleanup() can't open to delete cache file " << mTempID << "." << LLAssetType::lookup(mType)
- << ", mRemoteID is " << mRemoteID << LL_ENDL;
- }
- }
-
- delete mVFile;
- mVFile = NULL;
-
- LLXfer::cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
- const LLUUID& local_id,
- const LLUUID& remote_id,
- LLAssetType::EType type,
- const LLHost& remote_host,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data)
-{
- S32 retval = 0; // presume success
-
- mRemoteHost = remote_host;
-
- mLocalID = local_id;
- mRemoteID = remote_id;
- mType = type;
-
- mID = xfer_id;
- mCallback = callback;
- mCallbackDataHandle = user_data;
- mCallbackResult = LL_ERR_NOERR;
-
- std::string id_string;
- mLocalID.toString(id_string);
-
- mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
-
- LL_INFOS("Xfer") << "Requesting " << mName << LL_ENDL;
-
- if (mBuffer)
- {
- delete[] mBuffer;
- mBuffer = NULL;
- }
-
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
-
- mBufferLength = 0;
- mPacketNum = 0;
- mTempID.generate();
- mDeleteTempFile = true;
- mStatus = e_LL_XFER_PENDING;
- return retval;
-}
-
-//////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::startDownload()
-{
- S32 retval = 0; // presume success
-
- // Don't need to create the file here, it will happen when data arrives
-
- gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
- gMessageSystem->nextBlockFast(_PREHASH_XferID);
- gMessageSystem->addU64Fast(_PREHASH_ID, mID);
- gMessageSystem->addStringFast(_PREHASH_Filename, "");
- gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
- gMessageSystem->addBOOL("DeleteOnCompletion", false);
- gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
- gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
- gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
-
- gMessageSystem->sendReliable(mRemoteHost);
- mStatus = e_LL_XFER_IN_PROGRESS;
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- mRemoteHost = remote_host;
- mID = xfer_id;
- mPacketNum = -1;
-
-// cout << "Sending file: " << mLocalFilename << endl;
-
- delete [] mBuffer;
- mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
-
- mBufferLength = 0;
- mBufferStartOffset = 0;
-
- delete mVFile;
- mVFile = NULL;
- if(LLFileSystem::getExists(mLocalID, mType))
- {
- mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
-
- if (mVFile->getSize() <= 0)
- {
- LL_WARNS("Xfer") << "LLXfer_VFile::startSend() cache file " << mLocalID << "." << LLAssetType::lookup(mType)
- << " has unexpected file size of " << mVFile->getSize() << LL_ENDL;
- delete mVFile;
- mVFile = NULL;
-
- return LL_ERR_FILE_EMPTY;
- }
- }
-
- if(mVFile)
- {
- setXferSize(mVFile->getSize());
- mStatus = e_LL_XFER_PENDING;
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
- retval = LL_ERR_FILE_NOT_FOUND;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_VFile::closeFileHandle()
-{
- if (mVFile)
- {
- delete mVFile;
- mVFile = NULL;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::reopenFileHandle()
-{
- S32 retval = LL_ERR_NOERR; // presume success
-
- if (mVFile == NULL)
- {
- if (LLFileSystem::getExists(mLocalID, mType))
- {
- mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
- retval = LL_ERR_FILE_NOT_FOUND;
- }
- }
-
- return retval;
-}
-
-
-///////////////////////////////////////////////////////////
-
-void LLXfer_VFile::setXferSize (S32 xfer_size)
-{
- LLXfer::setXferSize(xfer_size);
-
- // Don't do this on the server side, where we have a persistent mVFile
- // It would be nice if LLXFers could tell which end of the pipe they were
- if (! mVFile)
- {
- LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
- }
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::getMaxBufferSize ()
-{
- return(LL_MAX_XFER_FILE_BUFFER);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::suck(S32 start_position)
-{
- S32 retval = 0;
-
- if (mVFile)
- {
- // grab a buffer from the right place in the file
- if (! mVFile->seek(start_position, 0))
- {
- LL_WARNS("Xfer") << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << LL_ENDL;
- LL_WARNS("Xfer") << "While sending file " << mLocalID << LL_ENDL;
- return -1;
- }
-
- if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER)) /* Flawfinder : ignore */
- {
- mBufferLength = mVFile->getLastBytesRead();
- mBufferStartOffset = start_position;
-
- mBufferContainsEOF = mVFile->eof();
- }
- else
- {
- retval = -1;
- }
- }
- else
- {
- retval = -1;
- }
-
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::flush()
-{
- S32 retval = 0;
- if (mBufferLength)
- {
- LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
-
- file.write((U8*)mBuffer, mBufferLength);
-
- mBufferLength = 0;
- }
- return (retval);
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXfer_VFile::processEOF()
-{
- S32 retval = 0;
- mStatus = e_LL_XFER_COMPLETE;
-
- flush();
-
- if (!mCallbackResult)
- {
- if (LLFileSystem::getExists(mTempID, mType))
- {
- LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
- if (!file.rename(mLocalID, mType))
- {
- LL_WARNS("Xfer") << "Cache rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL;
- }
- else
- {
- // Rename worked: the original file is gone. Clear mDeleteTempFile
- // so we don't attempt to delete the file in cleanup()
- mDeleteTempFile = false;
- }
- }
- else
- {
- LL_WARNS("Xfer") << "LLXfer_VFile::processEOF() can't open for renaming cache file " << mTempID << "." << LLAssetType::lookup(mType) << LL_ENDL;
- }
- }
-
- if (mVFile)
- {
- delete mVFile;
- mVFile = NULL;
- }
-
- retval = LLXfer::processEOF();
-
- return(retval);
-}
-
-////////////////////////////////////////////////////////////
-
-bool LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
-{
- return (id == mLocalID && type == mType);
-}
-
-//////////////////////////////////////////////////////////
-
-bool LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
-{
- return (id == mRemoteID && type == mType);
-}
-
-//////////////////////////////////////////////////////////
-
-std::string LLXfer_VFile::getFileName()
-{
- return mName;
-}
-
-//////////////////////////////////////////////////////////
-
-// hacky - doesn't matter what this is
-// as long as it's different from the other classes
-U32 LLXfer_VFile::getXferTypeTag()
-{
- return LLXfer::XFER_VFILE;
-}
-
+/**
+ * @file llxfer_vfile.cpp
+ * @brief implementation of LLXfer_VFile class for a single xfer (vfile).
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxfer_vfile.h"
+#include "lluuid.h"
+#include "llerror.h"
+#include "llmath.h"
+#include "llfilesystem.h"
+#include "lldir.h"
+
+// size of chunks read from/written to disk
+const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
+
+///////////////////////////////////////////////////////////
+
+LLXfer_VFile::LLXfer_VFile ()
+: LLXfer(-1)
+{
+ init(LLUUID::null, LLAssetType::AT_NONE);
+}
+
+LLXfer_VFile::LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type)
+: LLXfer(-1)
+{
+ init(local_id, type);
+}
+
+///////////////////////////////////////////////////////////
+
+LLXfer_VFile::~LLXfer_VFile ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_VFile::init (const LLUUID &local_id, LLAssetType::EType type)
+{
+ mLocalID = local_id;
+ mType = type;
+
+ mVFile = NULL;
+
+ std::string id_string;
+ mLocalID.toString(id_string);
+
+ mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_VFile::cleanup ()
+{
+ if (mTempID.notNull() &&
+ mDeleteTempFile)
+ {
+ if (LLFileSystem::getExists(mTempID, mType))
+ {
+ LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
+ file.remove();
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXfer_VFile::cleanup() can't open to delete cache file " << mTempID << "." << LLAssetType::lookup(mType)
+ << ", mRemoteID is " << mRemoteID << LL_ENDL;
+ }
+ }
+
+ delete mVFile;
+ mVFile = NULL;
+
+ LLXfer::cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
+ const LLUUID& local_id,
+ const LLUUID& remote_id,
+ LLAssetType::EType type,
+ const LLHost& remote_host,
+ void (*callback)(void**,S32,LLExtStat),
+ void** user_data)
+{
+ S32 retval = 0; // presume success
+
+ mRemoteHost = remote_host;
+
+ mLocalID = local_id;
+ mRemoteID = remote_id;
+ mType = type;
+
+ mID = xfer_id;
+ mCallback = callback;
+ mCallbackDataHandle = user_data;
+ mCallbackResult = LL_ERR_NOERR;
+
+ std::string id_string;
+ mLocalID.toString(id_string);
+
+ mName = llformat("VFile %s:%s", id_string.c_str(), LLAssetType::lookup(mType));
+
+ LL_INFOS("Xfer") << "Requesting " << mName << LL_ENDL;
+
+ if (mBuffer)
+ {
+ delete[] mBuffer;
+ mBuffer = NULL;
+ }
+
+ mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
+
+ mBufferLength = 0;
+ mPacketNum = 0;
+ mTempID.generate();
+ mDeleteTempFile = true;
+ mStatus = e_LL_XFER_PENDING;
+ return retval;
+}
+
+//////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::startDownload()
+{
+ S32 retval = 0; // presume success
+
+ // Don't need to create the file here, it will happen when data arrives
+
+ gMessageSystem->newMessageFast(_PREHASH_RequestXfer);
+ gMessageSystem->nextBlockFast(_PREHASH_XferID);
+ gMessageSystem->addU64Fast(_PREHASH_ID, mID);
+ gMessageSystem->addStringFast(_PREHASH_Filename, "");
+ gMessageSystem->addU8("FilePath", (U8) LL_PATH_NONE);
+ gMessageSystem->addBOOL("DeleteOnCompletion", false);
+ gMessageSystem->addBOOL("UseBigPackets", mChunkSize == LL_XFER_LARGE_PAYLOAD);
+ gMessageSystem->addUUIDFast(_PREHASH_VFileID, mRemoteID);
+ gMessageSystem->addS16Fast(_PREHASH_VFileType, (S16)mType);
+
+ gMessageSystem->sendReliable(mRemoteHost);
+ mStatus = e_LL_XFER_IN_PROGRESS;
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
+{
+ S32 retval = LL_ERR_NOERR; // presume success
+
+ mRemoteHost = remote_host;
+ mID = xfer_id;
+ mPacketNum = -1;
+
+// cout << "Sending file: " << mLocalFilename << endl;
+
+ delete [] mBuffer;
+ mBuffer = new char[LL_MAX_XFER_FILE_BUFFER];
+
+ mBufferLength = 0;
+ mBufferStartOffset = 0;
+
+ delete mVFile;
+ mVFile = NULL;
+ if(LLFileSystem::getExists(mLocalID, mType))
+ {
+ mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
+
+ if (mVFile->getSize() <= 0)
+ {
+ LL_WARNS("Xfer") << "LLXfer_VFile::startSend() cache file " << mLocalID << "." << LLAssetType::lookup(mType)
+ << " has unexpected file size of " << mVFile->getSize() << LL_ENDL;
+ delete mVFile;
+ mVFile = NULL;
+
+ return LL_ERR_FILE_EMPTY;
+ }
+ }
+
+ if(mVFile)
+ {
+ setXferSize(mVFile->getSize());
+ mStatus = e_LL_XFER_PENDING;
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
+ retval = LL_ERR_FILE_NOT_FOUND;
+ }
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_VFile::closeFileHandle()
+{
+ if (mVFile)
+ {
+ delete mVFile;
+ mVFile = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::reopenFileHandle()
+{
+ S32 retval = LL_ERR_NOERR; // presume success
+
+ if (mVFile == NULL)
+ {
+ if (LLFileSystem::getExists(mLocalID, mType))
+ {
+ mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
+ retval = LL_ERR_FILE_NOT_FOUND;
+ }
+ }
+
+ return retval;
+}
+
+
+///////////////////////////////////////////////////////////
+
+void LLXfer_VFile::setXferSize (S32 xfer_size)
+{
+ LLXfer::setXferSize(xfer_size);
+
+ // Don't do this on the server side, where we have a persistent mVFile
+ // It would be nice if LLXFers could tell which end of the pipe they were
+ if (! mVFile)
+ {
+ LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::getMaxBufferSize ()
+{
+ return(LL_MAX_XFER_FILE_BUFFER);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::suck(S32 start_position)
+{
+ S32 retval = 0;
+
+ if (mVFile)
+ {
+ // grab a buffer from the right place in the file
+ if (! mVFile->seek(start_position, 0))
+ {
+ LL_WARNS("Xfer") << "VFile Xfer Can't seek to position " << start_position << ", file length " << mVFile->getSize() << LL_ENDL;
+ LL_WARNS("Xfer") << "While sending file " << mLocalID << LL_ENDL;
+ return -1;
+ }
+
+ if (mVFile->read((U8*)mBuffer, LL_MAX_XFER_FILE_BUFFER)) /* Flawfinder : ignore */
+ {
+ mBufferLength = mVFile->getLastBytesRead();
+ mBufferStartOffset = start_position;
+
+ mBufferContainsEOF = mVFile->eof();
+ }
+ else
+ {
+ retval = -1;
+ }
+ }
+ else
+ {
+ retval = -1;
+ }
+
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::flush()
+{
+ S32 retval = 0;
+ if (mBufferLength)
+ {
+ LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
+
+ file.write((U8*)mBuffer, mBufferLength);
+
+ mBufferLength = 0;
+ }
+ return (retval);
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXfer_VFile::processEOF()
+{
+ S32 retval = 0;
+ mStatus = e_LL_XFER_COMPLETE;
+
+ flush();
+
+ if (!mCallbackResult)
+ {
+ if (LLFileSystem::getExists(mTempID, mType))
+ {
+ LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
+ if (!file.rename(mLocalID, mType))
+ {
+ LL_WARNS("Xfer") << "Cache rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL;
+ }
+ else
+ {
+ // Rename worked: the original file is gone. Clear mDeleteTempFile
+ // so we don't attempt to delete the file in cleanup()
+ mDeleteTempFile = false;
+ }
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXfer_VFile::processEOF() can't open for renaming cache file " << mTempID << "." << LLAssetType::lookup(mType) << LL_ENDL;
+ }
+ }
+
+ if (mVFile)
+ {
+ delete mVFile;
+ mVFile = NULL;
+ }
+
+ retval = LLXfer::processEOF();
+
+ return(retval);
+}
+
+////////////////////////////////////////////////////////////
+
+bool LLXfer_VFile::matchesLocalFile(const LLUUID &id, LLAssetType::EType type)
+{
+ return (id == mLocalID && type == mType);
+}
+
+//////////////////////////////////////////////////////////
+
+bool LLXfer_VFile::matchesRemoteFile(const LLUUID &id, LLAssetType::EType type)
+{
+ return (id == mRemoteID && type == mType);
+}
+
+//////////////////////////////////////////////////////////
+
+std::string LLXfer_VFile::getFileName()
+{
+ return mName;
+}
+
+//////////////////////////////////////////////////////////
+
+// hacky - doesn't matter what this is
+// as long as it's different from the other classes
+U32 LLXfer_VFile::getXferTypeTag()
+{
+ return LLXfer::XFER_VFILE;
+}
+
diff --git a/indra/llmessage/llxfer_vfile.h b/indra/llmessage/llxfer_vfile.h
index 032c5e2533..33fb63f68c 100644
--- a/indra/llmessage/llxfer_vfile.h
+++ b/indra/llmessage/llxfer_vfile.h
@@ -1,91 +1,91 @@
-/**
- * @file llxfer_vfile.h
- * @brief definition of LLXfer_VFile class for a single xfer_vfile.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLXFER_VFILE_H
-#define LL_LLXFER_VFILE_H
-
-#include "llxfer.h"
-#include "llassetstorage.h"
-
-class LLFileSystem;
-
-class LLXfer_VFile : public LLXfer
-{
- protected:
- LLUUID mLocalID;
- LLUUID mRemoteID;
- LLUUID mTempID;
- LLAssetType::EType mType;
-
- LLFileSystem *mVFile;
-
- std::string mName;
-
- bool mDeleteTempFile;
-
- public:
- LLXfer_VFile ();
- LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type);
- virtual ~LLXfer_VFile();
-
- virtual void init(const LLUUID &local_id, LLAssetType::EType type);
- virtual void cleanup();
-
- virtual S32 initializeRequest(U64 xfer_id,
- const LLUUID &local_id,
- const LLUUID &remote_id,
- const LLAssetType::EType type,
- const LLHost &remote_host,
- void (*callback)(void **,S32,LLExtStat),
- void **user_data);
- virtual S32 startDownload();
-
- virtual S32 processEOF();
-
- virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
- virtual void closeFileHandle();
- virtual S32 reopenFileHandle();
-
- virtual S32 suck(S32 start_position);
- virtual S32 flush();
-
- virtual bool matchesLocalFile(const LLUUID &id, LLAssetType::EType type);
- virtual bool matchesRemoteFile(const LLUUID &id, LLAssetType::EType type);
-
- virtual void setXferSize(S32 xfer_size);
- virtual S32 getMaxBufferSize();
-
- virtual U32 getXferTypeTag();
-
- virtual std::string getFileName();
-};
-
-#endif
-
-
-
-
-
+/**
+ * @file llxfer_vfile.h
+ * @brief definition of LLXfer_VFile class for a single xfer_vfile.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLXFER_VFILE_H
+#define LL_LLXFER_VFILE_H
+
+#include "llxfer.h"
+#include "llassetstorage.h"
+
+class LLFileSystem;
+
+class LLXfer_VFile : public LLXfer
+{
+ protected:
+ LLUUID mLocalID;
+ LLUUID mRemoteID;
+ LLUUID mTempID;
+ LLAssetType::EType mType;
+
+ LLFileSystem *mVFile;
+
+ std::string mName;
+
+ bool mDeleteTempFile;
+
+ public:
+ LLXfer_VFile ();
+ LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type);
+ virtual ~LLXfer_VFile();
+
+ virtual void init(const LLUUID &local_id, LLAssetType::EType type);
+ virtual void cleanup();
+
+ virtual S32 initializeRequest(U64 xfer_id,
+ const LLUUID &local_id,
+ const LLUUID &remote_id,
+ const LLAssetType::EType type,
+ const LLHost &remote_host,
+ void (*callback)(void **,S32,LLExtStat),
+ void **user_data);
+ virtual S32 startDownload();
+
+ virtual S32 processEOF();
+
+ virtual S32 startSend(U64 xfer_id, const LLHost &remote_host);
+ virtual void closeFileHandle();
+ virtual S32 reopenFileHandle();
+
+ virtual S32 suck(S32 start_position);
+ virtual S32 flush();
+
+ virtual bool matchesLocalFile(const LLUUID &id, LLAssetType::EType type);
+ virtual bool matchesRemoteFile(const LLUUID &id, LLAssetType::EType type);
+
+ virtual void setXferSize(S32 xfer_size);
+ virtual S32 getMaxBufferSize();
+
+ virtual U32 getXferTypeTag();
+
+ virtual std::string getFileName();
+};
+
+#endif
+
+
+
+
+
diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp
index 6187d439d9..d4d12b8ff2 100644
--- a/indra/llmessage/llxfermanager.cpp
+++ b/indra/llmessage/llxfermanager.cpp
@@ -1,1326 +1,1326 @@
-/**
- * @file llxfermanager.cpp
- * @brief implementation of LLXferManager class for a collection of xfers
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llxfermanager.h"
-
-#include "llxfer.h"
-#include "llxfer_file.h"
-#include "llxfer_mem.h"
-#include "llxfer_vfile.h"
-
-#include "llerror.h"
-#include "lluuid.h"
-#include "u64.h"
-
-const F32 LL_XFER_REGISTRATION_TIMEOUT = 60.0f; // timeout if a registered transfer hasn't been requested in 60 seconds
-const F32 LL_PACKET_TIMEOUT = 3.0f; // packet timeout at 3 s
-const S32 LL_PACKET_RETRY_LIMIT = 10; // packet retransmission limit
-
-const S32 LL_DEFAULT_MAX_SIMULTANEOUS_XFERS = 10;
-const S32 LL_DEFAULT_MAX_REQUEST_FIFO_XFERS = 1000;
-
-// Kills the connection if a viewer download queue hits this many requests backed up
-// Also set in simulator.xml at "hard_limit_outgoing_xfers_per_circuit"
-const S32 LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS = 500;
-
-// Use this to show sending some ConfirmXferPacket messages
-//#define LL_XFER_PROGRESS_MESSAGES 1
-
-// Use this for lots of diagnostic spam
-//#define LL_XFER_DIAGNOISTIC_LOGGING 1
-
-///////////////////////////////////////////////////////////
-
-LLXferManager::LLXferManager ()
-{
- init();
-}
-
-///////////////////////////////////////////////////////////
-
-LLXferManager::~LLXferManager ()
-{
- cleanup();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::init()
-{
- cleanup();
-
- setMaxOutgoingXfersPerCircuit(LL_DEFAULT_MAX_SIMULTANEOUS_XFERS);
- setHardLimitOutgoingXfersPerCircuit(LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS);
- setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS);
-
- // Turn on or off ack throttling
- mUseAckThrottling = false;
- setAckThrottleBPS(100000);
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::cleanup ()
-{
- for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
- mOutgoingHosts.clear();
-
- for_each(mSendList.begin(), mSendList.end(), DeletePointer());
- mSendList.clear();
-
- for_each(mReceiveList.begin(), mReceiveList.end(), DeletePointer());
- mReceiveList.clear();
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::setMaxIncomingXfers(S32 max_num)
-{
- mMaxIncomingXfers = max_num;
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::setMaxOutgoingXfersPerCircuit(S32 max_num)
-{
- mMaxOutgoingXfersPerCircuit = max_num;
-}
-
-void LLXferManager::setHardLimitOutgoingXfersPerCircuit(S32 max_num)
-{
- mHardLimitOutgoingXfersPerCircuit = max_num;
-}
-
-void LLXferManager::setUseAckThrottling(const bool use)
-{
- mUseAckThrottling = use;
-}
-
-void LLXferManager::setAckThrottleBPS(const F32 bps)
-{
- // Let's figure out the min we can set based on the ack retry rate
- // and number of simultaneous.
-
- // Assuming we're running as slow as possible, this is the lowest ack
- // rate we can use.
- F32 min_bps = (1000.f * 8.f* mMaxIncomingXfers) / LL_PACKET_TIMEOUT;
-
- // Set
- F32 actual_rate = llmax(min_bps*1.1f, bps);
- LL_DEBUGS("AppInit") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL;
- LL_DEBUGS("AppInit") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL;
- #ifdef LL_XFER_DIAGNOISTIC_LOGGING
- LL_INFOS("Xfer") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL;
- LL_INFOS("Xfer") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL;
- #endif // LL_XFER_DIAGNOISTIC_LOGGING
-
- mAckThrottle.setRate(actual_rate);
-}
-
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::updateHostStatus()
-{
- // Clear the outgoing host list
- for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
- mOutgoingHosts.clear();
-
- // Loop through all outgoing xfers and re-build mOutgoingHosts
- for (xfer_list_t::iterator send_iter = mSendList.begin();
- send_iter != mSendList.end(); ++send_iter)
- {
- LLHostStatus *host_statusp = NULL;
- for (status_list_t::iterator iter = mOutgoingHosts.begin();
- iter != mOutgoingHosts.end(); ++iter)
- {
- if ((*iter)->mHost == (*send_iter)->mRemoteHost)
- { // Already have this host
- host_statusp = *iter;
- break;
- }
- }
- if (!host_statusp)
- { // Don't have this host, so add it
- host_statusp = new LLHostStatus();
- if (host_statusp)
- {
- host_statusp->mHost = (*send_iter)->mRemoteHost;
- mOutgoingHosts.push_front(host_statusp);
- }
- }
- if (host_statusp)
- { // Do the accounting
- if ((*send_iter)->mStatus == e_LL_XFER_PENDING)
- {
- host_statusp->mNumPending++;
- }
- else if ((*send_iter)->mStatus == e_LL_XFER_IN_PROGRESS)
- {
- host_statusp->mNumActive++;
- }
- }
- }
-
-#ifdef LL_XFER_DIAGNOISTIC_LOGGING
- for (xfer_list_t::iterator send_iter = mSendList.begin();
- send_iter != mSendList.end(); ++send_iter)
- {
- LLXfer * xferp = *send_iter;
- LL_INFOS("Xfer") << "xfer to host " << xferp->mRemoteHost
- << " is " << xferp->mXferSize << " bytes"
- << ", status " << (S32)(xferp->mStatus)
- << ", waiting for ACK: " << (S32)(xferp->mWaitingForACK)
- << " in frame " << (S32) LLFrameTimer::getFrameCount()
- << LL_ENDL;
- }
-
- for (status_list_t::iterator iter = mOutgoingHosts.begin();
- iter != mOutgoingHosts.end(); ++iter)
- {
- LL_INFOS("Xfer") << "LLXfer host " << (*iter)->mHost.getIPandPort()
- << " has " << (*iter)->mNumActive
- << " active, " << (*iter)->mNumPending
- << " pending"
- << " in frame " << (S32) LLFrameTimer::getFrameCount()
- << LL_ENDL;
- }
-#endif // LL_XFER_DIAGNOISTIC_LOGGING
-
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::printHostStatus()
-{
- LLHostStatus *host_statusp = NULL;
- if (!mOutgoingHosts.empty())
- {
- LL_INFOS("Xfer") << "Outgoing Xfers:" << LL_ENDL;
-
- for (status_list_t::iterator iter = mOutgoingHosts.begin();
- iter != mOutgoingHosts.end(); ++iter)
- {
- host_statusp = *iter;
- LL_INFOS("Xfer") << " " << host_statusp->mHost << " active: " << host_statusp->mNumActive << " pending: " << host_statusp->mNumPending << LL_ENDL;
- }
- }
-}
-
-///////////////////////////////////////////////////////////
-
-LLXfer * LLXferManager::findXferByID(U64 id, xfer_list_t & xfer_list)
-{
- for (xfer_list_t::iterator iter = xfer_list.begin();
- iter != xfer_list.end();
- ++iter)
- {
- if ((*iter)->mID == id)
- {
- return(*iter);
- }
- }
- return(NULL);
-}
-
-
-///////////////////////////////////////////////////////////
-
-// WARNING: this invalidates iterators from xfer_list
-void LLXferManager::removeXfer(LLXfer *delp, xfer_list_t & xfer_list)
-{
- if (delp)
- {
- std::string direction = "send";
- if (&xfer_list == &mReceiveList)
- {
- direction = "receive";
- }
-
- // This assumes that delp will occur in the list once at most
- // Find the pointer in the list
- for (xfer_list_t::iterator iter = xfer_list.begin();
- iter != xfer_list.end();
- ++iter)
- {
- if ((*iter) == delp)
- {
- LL_DEBUGS("Xfer") << "Deleting xfer to host " << (*iter)->mRemoteHost
- << " of " << (*iter)->mXferSize << " bytes"
- << ", status " << (S32)((*iter)->mStatus)
- << " from the " << direction << " list"
- << LL_ENDL;
-
- xfer_list.erase(iter);
- delete (delp);
- break;
- }
- }
- }
-}
-
-///////////////////////////////////////////////////////////
-
-LLHostStatus * LLXferManager::findHostStatus(const LLHost &host)
-{
- LLHostStatus *host_statusp = NULL;
-
- for (status_list_t::iterator iter = mOutgoingHosts.begin();
- iter != mOutgoingHosts.end(); ++iter)
- {
- host_statusp = *iter;
- if (host_statusp->mHost == host)
- {
- return (host_statusp);
- }
- }
- return 0;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXferManager::numPendingXfers(const LLHost &host)
-{
- LLHostStatus *host_statusp = findHostStatus(host);
- if (host_statusp)
- {
- return host_statusp->mNumPending;
- }
- return 0;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXferManager::numActiveXfers(const LLHost &host)
-{
- LLHostStatus *host_statusp = findHostStatus(host);
- if (host_statusp)
- {
- return host_statusp->mNumActive;
- }
- return 0;
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::changeNumActiveXfers(const LLHost &host, S32 delta)
-{
- LLHostStatus *host_statusp = NULL;
-
- for (status_list_t::iterator iter = mOutgoingHosts.begin();
- iter != mOutgoingHosts.end(); ++iter)
- {
- host_statusp = *iter;
- if (host_statusp->mHost == host)
- {
- host_statusp->mNumActive += delta;
- }
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::registerCallbacks(LLMessageSystem *msgsystem)
-{
- msgsystem->setHandlerFuncFast(_PREHASH_ConfirmXferPacket, process_confirm_packet, NULL);
- msgsystem->setHandlerFuncFast(_PREHASH_RequestXfer, process_request_xfer, NULL);
- msgsystem->setHandlerFuncFast(_PREHASH_SendXferPacket, continue_file_receive, NULL);
- msgsystem->setHandlerFuncFast(_PREHASH_AbortXfer, process_abort_xfer, NULL);
-}
-
-///////////////////////////////////////////////////////////
-
-U64 LLXferManager::getNextID ()
-{
- LLUUID a_guid;
-
- a_guid.generate();
-
-
- return(*((U64*)(a_guid.mData)));
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXferManager::encodePacketNum(S32 packet_num, bool is_EOF)
-{
- if (is_EOF)
- {
- packet_num |= 0x80000000;
- }
- return packet_num;
-}
-
-///////////////////////////////////////////////////////////
-
-S32 LLXferManager::decodePacketNum(S32 packet_num)
-{
- return(packet_num & 0x0FFFFFFF);
-}
-
-///////////////////////////////////////////////////////////
-
-bool LLXferManager::isLastPacket(S32 packet_num)
-{
- return(packet_num & 0x80000000);
-}
-
-///////////////////////////////////////////////////////////
-
-U64 LLXferManager::requestFile(const std::string& local_filename,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data,
- bool is_priority,
- bool use_big_packets)
-{
- LLXfer_File* file_xfer_p = NULL;
-
- // First check to see if it's already requested
- for (xfer_list_t::iterator iter = mReceiveList.begin();
- iter != mReceiveList.end(); ++iter)
- {
- if ((*iter)->getXferTypeTag() == LLXfer::XFER_FILE)
- {
- file_xfer_p = (LLXfer_File*)(*iter);
- if (file_xfer_p->matchesLocalFilename(local_filename)
- && file_xfer_p->matchesRemoteFilename(remote_filename, remote_path)
- && (remote_host == file_xfer_p->mRemoteHost)
- && (callback == file_xfer_p->mCallback)
- && (user_data == file_xfer_p->mCallbackDataHandle))
- {
- // Already have the request (already in progress)
- return (*iter)->mID;
- }
- }
- }
-
- U64 xfer_id = 0;
-
- S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1;
- file_xfer_p = new LLXfer_File(chunk_size);
- if (file_xfer_p)
- {
- addToList(file_xfer_p, mReceiveList, is_priority);
-
- // Remove any file by the same name that happens to be lying
- // around.
- // Note: according to AaronB, this is here to deal with locks on files that were
- // in transit during a crash,
- if(delete_remote_on_completion &&
- (remote_filename.substr(remote_filename.length()-4) == ".tmp"))
- {
- LLFile::remove(local_filename, ENOENT);
- }
- xfer_id = getNextID();
- file_xfer_p->initializeRequest(
- xfer_id,
- local_filename,
- remote_filename,
- remote_path,
- remote_host,
- delete_remote_on_completion,
- callback,user_data);
- startPendingDownloads();
- }
- else
- {
- LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL;
- }
- return xfer_id;
-}
-
-void LLXferManager::requestVFile(const LLUUID& local_id,
- const LLUUID& remote_id,
- LLAssetType::EType type,
- const LLHost& remote_host,
- void (*callback)(void**,S32,LLExtStat),
- void** user_data,
- bool is_priority)
-{
- LLXfer_VFile * xfer_p = NULL;
-
- for (xfer_list_t::iterator iter = mReceiveList.begin();
- iter != mReceiveList.end(); ++iter)
- { // Find any matching existing requests
- if ((*iter)->getXferTypeTag() == LLXfer::XFER_VFILE)
- {
- xfer_p = (LLXfer_VFile*) (*iter);
- if (xfer_p->matchesLocalFile(local_id, type)
- && xfer_p->matchesRemoteFile(remote_id, type)
- && (remote_host == xfer_p->mRemoteHost)
- && (callback == xfer_p->mCallback)
- && (user_data == xfer_p->mCallbackDataHandle))
-
- { // Have match, don't add a duplicate
- #ifdef LL_XFER_DIAGNOISTIC_LOGGING
- LL_INFOS("Xfer") << "Dropping duplicate xfer request for " << remote_id
- << " on " << remote_host.getIPandPort()
- << " local id " << local_id
- << LL_ENDL;
- #endif // LL_XFER_DIAGNOISTIC_LOGGING
-
- return;
- }
- }
- }
-
- xfer_p = new LLXfer_VFile();
- if (xfer_p)
- {
- #ifdef LL_XFER_DIAGNOISTIC_LOGGING
- LL_INFOS("Xfer") << "Starting file xfer for " << remote_id
- << " type " << LLAssetType::lookupHumanReadable(type)
- << " from " << xfer_p->mRemoteHost.getIPandPort()
- << ", local id " << local_id
- << LL_ENDL;
- #endif // LL_XFER_DIAGNOISTIC_LOGGING
-
- addToList(xfer_p, mReceiveList, is_priority);
- ((LLXfer_VFile *)xfer_p)->initializeRequest(getNextID(),
- local_id,
- remote_id,
- type,
- remote_host,
- callback,
- user_data);
- startPendingDownloads();
- }
- else
- {
- LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL;
- }
-
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user_data*/)
-{
- // there's sometimes an extra 4 bytes added to an xfer payload
- const S32 BUF_SIZE = LL_XFER_LARGE_PAYLOAD + 4;
- char fdata_buf[BUF_SIZE]; /* Flawfinder : ignore */
- S32 fdata_size;
- U64 id;
- S32 packetnum;
- LLXfer * xferp;
-
- mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
- mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetnum);
-
- fdata_size = mesgsys->getSizeFast(_PREHASH_DataPacket,_PREHASH_Data);
- if (fdata_size < 0 ||
- fdata_size > BUF_SIZE)
- {
- char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_WARNS("Xfer") << "Received invalid xfer data size of " << fdata_size
- << " in packet number " << packetnum
- << " from " << mesgsys->getSender()
- << " for xfer id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF))
- << LL_ENDL;
- return;
- }
- mesgsys->getBinaryDataFast(_PREHASH_DataPacket, _PREHASH_Data, fdata_buf, fdata_size, 0, BUF_SIZE);
-
- xferp = findXferByID(id, mReceiveList);
- if (!xferp)
- {
- char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_WARNS("Xfer") << "received xfer data from " << mesgsys->getSender()
- << " for non-existent xfer id: "
- << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << LL_ENDL;
- return;
- }
-
- S32 xfer_size;
-
- if (decodePacketNum(packetnum) != xferp->mPacketNum) // is the packet different from what we were expecting?
- {
- // confirm it if it was a resend of the last one, since the confirmation might have gotten dropped
- if (decodePacketNum(packetnum) == (xferp->mPacketNum - 1))
- {
- LL_INFOS("Xfer") << "Reconfirming xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet " << packetnum << LL_ENDL; sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
- }
- else
- {
- LL_INFOS("Xfer") << "Ignoring xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " recv'd packet " << packetnum << "; expecting " << xferp->mPacketNum << LL_ENDL;
- }
- return;
- }
-
- S32 result = 0;
-
- if (xferp->mPacketNum == 0) // first packet has size encoded as additional S32 at beginning of data
- {
- ntohmemcpy(&xfer_size,fdata_buf,MVT_S32,sizeof(S32));
-
-// do any necessary things on first packet ie. allocate memory
- xferp->setXferSize(xfer_size);
-
- // adjust buffer start and size
- result = xferp->receiveData(&(fdata_buf[sizeof(S32)]),fdata_size-(sizeof(S32)));
- }
- else
- {
- result = xferp->receiveData(fdata_buf,fdata_size);
- }
-
- if (result == LL_ERR_CANNOT_OPEN_FILE)
- {
- xferp->abort(LL_ERR_CANNOT_OPEN_FILE);
- removeXfer(xferp,mReceiveList);
- startPendingDownloads();
- return;
- }
-
- xferp->mPacketNum++; // expect next packet
-
- if (!mUseAckThrottling)
- {
- // No throttling, confirm right away
- sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
- }
- else
- {
- // Throttling, put on queue to be confirmed later.
- LLXferAckInfo ack_info;
- ack_info.mID = id;
- ack_info.mPacketNum = decodePacketNum(packetnum);
- ack_info.mRemoteHost = mesgsys->getSender();
- mXferAckQueue.push_back(ack_info);
- }
-
- if (isLastPacket(packetnum))
- {
- xferp->processEOF();
- removeXfer(xferp,mReceiveList);
- startPendingDownloads();
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host)
-{
-#ifdef LL_XFER_PROGRESS_MESSAGES
- if (!(packetnum % 50))
- {
- cout << "confirming xfer packet #" << packetnum << endl;
- }
-#endif
- mesgsys->newMessageFast(_PREHASH_ConfirmXferPacket);
- mesgsys->nextBlockFast(_PREHASH_XferID);
- mesgsys->addU64Fast(_PREHASH_ID, id);
- mesgsys->addU32Fast(_PREHASH_Packet, packetnum);
-
- // Ignore a circuit failure here, we'll catch it with another message
- mesgsys->sendMessage(remote_host);
-}
-
-///////////////////////////////////////////////////////////
-
-static bool find_and_remove(std::multiset<std::string>& files,
- const std::string& filename)
-{
- std::multiset<std::string>::iterator ptr;
- if ( (ptr = files.find(filename)) != files.end())
- {
- //erase(filename) erases *all* entries with that key
- files.erase(ptr);
- return true;
- }
- return false;
-}
-
-void LLXferManager::expectFileForRequest(const std::string& filename)
-{
- mExpectedRequests.insert(filename);
-}
-
-bool LLXferManager::validateFileForRequest(const std::string& filename)
-{
- return find_and_remove(mExpectedRequests, filename);
-}
-
-void LLXferManager::expectFileForTransfer(const std::string& filename)
-{
- mExpectedTransfers.insert(filename);
-}
-
-bool LLXferManager::validateFileForTransfer(const std::string& filename)
-{
- return find_and_remove(mExpectedTransfers, filename);
-}
-
-/* Present in fireengine, not used by viewer
-void LLXferManager::expectVFileForRequest(const std::string& filename)
-{
- mExpectedVFileRequests.insert(filename);
-}
-
-bool LLXferManager::validateVFileForRequest(const std::string& filename)
-{
- return find_and_remove(mExpectedVFileRequests, filename);
-}
-
-void LLXferManager::expectVFileForTransfer(const std::string& filename)
-{
- mExpectedVFileTransfers.insert(filename);
-}
-
-bool LLXferManager::validateVFileForTransfer(const std::string& filename)
-{
- return find_and_remove(mExpectedVFileTransfers, filename);
-}
-*/
-
-static bool remove_prefix(std::string& filename, const std::string& prefix)
-{
- if (std::equal(prefix.begin(), prefix.end(), filename.begin()))
- {
- filename = filename.substr(prefix.length());
- return true;
- }
- return false;
-}
-
-static bool verify_cache_filename(const std::string& filename)
-{
- //NOTE: This routine is only used to check file names that our own
- // code places in the cache directory. As such, it can be limited
- // to this very restrictive file name pattern. It does not need to
- // handle other characters. The only known uses of this are (with examples):
- // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp
- // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
- // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
-
- //IMPORTANT: Do not broaden the filenames accepted by this routine
- // without careful analysis. Anything allowed by this function can
- // be downloaded by the viewer.
-
- size_t len = filename.size();
- //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
- if (len < 5 || len > 50)
- {
- return false;
- }
- for(size_t i=0; i<(len-4); ++i)
- {
- char c = filename[i];
- bool ok = isalnum(c) || '_'==c || '-'==c;
- if (!ok)
- {
- return false;
- }
- }
- return filename[len-4] == '.'
- && filename[len-3] == 't'
- && filename[len-2] == 'm'
- && filename[len-1] == 'p';
-}
-
-void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
-{
-
- U64 id;
- std::string local_filename;
- ELLPath local_path = LL_PATH_NONE;
- S32 result = LL_ERR_NOERR;
- LLUUID uuid;
- LLAssetType::EType type;
- S16 type_s16;
- bool b_use_big_packets;
-
- mesgsys->getBOOL("XferID", "UseBigPackets", b_use_big_packets);
-
- mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
- char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_INFOS("Xfer") << "xfer request id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF))
- << " to " << mesgsys->getSender() << LL_ENDL;
-
- mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename);
-
- {
- U8 local_path_u8;
- mesgsys->getU8("XferID", "FilePath", local_path_u8);
- local_path = (ELLPath)local_path_u8;
- }
-
- mesgsys->getUUIDFast(_PREHASH_XferID, _PREHASH_VFileID, uuid);
- mesgsys->getS16Fast(_PREHASH_XferID, _PREHASH_VFileType, type_s16);
- type = (LLAssetType::EType)type_s16;
-
- LLXfer *xferp;
-
- if (uuid != LLUUID::null)
- { // Request for an asset - use a cache file
- if(NULL == LLAssetType::lookup(type))
- {
- LL_WARNS("Xfer") << "Invalid type for xfer request: " << uuid << ":"
- << type_s16 << " to " << mesgsys->getSender() << LL_ENDL;
- return;
- }
-
- LL_INFOS("Xfer") << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL;
-
- xferp = (LLXfer *)new LLXfer_VFile(uuid, type);
- if (xferp)
- {
- mSendList.push_front(xferp);
- result = xferp->startSend(id,mesgsys->getSender());
- }
- else
- {
- LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL;
- }
- }
- else if (!local_filename.empty())
- { // Was given a file name to send
- // See DEV-21775 for detailed security issues
-
- if (local_path == LL_PATH_NONE)
- {
- // this handles legacy simulators that are passing objects
- // by giving a filename that explicitly names the cache directory
- static const std::string legacy_cache_prefix = "data/";
- if (remove_prefix(local_filename, legacy_cache_prefix))
- {
- local_path = LL_PATH_CACHE;
- }
- }
-
- switch (local_path)
- {
- case LL_PATH_NONE:
- if(!validateFileForTransfer(local_filename))
- {
- LL_WARNS("Xfer") << "SECURITY: Unapproved filename '" << local_filename << LL_ENDL;
- return;
- }
- break;
-
- case LL_PATH_CACHE:
- if(!verify_cache_filename(local_filename))
- {
- LL_WARNS("Xfer") << "SECURITY: Illegal cache filename '" << local_filename << LL_ENDL;
- return;
- }
- break;
-
- default:
- LL_WARNS("Xfer") << "SECURITY: Restricted file dir enum: " << (U32)local_path << LL_ENDL;
- return;
- }
-
- // If we want to use a special path (e.g. LL_PATH_CACHE), we want to make sure we create the
- // proper expanded filename.
- std::string expanded_filename;
- if (local_path != LL_PATH_NONE)
- {
- expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename );
- }
- else
- {
- expanded_filename = local_filename;
- }
- LL_INFOS("Xfer") << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << LL_ENDL;
-
- bool delete_local_on_completion = false;
- mesgsys->getBOOL("XferID", "DeleteOnCompletion", delete_local_on_completion);
-
- // -1 chunk_size causes it to use the default
- xferp = (LLXfer *)new LLXfer_File(expanded_filename, delete_local_on_completion, b_use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1);
-
- if (xferp)
- {
- mSendList.push_front(xferp);
- result = xferp->startSend(id,mesgsys->getSender());
- }
- else
- {
- LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL;
- }
- }
- else
- { // no uuid or filename - use the ID sent
- char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
- LL_INFOS("Xfer") << "starting memory transfer: "
- << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << " to "
- << mesgsys->getSender() << LL_ENDL;
-
- xferp = findXferByID(id, mSendList);
-
- if (xferp)
- {
- result = xferp->startSend(id,mesgsys->getSender());
- }
- else
- {
- LL_INFOS("Xfer") << "Warning: xfer ID " << U64_BUF << " not found." << LL_ENDL;
- result = LL_ERR_FILE_NOT_FOUND;
- }
- }
-
- if (result)
- {
- if (xferp)
- {
- xferp->abort(result);
- removeXfer(xferp, mSendList);
- }
- else // can happen with a memory transfer not found
- {
- LL_INFOS("Xfer") << "Aborting xfer to " << mesgsys->getSender() << " with error: " << result << LL_ENDL;
-
- mesgsys->newMessageFast(_PREHASH_AbortXfer);
- mesgsys->nextBlockFast(_PREHASH_XferID);
- mesgsys->addU64Fast(_PREHASH_ID, id);
- mesgsys->addS32Fast(_PREHASH_Result, result);
-
- mesgsys->sendMessage(mesgsys->getSender());
- }
- }
- else if(xferp)
- {
- // Figure out how many transfers the host has requested
- LLHostStatus *host_statusp = findHostStatus(xferp->mRemoteHost);
- if (host_statusp)
- {
- if (host_statusp->mNumActive < mMaxOutgoingXfersPerCircuit)
- { // Not many transfers in progress already, so start immediately
- xferp->sendNextPacket();
- changeNumActiveXfers(xferp->mRemoteHost,1);
- LL_DEBUGS("Xfer") << "Starting xfer ID " << U64_to_str(id) << " immediately" << LL_ENDL;
- }
- else if (mHardLimitOutgoingXfersPerCircuit == 0 ||
- (host_statusp->mNumActive + host_statusp->mNumPending) < mHardLimitOutgoingXfersPerCircuit)
- { // Must close the file handle and wait for earlier ones to complete
- LL_INFOS("Xfer") << " queueing xfer request id " << U64_to_str(id) << ", "
- << host_statusp->mNumActive << " active and "
- << host_statusp->mNumPending << " pending ahead of this one"
- << LL_ENDL;
- xferp->closeFileHandle(); // Close the file handle until we're ready to send again
- }
- else if (mHardLimitOutgoingXfersPerCircuit > 0)
- { // Way too many requested ... it's time to stop being nice and kill the circuit
- xferp->closeFileHandle(); // Close the file handle in any case
- LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(xferp->mRemoteHost);
- if (cdp)
- {
- if (cdp->getTrusted())
- { // Trusted internal circuit - don't kill it
- LL_WARNS("Xfer") << "Trusted circuit to " << xferp->mRemoteHost << " has too many xfer requests in the queue "
- << host_statusp->mNumActive << " active and "
- << host_statusp->mNumPending << " pending ahead of this one"
- << LL_ENDL;
- }
- else
- { // Untrusted circuit - time to stop messing around and kill it
- LL_WARNS("Xfer") << "Killing circuit to " << xferp->mRemoteHost << " for having too many xfer requests in the queue "
- << host_statusp->mNumActive << " active and "
- << host_statusp->mNumPending << " pending ahead of this one"
- << LL_ENDL;
- gMessageSystem->disableCircuit(xferp->mRemoteHost);
- }
- }
- else
- { // WTF? Why can't we find a circuit? Try to kill it off
- LL_WARNS("Xfer") << "Backlog with circuit to " << xferp->mRemoteHost << " with too many xfer requests in the queue "
- << host_statusp->mNumActive << " active and "
- << host_statusp->mNumPending << " pending ahead of this one"
- << " but no LLCircuitData found???"
- << LL_ENDL;
- gMessageSystem->disableCircuit(xferp->mRemoteHost);
- }
- }
- }
- else
- {
- LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no LLHostStatus found for id " << U64_to_str(id)
- << " host " << xferp->mRemoteHost << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no xfer found for id " << U64_to_str(id) << LL_ENDL;
- }
-}
-
-///////////////////////////////////////////////////////////
-
-// Return true if host is in a transfer-flood sitation. Same check for both internal and external hosts
-bool LLXferManager::isHostFlooded(const LLHost & host)
-{
- bool flooded = false;
- LLHostStatus *host_statusp = findHostStatus(host);
- if (host_statusp)
- {
- flooded = (mHardLimitOutgoingXfersPerCircuit > 0 &&
- (host_statusp->mNumActive + host_statusp->mNumPending) >= (S32)(mHardLimitOutgoingXfersPerCircuit * 0.8f));
- }
-
- return flooded;
-}
-
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/)
-{
- U64 id = 0;
- S32 packetNum = 0;
-
- mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
- mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetNum);
-
- LLXfer* xferp = findXferByID(id, mSendList);
- if (xferp)
- {
-// cout << "confirmed packet #" << packetNum << " ping: "<< xferp->ACKTimer.getElapsedTimeF32() << endl;
- xferp->mWaitingForACK = false;
- if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
- {
- xferp->sendNextPacket();
- }
- else
- {
- removeXfer(xferp, mSendList);
- }
- }
-}
-
-///////////////////////////////////////////////////////////
-
-// Called from LLMessageSystem::processAcks()
-void LLXferManager::retransmitUnackedPackets()
-{
- LLXfer *xferp;
-
- xfer_list_t::iterator iter = mReceiveList.begin();
- while (iter != mReceiveList.end())
- {
- xferp = (*iter);
- if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
- {
- // if the circuit dies, abort
- if (! gMessageSystem->mCircuitInfo.isCircuitAlive( xferp->mRemoteHost ))
- {
- LL_WARNS("Xfer") << "Xfer found in progress on dead circuit, aborting transfer to "
- << xferp->mRemoteHost.getIPandPort()
- << LL_ENDL;
- xferp->mCallbackResult = LL_ERR_CIRCUIT_GONE;
- xferp->processEOF();
-
- iter = mReceiveList.erase(iter); // iter is set to next one after the deletion point
- delete (xferp);
- continue;
- }
-
- }
- ++iter;
- }
-
- // Re-build mOutgoingHosts data
- updateHostStatus();
-
- F32 et;
- iter = mSendList.begin();
- while (iter != mSendList.end())
- {
- xferp = (*iter);
- if (xferp->mWaitingForACK && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_PACKET_TIMEOUT))
- {
- if (xferp->mRetries > LL_PACKET_RETRY_LIMIT)
- {
- LL_INFOS("Xfer") << "dropping xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet retransmit limit exceeded, xfer dropped" << LL_ENDL;
- xferp->abort(LL_ERR_TCP_TIMEOUT);
- iter = mSendList.erase(iter);
- delete xferp;
- continue;
- }
- else
- {
- LL_INFOS("Xfer") << "resending xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet unconfirmed after: "<< et << " sec, packet " << xferp->mPacketNum << LL_ENDL;
- xferp->resendLastPacket();
- }
- }
- else if ((xferp->mStatus == e_LL_XFER_REGISTERED) && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_XFER_REGISTRATION_TIMEOUT))
- {
- LL_INFOS("Xfer") << "registered xfer never requested, xfer dropped" << LL_ENDL;
- xferp->abort(LL_ERR_TCP_TIMEOUT);
- iter = mSendList.erase(iter);
- delete xferp;
- continue;
- }
- else if (xferp->mStatus == e_LL_XFER_ABORTED)
- {
- LL_WARNS("Xfer") << "Removing aborted xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << LL_ENDL;
- iter = mSendList.erase(iter);
- delete xferp;
- continue;
- }
- else if (xferp->mStatus == e_LL_XFER_PENDING)
- {
-// LL_INFOS("Xfer") << "*** numActiveXfers = " << numActiveXfers(xferp->mRemoteHost) << " mMaxOutgoingXfersPerCircuit = " << mMaxOutgoingXfersPerCircuit << LL_ENDL;
- if (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit)
- {
- if (xferp->reopenFileHandle())
- {
- LL_WARNS("Xfer") << "Error re-opening file handle for xfer ID " << U64_to_str(xferp->mID)
- << " to host " << xferp->mRemoteHost << LL_ENDL;
- xferp->abort(LL_ERR_CANNOT_OPEN_FILE);
- iter = mSendList.erase(iter);
- delete xferp;
- continue;
- }
- else
- { // No error re-opening the file, send the first packet
- LL_DEBUGS("Xfer") << "Moving pending xfer ID " << U64_to_str(xferp->mID) << " to active" << LL_ENDL;
- xferp->sendNextPacket();
- changeNumActiveXfers(xferp->mRemoteHost,1);
- }
- }
- }
- ++iter;
- } // end while() loop
-
- //
- // HACK - if we're using xfer confirm throttling, throttle our xfer confirms here
- // so we don't blow through bandwidth.
- //
-
- while (mXferAckQueue.size())
- {
- if (mAckThrottle.checkOverflow(1000.0f*8.0f))
- {
- break;
- }
- //LL_INFOS("Xfer") << "Confirm packet queue length:" << mXferAckQueue.size() << LL_ENDL;
- LLXferAckInfo ack_info = mXferAckQueue.front();
- mXferAckQueue.pop_front();
- //LL_INFOS("Xfer") << "Sending confirm packet" << LL_ENDL;
- sendConfirmPacket(gMessageSystem, ack_info.mID, ack_info.mPacketNum, ack_info.mRemoteHost);
- mAckThrottle.throttleOverflow(1000.f*8.f); // Assume 1000 bytes/packet
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::abortRequestById(U64 xfer_id, S32 result_code)
-{
- LLXfer * xferp = findXferByID(xfer_id, mReceiveList);
- if (xferp)
- {
- if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
- {
- // causes processAbort();
- xferp->abort(result_code);
- }
- else
- {
- xferp->mCallbackResult = result_code;
- xferp->processEOF(); //should notify requester
- removeXfer(xferp, mReceiveList);
- }
- // Since already removed or marked as aborted no need
- // to wait for processAbort() to start new download
- startPendingDownloads();
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::processAbort (LLMessageSystem *mesgsys, void ** /*user_data*/)
-{
- U64 id = 0;
- S32 result_code = 0;
- LLXfer * xferp;
-
- mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
- mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Result, result_code);
-
- xferp = findXferByID(id, mReceiveList);
- if (xferp)
- {
- xferp->mCallbackResult = result_code;
- xferp->processEOF();
- removeXfer(xferp, mReceiveList);
- startPendingDownloads();
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::startPendingDownloads()
-{
- // This method goes through the list, and starts pending
- // operations until active downloads == mMaxIncomingXfers. I copy
- // the pending xfers into a temporary data structure because the
- // xfers are stored as an intrusive linked list where older
- // requests get pushed toward the back. Thus, if we didn't do a
- // stateful iteration, it would be possible for old requests to
- // never start.
- LLXfer* xferp;
- std::list<LLXfer*> pending_downloads;
- S32 download_count = 0;
- S32 pending_count = 0;
- for (xfer_list_t::iterator iter = mReceiveList.begin();
- iter != mReceiveList.end();
- ++iter)
- {
- xferp = (*iter);
- if(xferp->mStatus == e_LL_XFER_PENDING)
- { // Count and accumulate pending downloads
- ++pending_count;
- pending_downloads.push_front(xferp);
- }
- else if(xferp->mStatus == e_LL_XFER_IN_PROGRESS)
- { // Count downloads in progress
- ++download_count;
- }
- }
-
- S32 start_count = mMaxIncomingXfers - download_count;
-
- LL_DEBUGS("Xfer") << "LLXferManager::startPendingDownloads() - XFER_IN_PROGRESS: "
- << download_count << " XFER_PENDING: " << pending_count
- << " startring " << llmin(start_count, pending_count) << LL_ENDL;
-
- if((start_count > 0) && (pending_count > 0))
- {
- S32 result;
- for (std::list<LLXfer*>::iterator iter = pending_downloads.begin();
- iter != pending_downloads.end(); ++iter)
- {
- xferp = *iter;
- if (start_count-- <= 0)
- break;
- result = xferp->startDownload();
- if(result)
- {
- xferp->abort(result);
- ++start_count;
- }
- }
- }
-}
-
-///////////////////////////////////////////////////////////
-
-void LLXferManager::addToList(LLXfer* xferp, xfer_list_t & xfer_list, bool is_priority)
-{
- if(is_priority)
- {
- xfer_list.push_back(xferp);
- }
- else
- {
- xfer_list.push_front(xferp);
- }
-}
-
-///////////////////////////////////////////////////////////
-// Globals and C routines
-///////////////////////////////////////////////////////////
-
-LLXferManager *gXferManager = NULL;
-
-
-void start_xfer_manager()
-{
- gXferManager = new LLXferManager();
-}
-
-void cleanup_xfer_manager()
-{
- if (gXferManager)
- {
- delete(gXferManager);
- gXferManager = NULL;
- }
-}
-
-void process_confirm_packet (LLMessageSystem *mesgsys, void **user_data)
-{
- gXferManager->processConfirmation(mesgsys,user_data);
-}
-
-void process_request_xfer(LLMessageSystem *mesgsys, void **user_data)
-{
- gXferManager->processFileRequest(mesgsys,user_data);
-}
-
-void continue_file_receive(LLMessageSystem *mesgsys, void **user_data)
-{
-#if LL_TEST_XFER_REXMIT
- if (ll_frand() > 0.05f)
- {
-#endif
- gXferManager->processReceiveData(mesgsys,user_data);
-#if LL_TEST_XFER_REXMIT
- }
- else
- {
- cout << "oops! dropped a xfer packet" << endl;
- }
-#endif
-}
-
-void process_abort_xfer(LLMessageSystem *mesgsys, void **user_data)
-{
- gXferManager->processAbort(mesgsys,user_data);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+/**
+ * @file llxfermanager.cpp
+ * @brief implementation of LLXferManager class for a collection of xfers
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxfermanager.h"
+
+#include "llxfer.h"
+#include "llxfer_file.h"
+#include "llxfer_mem.h"
+#include "llxfer_vfile.h"
+
+#include "llerror.h"
+#include "lluuid.h"
+#include "u64.h"
+
+const F32 LL_XFER_REGISTRATION_TIMEOUT = 60.0f; // timeout if a registered transfer hasn't been requested in 60 seconds
+const F32 LL_PACKET_TIMEOUT = 3.0f; // packet timeout at 3 s
+const S32 LL_PACKET_RETRY_LIMIT = 10; // packet retransmission limit
+
+const S32 LL_DEFAULT_MAX_SIMULTANEOUS_XFERS = 10;
+const S32 LL_DEFAULT_MAX_REQUEST_FIFO_XFERS = 1000;
+
+// Kills the connection if a viewer download queue hits this many requests backed up
+// Also set in simulator.xml at "hard_limit_outgoing_xfers_per_circuit"
+const S32 LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS = 500;
+
+// Use this to show sending some ConfirmXferPacket messages
+//#define LL_XFER_PROGRESS_MESSAGES 1
+
+// Use this for lots of diagnostic spam
+//#define LL_XFER_DIAGNOISTIC_LOGGING 1
+
+///////////////////////////////////////////////////////////
+
+LLXferManager::LLXferManager ()
+{
+ init();
+}
+
+///////////////////////////////////////////////////////////
+
+LLXferManager::~LLXferManager ()
+{
+ cleanup();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::init()
+{
+ cleanup();
+
+ setMaxOutgoingXfersPerCircuit(LL_DEFAULT_MAX_SIMULTANEOUS_XFERS);
+ setHardLimitOutgoingXfersPerCircuit(LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS);
+ setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS);
+
+ // Turn on or off ack throttling
+ mUseAckThrottling = false;
+ setAckThrottleBPS(100000);
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::cleanup ()
+{
+ for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
+ mOutgoingHosts.clear();
+
+ for_each(mSendList.begin(), mSendList.end(), DeletePointer());
+ mSendList.clear();
+
+ for_each(mReceiveList.begin(), mReceiveList.end(), DeletePointer());
+ mReceiveList.clear();
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::setMaxIncomingXfers(S32 max_num)
+{
+ mMaxIncomingXfers = max_num;
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::setMaxOutgoingXfersPerCircuit(S32 max_num)
+{
+ mMaxOutgoingXfersPerCircuit = max_num;
+}
+
+void LLXferManager::setHardLimitOutgoingXfersPerCircuit(S32 max_num)
+{
+ mHardLimitOutgoingXfersPerCircuit = max_num;
+}
+
+void LLXferManager::setUseAckThrottling(const bool use)
+{
+ mUseAckThrottling = use;
+}
+
+void LLXferManager::setAckThrottleBPS(const F32 bps)
+{
+ // Let's figure out the min we can set based on the ack retry rate
+ // and number of simultaneous.
+
+ // Assuming we're running as slow as possible, this is the lowest ack
+ // rate we can use.
+ F32 min_bps = (1000.f * 8.f* mMaxIncomingXfers) / LL_PACKET_TIMEOUT;
+
+ // Set
+ F32 actual_rate = llmax(min_bps*1.1f, bps);
+ LL_DEBUGS("AppInit") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL;
+ LL_DEBUGS("AppInit") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL;
+ #ifdef LL_XFER_DIAGNOISTIC_LOGGING
+ LL_INFOS("Xfer") << "LLXferManager ack throttle min rate: " << min_bps << LL_ENDL;
+ LL_INFOS("Xfer") << "LLXferManager ack throttle actual rate: " << actual_rate << LL_ENDL;
+ #endif // LL_XFER_DIAGNOISTIC_LOGGING
+
+ mAckThrottle.setRate(actual_rate);
+}
+
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::updateHostStatus()
+{
+ // Clear the outgoing host list
+ for_each(mOutgoingHosts.begin(), mOutgoingHosts.end(), DeletePointer());
+ mOutgoingHosts.clear();
+
+ // Loop through all outgoing xfers and re-build mOutgoingHosts
+ for (xfer_list_t::iterator send_iter = mSendList.begin();
+ send_iter != mSendList.end(); ++send_iter)
+ {
+ LLHostStatus *host_statusp = NULL;
+ for (status_list_t::iterator iter = mOutgoingHosts.begin();
+ iter != mOutgoingHosts.end(); ++iter)
+ {
+ if ((*iter)->mHost == (*send_iter)->mRemoteHost)
+ { // Already have this host
+ host_statusp = *iter;
+ break;
+ }
+ }
+ if (!host_statusp)
+ { // Don't have this host, so add it
+ host_statusp = new LLHostStatus();
+ if (host_statusp)
+ {
+ host_statusp->mHost = (*send_iter)->mRemoteHost;
+ mOutgoingHosts.push_front(host_statusp);
+ }
+ }
+ if (host_statusp)
+ { // Do the accounting
+ if ((*send_iter)->mStatus == e_LL_XFER_PENDING)
+ {
+ host_statusp->mNumPending++;
+ }
+ else if ((*send_iter)->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ host_statusp->mNumActive++;
+ }
+ }
+ }
+
+#ifdef LL_XFER_DIAGNOISTIC_LOGGING
+ for (xfer_list_t::iterator send_iter = mSendList.begin();
+ send_iter != mSendList.end(); ++send_iter)
+ {
+ LLXfer * xferp = *send_iter;
+ LL_INFOS("Xfer") << "xfer to host " << xferp->mRemoteHost
+ << " is " << xferp->mXferSize << " bytes"
+ << ", status " << (S32)(xferp->mStatus)
+ << ", waiting for ACK: " << (S32)(xferp->mWaitingForACK)
+ << " in frame " << (S32) LLFrameTimer::getFrameCount()
+ << LL_ENDL;
+ }
+
+ for (status_list_t::iterator iter = mOutgoingHosts.begin();
+ iter != mOutgoingHosts.end(); ++iter)
+ {
+ LL_INFOS("Xfer") << "LLXfer host " << (*iter)->mHost.getIPandPort()
+ << " has " << (*iter)->mNumActive
+ << " active, " << (*iter)->mNumPending
+ << " pending"
+ << " in frame " << (S32) LLFrameTimer::getFrameCount()
+ << LL_ENDL;
+ }
+#endif // LL_XFER_DIAGNOISTIC_LOGGING
+
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::printHostStatus()
+{
+ LLHostStatus *host_statusp = NULL;
+ if (!mOutgoingHosts.empty())
+ {
+ LL_INFOS("Xfer") << "Outgoing Xfers:" << LL_ENDL;
+
+ for (status_list_t::iterator iter = mOutgoingHosts.begin();
+ iter != mOutgoingHosts.end(); ++iter)
+ {
+ host_statusp = *iter;
+ LL_INFOS("Xfer") << " " << host_statusp->mHost << " active: " << host_statusp->mNumActive << " pending: " << host_statusp->mNumPending << LL_ENDL;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+LLXfer * LLXferManager::findXferByID(U64 id, xfer_list_t & xfer_list)
+{
+ for (xfer_list_t::iterator iter = xfer_list.begin();
+ iter != xfer_list.end();
+ ++iter)
+ {
+ if ((*iter)->mID == id)
+ {
+ return(*iter);
+ }
+ }
+ return(NULL);
+}
+
+
+///////////////////////////////////////////////////////////
+
+// WARNING: this invalidates iterators from xfer_list
+void LLXferManager::removeXfer(LLXfer *delp, xfer_list_t & xfer_list)
+{
+ if (delp)
+ {
+ std::string direction = "send";
+ if (&xfer_list == &mReceiveList)
+ {
+ direction = "receive";
+ }
+
+ // This assumes that delp will occur in the list once at most
+ // Find the pointer in the list
+ for (xfer_list_t::iterator iter = xfer_list.begin();
+ iter != xfer_list.end();
+ ++iter)
+ {
+ if ((*iter) == delp)
+ {
+ LL_DEBUGS("Xfer") << "Deleting xfer to host " << (*iter)->mRemoteHost
+ << " of " << (*iter)->mXferSize << " bytes"
+ << ", status " << (S32)((*iter)->mStatus)
+ << " from the " << direction << " list"
+ << LL_ENDL;
+
+ xfer_list.erase(iter);
+ delete (delp);
+ break;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+LLHostStatus * LLXferManager::findHostStatus(const LLHost &host)
+{
+ LLHostStatus *host_statusp = NULL;
+
+ for (status_list_t::iterator iter = mOutgoingHosts.begin();
+ iter != mOutgoingHosts.end(); ++iter)
+ {
+ host_statusp = *iter;
+ if (host_statusp->mHost == host)
+ {
+ return (host_statusp);
+ }
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXferManager::numPendingXfers(const LLHost &host)
+{
+ LLHostStatus *host_statusp = findHostStatus(host);
+ if (host_statusp)
+ {
+ return host_statusp->mNumPending;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXferManager::numActiveXfers(const LLHost &host)
+{
+ LLHostStatus *host_statusp = findHostStatus(host);
+ if (host_statusp)
+ {
+ return host_statusp->mNumActive;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::changeNumActiveXfers(const LLHost &host, S32 delta)
+{
+ LLHostStatus *host_statusp = NULL;
+
+ for (status_list_t::iterator iter = mOutgoingHosts.begin();
+ iter != mOutgoingHosts.end(); ++iter)
+ {
+ host_statusp = *iter;
+ if (host_statusp->mHost == host)
+ {
+ host_statusp->mNumActive += delta;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::registerCallbacks(LLMessageSystem *msgsystem)
+{
+ msgsystem->setHandlerFuncFast(_PREHASH_ConfirmXferPacket, process_confirm_packet, NULL);
+ msgsystem->setHandlerFuncFast(_PREHASH_RequestXfer, process_request_xfer, NULL);
+ msgsystem->setHandlerFuncFast(_PREHASH_SendXferPacket, continue_file_receive, NULL);
+ msgsystem->setHandlerFuncFast(_PREHASH_AbortXfer, process_abort_xfer, NULL);
+}
+
+///////////////////////////////////////////////////////////
+
+U64 LLXferManager::getNextID ()
+{
+ LLUUID a_guid;
+
+ a_guid.generate();
+
+
+ return(*((U64*)(a_guid.mData)));
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXferManager::encodePacketNum(S32 packet_num, bool is_EOF)
+{
+ if (is_EOF)
+ {
+ packet_num |= 0x80000000;
+ }
+ return packet_num;
+}
+
+///////////////////////////////////////////////////////////
+
+S32 LLXferManager::decodePacketNum(S32 packet_num)
+{
+ return(packet_num & 0x0FFFFFFF);
+}
+
+///////////////////////////////////////////////////////////
+
+bool LLXferManager::isLastPacket(S32 packet_num)
+{
+ return(packet_num & 0x80000000);
+}
+
+///////////////////////////////////////////////////////////
+
+U64 LLXferManager::requestFile(const std::string& local_filename,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void**,S32,LLExtStat),
+ void** user_data,
+ bool is_priority,
+ bool use_big_packets)
+{
+ LLXfer_File* file_xfer_p = NULL;
+
+ // First check to see if it's already requested
+ for (xfer_list_t::iterator iter = mReceiveList.begin();
+ iter != mReceiveList.end(); ++iter)
+ {
+ if ((*iter)->getXferTypeTag() == LLXfer::XFER_FILE)
+ {
+ file_xfer_p = (LLXfer_File*)(*iter);
+ if (file_xfer_p->matchesLocalFilename(local_filename)
+ && file_xfer_p->matchesRemoteFilename(remote_filename, remote_path)
+ && (remote_host == file_xfer_p->mRemoteHost)
+ && (callback == file_xfer_p->mCallback)
+ && (user_data == file_xfer_p->mCallbackDataHandle))
+ {
+ // Already have the request (already in progress)
+ return (*iter)->mID;
+ }
+ }
+ }
+
+ U64 xfer_id = 0;
+
+ S32 chunk_size = use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1;
+ file_xfer_p = new LLXfer_File(chunk_size);
+ if (file_xfer_p)
+ {
+ addToList(file_xfer_p, mReceiveList, is_priority);
+
+ // Remove any file by the same name that happens to be lying
+ // around.
+ // Note: according to AaronB, this is here to deal with locks on files that were
+ // in transit during a crash,
+ if(delete_remote_on_completion &&
+ (remote_filename.substr(remote_filename.length()-4) == ".tmp"))
+ {
+ LLFile::remove(local_filename, ENOENT);
+ }
+ xfer_id = getNextID();
+ file_xfer_p->initializeRequest(
+ xfer_id,
+ local_filename,
+ remote_filename,
+ remote_path,
+ remote_host,
+ delete_remote_on_completion,
+ callback,user_data);
+ startPendingDownloads();
+ }
+ else
+ {
+ LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL;
+ }
+ return xfer_id;
+}
+
+void LLXferManager::requestVFile(const LLUUID& local_id,
+ const LLUUID& remote_id,
+ LLAssetType::EType type,
+ const LLHost& remote_host,
+ void (*callback)(void**,S32,LLExtStat),
+ void** user_data,
+ bool is_priority)
+{
+ LLXfer_VFile * xfer_p = NULL;
+
+ for (xfer_list_t::iterator iter = mReceiveList.begin();
+ iter != mReceiveList.end(); ++iter)
+ { // Find any matching existing requests
+ if ((*iter)->getXferTypeTag() == LLXfer::XFER_VFILE)
+ {
+ xfer_p = (LLXfer_VFile*) (*iter);
+ if (xfer_p->matchesLocalFile(local_id, type)
+ && xfer_p->matchesRemoteFile(remote_id, type)
+ && (remote_host == xfer_p->mRemoteHost)
+ && (callback == xfer_p->mCallback)
+ && (user_data == xfer_p->mCallbackDataHandle))
+
+ { // Have match, don't add a duplicate
+ #ifdef LL_XFER_DIAGNOISTIC_LOGGING
+ LL_INFOS("Xfer") << "Dropping duplicate xfer request for " << remote_id
+ << " on " << remote_host.getIPandPort()
+ << " local id " << local_id
+ << LL_ENDL;
+ #endif // LL_XFER_DIAGNOISTIC_LOGGING
+
+ return;
+ }
+ }
+ }
+
+ xfer_p = new LLXfer_VFile();
+ if (xfer_p)
+ {
+ #ifdef LL_XFER_DIAGNOISTIC_LOGGING
+ LL_INFOS("Xfer") << "Starting file xfer for " << remote_id
+ << " type " << LLAssetType::lookupHumanReadable(type)
+ << " from " << xfer_p->mRemoteHost.getIPandPort()
+ << ", local id " << local_id
+ << LL_ENDL;
+ #endif // LL_XFER_DIAGNOISTIC_LOGGING
+
+ addToList(xfer_p, mReceiveList, is_priority);
+ ((LLXfer_VFile *)xfer_p)->initializeRequest(getNextID(),
+ local_id,
+ remote_id,
+ type,
+ remote_host,
+ callback,
+ user_data);
+ startPendingDownloads();
+ }
+ else
+ {
+ LL_ERRS("Xfer") << "Xfer allocation error" << LL_ENDL;
+ }
+
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user_data*/)
+{
+ // there's sometimes an extra 4 bytes added to an xfer payload
+ const S32 BUF_SIZE = LL_XFER_LARGE_PAYLOAD + 4;
+ char fdata_buf[BUF_SIZE]; /* Flawfinder : ignore */
+ S32 fdata_size;
+ U64 id;
+ S32 packetnum;
+ LLXfer * xferp;
+
+ mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
+ mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetnum);
+
+ fdata_size = mesgsys->getSizeFast(_PREHASH_DataPacket,_PREHASH_Data);
+ if (fdata_size < 0 ||
+ fdata_size > BUF_SIZE)
+ {
+ char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
+ LL_WARNS("Xfer") << "Received invalid xfer data size of " << fdata_size
+ << " in packet number " << packetnum
+ << " from " << mesgsys->getSender()
+ << " for xfer id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF))
+ << LL_ENDL;
+ return;
+ }
+ mesgsys->getBinaryDataFast(_PREHASH_DataPacket, _PREHASH_Data, fdata_buf, fdata_size, 0, BUF_SIZE);
+
+ xferp = findXferByID(id, mReceiveList);
+ if (!xferp)
+ {
+ char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
+ LL_WARNS("Xfer") << "received xfer data from " << mesgsys->getSender()
+ << " for non-existent xfer id: "
+ << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << LL_ENDL;
+ return;
+ }
+
+ S32 xfer_size;
+
+ if (decodePacketNum(packetnum) != xferp->mPacketNum) // is the packet different from what we were expecting?
+ {
+ // confirm it if it was a resend of the last one, since the confirmation might have gotten dropped
+ if (decodePacketNum(packetnum) == (xferp->mPacketNum - 1))
+ {
+ LL_INFOS("Xfer") << "Reconfirming xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet " << packetnum << LL_ENDL; sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
+ }
+ else
+ {
+ LL_INFOS("Xfer") << "Ignoring xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " recv'd packet " << packetnum << "; expecting " << xferp->mPacketNum << LL_ENDL;
+ }
+ return;
+ }
+
+ S32 result = 0;
+
+ if (xferp->mPacketNum == 0) // first packet has size encoded as additional S32 at beginning of data
+ {
+ ntohmemcpy(&xfer_size,fdata_buf,MVT_S32,sizeof(S32));
+
+// do any necessary things on first packet ie. allocate memory
+ xferp->setXferSize(xfer_size);
+
+ // adjust buffer start and size
+ result = xferp->receiveData(&(fdata_buf[sizeof(S32)]),fdata_size-(sizeof(S32)));
+ }
+ else
+ {
+ result = xferp->receiveData(fdata_buf,fdata_size);
+ }
+
+ if (result == LL_ERR_CANNOT_OPEN_FILE)
+ {
+ xferp->abort(LL_ERR_CANNOT_OPEN_FILE);
+ removeXfer(xferp,mReceiveList);
+ startPendingDownloads();
+ return;
+ }
+
+ xferp->mPacketNum++; // expect next packet
+
+ if (!mUseAckThrottling)
+ {
+ // No throttling, confirm right away
+ sendConfirmPacket(mesgsys, id, decodePacketNum(packetnum), mesgsys->getSender());
+ }
+ else
+ {
+ // Throttling, put on queue to be confirmed later.
+ LLXferAckInfo ack_info;
+ ack_info.mID = id;
+ ack_info.mPacketNum = decodePacketNum(packetnum);
+ ack_info.mRemoteHost = mesgsys->getSender();
+ mXferAckQueue.push_back(ack_info);
+ }
+
+ if (isLastPacket(packetnum))
+ {
+ xferp->processEOF();
+ removeXfer(xferp,mReceiveList);
+ startPendingDownloads();
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host)
+{
+#ifdef LL_XFER_PROGRESS_MESSAGES
+ if (!(packetnum % 50))
+ {
+ cout << "confirming xfer packet #" << packetnum << endl;
+ }
+#endif
+ mesgsys->newMessageFast(_PREHASH_ConfirmXferPacket);
+ mesgsys->nextBlockFast(_PREHASH_XferID);
+ mesgsys->addU64Fast(_PREHASH_ID, id);
+ mesgsys->addU32Fast(_PREHASH_Packet, packetnum);
+
+ // Ignore a circuit failure here, we'll catch it with another message
+ mesgsys->sendMessage(remote_host);
+}
+
+///////////////////////////////////////////////////////////
+
+static bool find_and_remove(std::multiset<std::string>& files,
+ const std::string& filename)
+{
+ std::multiset<std::string>::iterator ptr;
+ if ( (ptr = files.find(filename)) != files.end())
+ {
+ //erase(filename) erases *all* entries with that key
+ files.erase(ptr);
+ return true;
+ }
+ return false;
+}
+
+void LLXferManager::expectFileForRequest(const std::string& filename)
+{
+ mExpectedRequests.insert(filename);
+}
+
+bool LLXferManager::validateFileForRequest(const std::string& filename)
+{
+ return find_and_remove(mExpectedRequests, filename);
+}
+
+void LLXferManager::expectFileForTransfer(const std::string& filename)
+{
+ mExpectedTransfers.insert(filename);
+}
+
+bool LLXferManager::validateFileForTransfer(const std::string& filename)
+{
+ return find_and_remove(mExpectedTransfers, filename);
+}
+
+/* Present in fireengine, not used by viewer
+void LLXferManager::expectVFileForRequest(const std::string& filename)
+{
+ mExpectedVFileRequests.insert(filename);
+}
+
+bool LLXferManager::validateVFileForRequest(const std::string& filename)
+{
+ return find_and_remove(mExpectedVFileRequests, filename);
+}
+
+void LLXferManager::expectVFileForTransfer(const std::string& filename)
+{
+ mExpectedVFileTransfers.insert(filename);
+}
+
+bool LLXferManager::validateVFileForTransfer(const std::string& filename)
+{
+ return find_and_remove(mExpectedVFileTransfers, filename);
+}
+*/
+
+static bool remove_prefix(std::string& filename, const std::string& prefix)
+{
+ if (std::equal(prefix.begin(), prefix.end(), filename.begin()))
+ {
+ filename = filename.substr(prefix.length());
+ return true;
+ }
+ return false;
+}
+
+static bool verify_cache_filename(const std::string& filename)
+{
+ //NOTE: This routine is only used to check file names that our own
+ // code places in the cache directory. As such, it can be limited
+ // to this very restrictive file name pattern. It does not need to
+ // handle other characters. The only known uses of this are (with examples):
+ // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp
+ // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp
+ // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp
+
+ //IMPORTANT: Do not broaden the filenames accepted by this routine
+ // without careful analysis. Anything allowed by this function can
+ // be downloaded by the viewer.
+
+ size_t len = filename.size();
+ //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp");
+ if (len < 5 || len > 50)
+ {
+ return false;
+ }
+ for(size_t i=0; i<(len-4); ++i)
+ {
+ char c = filename[i];
+ bool ok = isalnum(c) || '_'==c || '-'==c;
+ if (!ok)
+ {
+ return false;
+ }
+ }
+ return filename[len-4] == '.'
+ && filename[len-3] == 't'
+ && filename[len-2] == 'm'
+ && filename[len-1] == 'p';
+}
+
+void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/)
+{
+
+ U64 id;
+ std::string local_filename;
+ ELLPath local_path = LL_PATH_NONE;
+ S32 result = LL_ERR_NOERR;
+ LLUUID uuid;
+ LLAssetType::EType type;
+ S16 type_s16;
+ bool b_use_big_packets;
+
+ mesgsys->getBOOL("XferID", "UseBigPackets", b_use_big_packets);
+
+ mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
+ char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
+ LL_INFOS("Xfer") << "xfer request id: " << U64_to_str(id, U64_BUF, sizeof(U64_BUF))
+ << " to " << mesgsys->getSender() << LL_ENDL;
+
+ mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename);
+
+ {
+ U8 local_path_u8;
+ mesgsys->getU8("XferID", "FilePath", local_path_u8);
+ local_path = (ELLPath)local_path_u8;
+ }
+
+ mesgsys->getUUIDFast(_PREHASH_XferID, _PREHASH_VFileID, uuid);
+ mesgsys->getS16Fast(_PREHASH_XferID, _PREHASH_VFileType, type_s16);
+ type = (LLAssetType::EType)type_s16;
+
+ LLXfer *xferp;
+
+ if (uuid != LLUUID::null)
+ { // Request for an asset - use a cache file
+ if(NULL == LLAssetType::lookup(type))
+ {
+ LL_WARNS("Xfer") << "Invalid type for xfer request: " << uuid << ":"
+ << type_s16 << " to " << mesgsys->getSender() << LL_ENDL;
+ return;
+ }
+
+ LL_INFOS("Xfer") << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL;
+
+ xferp = (LLXfer *)new LLXfer_VFile(uuid, type);
+ if (xferp)
+ {
+ mSendList.push_front(xferp);
+ result = xferp->startSend(id,mesgsys->getSender());
+ }
+ else
+ {
+ LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL;
+ }
+ }
+ else if (!local_filename.empty())
+ { // Was given a file name to send
+ // See DEV-21775 for detailed security issues
+
+ if (local_path == LL_PATH_NONE)
+ {
+ // this handles legacy simulators that are passing objects
+ // by giving a filename that explicitly names the cache directory
+ static const std::string legacy_cache_prefix = "data/";
+ if (remove_prefix(local_filename, legacy_cache_prefix))
+ {
+ local_path = LL_PATH_CACHE;
+ }
+ }
+
+ switch (local_path)
+ {
+ case LL_PATH_NONE:
+ if(!validateFileForTransfer(local_filename))
+ {
+ LL_WARNS("Xfer") << "SECURITY: Unapproved filename '" << local_filename << LL_ENDL;
+ return;
+ }
+ break;
+
+ case LL_PATH_CACHE:
+ if(!verify_cache_filename(local_filename))
+ {
+ LL_WARNS("Xfer") << "SECURITY: Illegal cache filename '" << local_filename << LL_ENDL;
+ return;
+ }
+ break;
+
+ default:
+ LL_WARNS("Xfer") << "SECURITY: Restricted file dir enum: " << (U32)local_path << LL_ENDL;
+ return;
+ }
+
+ // If we want to use a special path (e.g. LL_PATH_CACHE), we want to make sure we create the
+ // proper expanded filename.
+ std::string expanded_filename;
+ if (local_path != LL_PATH_NONE)
+ {
+ expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename );
+ }
+ else
+ {
+ expanded_filename = local_filename;
+ }
+ LL_INFOS("Xfer") << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << LL_ENDL;
+
+ bool delete_local_on_completion = false;
+ mesgsys->getBOOL("XferID", "DeleteOnCompletion", delete_local_on_completion);
+
+ // -1 chunk_size causes it to use the default
+ xferp = (LLXfer *)new LLXfer_File(expanded_filename, delete_local_on_completion, b_use_big_packets ? LL_XFER_LARGE_PAYLOAD : -1);
+
+ if (xferp)
+ {
+ mSendList.push_front(xferp);
+ result = xferp->startSend(id,mesgsys->getSender());
+ }
+ else
+ {
+ LL_ERRS("Xfer") << "Xfer allcoation error" << LL_ENDL;
+ }
+ }
+ else
+ { // no uuid or filename - use the ID sent
+ char U64_BUF[MAX_STRING]; /* Flawfinder : ignore */
+ LL_INFOS("Xfer") << "starting memory transfer: "
+ << U64_to_str(id, U64_BUF, sizeof(U64_BUF)) << " to "
+ << mesgsys->getSender() << LL_ENDL;
+
+ xferp = findXferByID(id, mSendList);
+
+ if (xferp)
+ {
+ result = xferp->startSend(id,mesgsys->getSender());
+ }
+ else
+ {
+ LL_INFOS("Xfer") << "Warning: xfer ID " << U64_BUF << " not found." << LL_ENDL;
+ result = LL_ERR_FILE_NOT_FOUND;
+ }
+ }
+
+ if (result)
+ {
+ if (xferp)
+ {
+ xferp->abort(result);
+ removeXfer(xferp, mSendList);
+ }
+ else // can happen with a memory transfer not found
+ {
+ LL_INFOS("Xfer") << "Aborting xfer to " << mesgsys->getSender() << " with error: " << result << LL_ENDL;
+
+ mesgsys->newMessageFast(_PREHASH_AbortXfer);
+ mesgsys->nextBlockFast(_PREHASH_XferID);
+ mesgsys->addU64Fast(_PREHASH_ID, id);
+ mesgsys->addS32Fast(_PREHASH_Result, result);
+
+ mesgsys->sendMessage(mesgsys->getSender());
+ }
+ }
+ else if(xferp)
+ {
+ // Figure out how many transfers the host has requested
+ LLHostStatus *host_statusp = findHostStatus(xferp->mRemoteHost);
+ if (host_statusp)
+ {
+ if (host_statusp->mNumActive < mMaxOutgoingXfersPerCircuit)
+ { // Not many transfers in progress already, so start immediately
+ xferp->sendNextPacket();
+ changeNumActiveXfers(xferp->mRemoteHost,1);
+ LL_DEBUGS("Xfer") << "Starting xfer ID " << U64_to_str(id) << " immediately" << LL_ENDL;
+ }
+ else if (mHardLimitOutgoingXfersPerCircuit == 0 ||
+ (host_statusp->mNumActive + host_statusp->mNumPending) < mHardLimitOutgoingXfersPerCircuit)
+ { // Must close the file handle and wait for earlier ones to complete
+ LL_INFOS("Xfer") << " queueing xfer request id " << U64_to_str(id) << ", "
+ << host_statusp->mNumActive << " active and "
+ << host_statusp->mNumPending << " pending ahead of this one"
+ << LL_ENDL;
+ xferp->closeFileHandle(); // Close the file handle until we're ready to send again
+ }
+ else if (mHardLimitOutgoingXfersPerCircuit > 0)
+ { // Way too many requested ... it's time to stop being nice and kill the circuit
+ xferp->closeFileHandle(); // Close the file handle in any case
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(xferp->mRemoteHost);
+ if (cdp)
+ {
+ if (cdp->getTrusted())
+ { // Trusted internal circuit - don't kill it
+ LL_WARNS("Xfer") << "Trusted circuit to " << xferp->mRemoteHost << " has too many xfer requests in the queue "
+ << host_statusp->mNumActive << " active and "
+ << host_statusp->mNumPending << " pending ahead of this one"
+ << LL_ENDL;
+ }
+ else
+ { // Untrusted circuit - time to stop messing around and kill it
+ LL_WARNS("Xfer") << "Killing circuit to " << xferp->mRemoteHost << " for having too many xfer requests in the queue "
+ << host_statusp->mNumActive << " active and "
+ << host_statusp->mNumPending << " pending ahead of this one"
+ << LL_ENDL;
+ gMessageSystem->disableCircuit(xferp->mRemoteHost);
+ }
+ }
+ else
+ { // WTF? Why can't we find a circuit? Try to kill it off
+ LL_WARNS("Xfer") << "Backlog with circuit to " << xferp->mRemoteHost << " with too many xfer requests in the queue "
+ << host_statusp->mNumActive << " active and "
+ << host_statusp->mNumPending << " pending ahead of this one"
+ << " but no LLCircuitData found???"
+ << LL_ENDL;
+ gMessageSystem->disableCircuit(xferp->mRemoteHost);
+ }
+ }
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no LLHostStatus found for id " << U64_to_str(id)
+ << " host " << xferp->mRemoteHost << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("Xfer") << "LLXferManager::processFileRequest() - no xfer found for id " << U64_to_str(id) << LL_ENDL;
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+// Return true if host is in a transfer-flood sitation. Same check for both internal and external hosts
+bool LLXferManager::isHostFlooded(const LLHost & host)
+{
+ bool flooded = false;
+ LLHostStatus *host_statusp = findHostStatus(host);
+ if (host_statusp)
+ {
+ flooded = (mHardLimitOutgoingXfersPerCircuit > 0 &&
+ (host_statusp->mNumActive + host_statusp->mNumPending) >= (S32)(mHardLimitOutgoingXfersPerCircuit * 0.8f));
+ }
+
+ return flooded;
+}
+
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/)
+{
+ U64 id = 0;
+ S32 packetNum = 0;
+
+ mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
+ mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Packet, packetNum);
+
+ LLXfer* xferp = findXferByID(id, mSendList);
+ if (xferp)
+ {
+// cout << "confirmed packet #" << packetNum << " ping: "<< xferp->ACKTimer.getElapsedTimeF32() << endl;
+ xferp->mWaitingForACK = false;
+ if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ xferp->sendNextPacket();
+ }
+ else
+ {
+ removeXfer(xferp, mSendList);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+// Called from LLMessageSystem::processAcks()
+void LLXferManager::retransmitUnackedPackets()
+{
+ LLXfer *xferp;
+
+ xfer_list_t::iterator iter = mReceiveList.begin();
+ while (iter != mReceiveList.end())
+ {
+ xferp = (*iter);
+ if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ // if the circuit dies, abort
+ if (! gMessageSystem->mCircuitInfo.isCircuitAlive( xferp->mRemoteHost ))
+ {
+ LL_WARNS("Xfer") << "Xfer found in progress on dead circuit, aborting transfer to "
+ << xferp->mRemoteHost.getIPandPort()
+ << LL_ENDL;
+ xferp->mCallbackResult = LL_ERR_CIRCUIT_GONE;
+ xferp->processEOF();
+
+ iter = mReceiveList.erase(iter); // iter is set to next one after the deletion point
+ delete (xferp);
+ continue;
+ }
+
+ }
+ ++iter;
+ }
+
+ // Re-build mOutgoingHosts data
+ updateHostStatus();
+
+ F32 et;
+ iter = mSendList.begin();
+ while (iter != mSendList.end())
+ {
+ xferp = (*iter);
+ if (xferp->mWaitingForACK && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_PACKET_TIMEOUT))
+ {
+ if (xferp->mRetries > LL_PACKET_RETRY_LIMIT)
+ {
+ LL_INFOS("Xfer") << "dropping xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet retransmit limit exceeded, xfer dropped" << LL_ENDL;
+ xferp->abort(LL_ERR_TCP_TIMEOUT);
+ iter = mSendList.erase(iter);
+ delete xferp;
+ continue;
+ }
+ else
+ {
+ LL_INFOS("Xfer") << "resending xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << " packet unconfirmed after: "<< et << " sec, packet " << xferp->mPacketNum << LL_ENDL;
+ xferp->resendLastPacket();
+ }
+ }
+ else if ((xferp->mStatus == e_LL_XFER_REGISTERED) && ( (et = xferp->ACKTimer.getElapsedTimeF32()) > LL_XFER_REGISTRATION_TIMEOUT))
+ {
+ LL_INFOS("Xfer") << "registered xfer never requested, xfer dropped" << LL_ENDL;
+ xferp->abort(LL_ERR_TCP_TIMEOUT);
+ iter = mSendList.erase(iter);
+ delete xferp;
+ continue;
+ }
+ else if (xferp->mStatus == e_LL_XFER_ABORTED)
+ {
+ LL_WARNS("Xfer") << "Removing aborted xfer " << xferp->mRemoteHost << ":" << xferp->getFileName() << LL_ENDL;
+ iter = mSendList.erase(iter);
+ delete xferp;
+ continue;
+ }
+ else if (xferp->mStatus == e_LL_XFER_PENDING)
+ {
+// LL_INFOS("Xfer") << "*** numActiveXfers = " << numActiveXfers(xferp->mRemoteHost) << " mMaxOutgoingXfersPerCircuit = " << mMaxOutgoingXfersPerCircuit << LL_ENDL;
+ if (numActiveXfers(xferp->mRemoteHost) < mMaxOutgoingXfersPerCircuit)
+ {
+ if (xferp->reopenFileHandle())
+ {
+ LL_WARNS("Xfer") << "Error re-opening file handle for xfer ID " << U64_to_str(xferp->mID)
+ << " to host " << xferp->mRemoteHost << LL_ENDL;
+ xferp->abort(LL_ERR_CANNOT_OPEN_FILE);
+ iter = mSendList.erase(iter);
+ delete xferp;
+ continue;
+ }
+ else
+ { // No error re-opening the file, send the first packet
+ LL_DEBUGS("Xfer") << "Moving pending xfer ID " << U64_to_str(xferp->mID) << " to active" << LL_ENDL;
+ xferp->sendNextPacket();
+ changeNumActiveXfers(xferp->mRemoteHost,1);
+ }
+ }
+ }
+ ++iter;
+ } // end while() loop
+
+ //
+ // HACK - if we're using xfer confirm throttling, throttle our xfer confirms here
+ // so we don't blow through bandwidth.
+ //
+
+ while (mXferAckQueue.size())
+ {
+ if (mAckThrottle.checkOverflow(1000.0f*8.0f))
+ {
+ break;
+ }
+ //LL_INFOS("Xfer") << "Confirm packet queue length:" << mXferAckQueue.size() << LL_ENDL;
+ LLXferAckInfo ack_info = mXferAckQueue.front();
+ mXferAckQueue.pop_front();
+ //LL_INFOS("Xfer") << "Sending confirm packet" << LL_ENDL;
+ sendConfirmPacket(gMessageSystem, ack_info.mID, ack_info.mPacketNum, ack_info.mRemoteHost);
+ mAckThrottle.throttleOverflow(1000.f*8.f); // Assume 1000 bytes/packet
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::abortRequestById(U64 xfer_id, S32 result_code)
+{
+ LLXfer * xferp = findXferByID(xfer_id, mReceiveList);
+ if (xferp)
+ {
+ if (xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ {
+ // causes processAbort();
+ xferp->abort(result_code);
+ }
+ else
+ {
+ xferp->mCallbackResult = result_code;
+ xferp->processEOF(); //should notify requester
+ removeXfer(xferp, mReceiveList);
+ }
+ // Since already removed or marked as aborted no need
+ // to wait for processAbort() to start new download
+ startPendingDownloads();
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::processAbort (LLMessageSystem *mesgsys, void ** /*user_data*/)
+{
+ U64 id = 0;
+ S32 result_code = 0;
+ LLXfer * xferp;
+
+ mesgsys->getU64Fast(_PREHASH_XferID, _PREHASH_ID, id);
+ mesgsys->getS32Fast(_PREHASH_XferID, _PREHASH_Result, result_code);
+
+ xferp = findXferByID(id, mReceiveList);
+ if (xferp)
+ {
+ xferp->mCallbackResult = result_code;
+ xferp->processEOF();
+ removeXfer(xferp, mReceiveList);
+ startPendingDownloads();
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::startPendingDownloads()
+{
+ // This method goes through the list, and starts pending
+ // operations until active downloads == mMaxIncomingXfers. I copy
+ // the pending xfers into a temporary data structure because the
+ // xfers are stored as an intrusive linked list where older
+ // requests get pushed toward the back. Thus, if we didn't do a
+ // stateful iteration, it would be possible for old requests to
+ // never start.
+ LLXfer* xferp;
+ std::list<LLXfer*> pending_downloads;
+ S32 download_count = 0;
+ S32 pending_count = 0;
+ for (xfer_list_t::iterator iter = mReceiveList.begin();
+ iter != mReceiveList.end();
+ ++iter)
+ {
+ xferp = (*iter);
+ if(xferp->mStatus == e_LL_XFER_PENDING)
+ { // Count and accumulate pending downloads
+ ++pending_count;
+ pending_downloads.push_front(xferp);
+ }
+ else if(xferp->mStatus == e_LL_XFER_IN_PROGRESS)
+ { // Count downloads in progress
+ ++download_count;
+ }
+ }
+
+ S32 start_count = mMaxIncomingXfers - download_count;
+
+ LL_DEBUGS("Xfer") << "LLXferManager::startPendingDownloads() - XFER_IN_PROGRESS: "
+ << download_count << " XFER_PENDING: " << pending_count
+ << " startring " << llmin(start_count, pending_count) << LL_ENDL;
+
+ if((start_count > 0) && (pending_count > 0))
+ {
+ S32 result;
+ for (std::list<LLXfer*>::iterator iter = pending_downloads.begin();
+ iter != pending_downloads.end(); ++iter)
+ {
+ xferp = *iter;
+ if (start_count-- <= 0)
+ break;
+ result = xferp->startDownload();
+ if(result)
+ {
+ xferp->abort(result);
+ ++start_count;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////
+
+void LLXferManager::addToList(LLXfer* xferp, xfer_list_t & xfer_list, bool is_priority)
+{
+ if(is_priority)
+ {
+ xfer_list.push_back(xferp);
+ }
+ else
+ {
+ xfer_list.push_front(xferp);
+ }
+}
+
+///////////////////////////////////////////////////////////
+// Globals and C routines
+///////////////////////////////////////////////////////////
+
+LLXferManager *gXferManager = NULL;
+
+
+void start_xfer_manager()
+{
+ gXferManager = new LLXferManager();
+}
+
+void cleanup_xfer_manager()
+{
+ if (gXferManager)
+ {
+ delete(gXferManager);
+ gXferManager = NULL;
+ }
+}
+
+void process_confirm_packet (LLMessageSystem *mesgsys, void **user_data)
+{
+ gXferManager->processConfirmation(mesgsys,user_data);
+}
+
+void process_request_xfer(LLMessageSystem *mesgsys, void **user_data)
+{
+ gXferManager->processFileRequest(mesgsys,user_data);
+}
+
+void continue_file_receive(LLMessageSystem *mesgsys, void **user_data)
+{
+#if LL_TEST_XFER_REXMIT
+ if (ll_frand() > 0.05f)
+ {
+#endif
+ gXferManager->processReceiveData(mesgsys,user_data);
+#if LL_TEST_XFER_REXMIT
+ }
+ else
+ {
+ cout << "oops! dropped a xfer packet" << endl;
+ }
+#endif
+}
+
+void process_abort_xfer(LLMessageSystem *mesgsys, void **user_data)
+{
+ gXferManager->processAbort(mesgsys,user_data);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/indra/llmessage/llxfermanager.h b/indra/llmessage/llxfermanager.h
index 5b42e781eb..ce412ddd26 100644
--- a/indra/llmessage/llxfermanager.h
+++ b/indra/llmessage/llxfermanager.h
@@ -1,223 +1,223 @@
-/**
- * @file llxfermanager.h
- * @brief definition of LLXferManager class for a keeping track of
- * multiple xfers
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLXFERMANAGER_H
-#define LL_LLXFERMANAGER_H
-
-/**
- * this manager keeps both a send list and a receive list; anything with a
- * LLXferManager can send and receive files via messages
- */
-
-//Forward declaration to avoid circular dependencies
-class LLXfer;
-
-#include "llxfer.h"
-#include "message.h"
-#include "llassetstorage.h"
-#include "lldir.h"
-#include <deque>
-#include "llthrottle.h"
-
-class LLHostStatus
-{
- public:
- LLHost mHost;
- S32 mNumActive;
- S32 mNumPending;
-
- LLHostStatus() {mNumActive = 0; mNumPending = 0;};
- virtual ~LLHostStatus(){};
-};
-
-// Class stores ack information, to be put on list so we can throttle xfer rate.
-class LLXferAckInfo
-{
-public:
- LLXferAckInfo(U32 dummy = 0)
- {
- mID = 0;
- mPacketNum = -1;
- }
-
- U64 mID;
- S32 mPacketNum;
- LLHost mRemoteHost;
-};
-
-class LLXferManager
-{
- protected:
- S32 mMaxOutgoingXfersPerCircuit;
- S32 mHardLimitOutgoingXfersPerCircuit; // At this limit, kill off the connection
- S32 mMaxIncomingXfers;
-
- bool mUseAckThrottling; // Use ack throttling to cap file xfer bandwidth
- std::deque<LLXferAckInfo> mXferAckQueue;
- LLThrottle mAckThrottle;
- public:
-
- // This enumeration is useful in the requestFile() to specify if
- // an xfer must happen asap.
- enum
- {
- LOW_PRIORITY = false,
- HIGH_PRIORITY = true,
- };
-
- // Linked FIFO list, add to the front and pull from back
- typedef std::deque<LLXfer *> xfer_list_t;
- xfer_list_t mSendList;
- xfer_list_t mReceiveList;
-
- typedef std::list<LLHostStatus*> status_list_t;
- status_list_t mOutgoingHosts;
-
- protected:
- // implementation methods
- virtual void startPendingDownloads();
- virtual void addToList(LLXfer* xferp, xfer_list_t & xfer_list, bool is_priority);
- std::multiset<std::string> mExpectedTransfers; // files that are authorized to transfer out
- std::multiset<std::string> mExpectedRequests; // files that are authorized to be downloaded on top of
- std::multiset<std::string> mExpectedVFileTransfers; // files that are authorized to transfer out
- std::multiset<std::string> mExpectedVFileRequests; // files that are authorized to be downloaded on top of
-
- public:
- LLXferManager();
- virtual ~LLXferManager();
-
- virtual void init();
- virtual void cleanup();
-
- void setUseAckThrottling(const bool use);
- void setAckThrottleBPS(const F32 bps);
-
-// list management routines
- virtual LLXfer *findXferByID(U64 id, xfer_list_t & xfer_list);
- virtual void removeXfer (LLXfer *delp, xfer_list_t & xfer_list);
-
- LLHostStatus * findHostStatus(const LLHost &host);
- virtual S32 numActiveXfers(const LLHost &host);
- virtual S32 numPendingXfers(const LLHost &host);
-
- virtual void changeNumActiveXfers(const LLHost &host, S32 delta);
-
- virtual void setMaxOutgoingXfersPerCircuit (S32 max_num);
- virtual void setHardLimitOutgoingXfersPerCircuit(S32 max_num);
- virtual void setMaxIncomingXfers(S32 max_num);
- virtual void updateHostStatus();
- virtual void printHostStatus();
-
-// general utility routines
- virtual void registerCallbacks(LLMessageSystem *mesgsys);
- virtual U64 getNextID ();
- virtual S32 encodePacketNum(S32 packet_num, bool is_eof);
- virtual S32 decodePacketNum(S32 packet_num);
- virtual bool isLastPacket(S32 packet_num);
-
-// file requesting routines
-// .. to file
- virtual U64 requestFile(const std::string& local_filename,
- const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost& remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void**,S32,LLExtStat), void** user_data,
- bool is_priority = false,
- bool use_big_packets = false);
- /*
-// .. to memory
- virtual void requestFile(const std::string& remote_filename,
- ELLPath remote_path,
- const LLHost &remote_host,
- bool delete_remote_on_completion,
- void (*callback)(void*, S32, void**, S32, LLExtStat),
- void** user_data,
- bool is_priority = false);
- */
-// vfile requesting
-// .. to vfile
- virtual void requestVFile(const LLUUID &local_id, const LLUUID& remote_id,
- LLAssetType::EType type,
- const LLHost& remote_host,
- void (*callback)(void**,S32,LLExtStat), void** user_data,
- bool is_priority = false);
- /**
- When arbitrary files are requested to be transfered (by giving a dir of LL_PATH_NONE)
- they must be "expected", but having something pre-authorize them. This pair of functions
- maintains a pre-authorized list. The first function adds something to the list, the second
- checks if is authorized, removing it if so. In this way, a file is only authorized for
- a single use.
- */
- virtual void expectFileForTransfer(const std::string& filename);
- virtual bool validateFileForTransfer(const std::string& filename);
- /**
- Same idea, but for the viewer about to call InitiateDownload to track what it requested.
- */
- virtual void expectFileForRequest(const std::string& filename);
- virtual bool validateFileForRequest(const std::string& filename);
-
- /**
- Same idea but for VFiles, kept separate to avoid namespace overlap
- */
- /* Present in fireengine, not used by viewer
- virtual void expectVFileForTransfer(const std::string& filename);
- virtual bool validateVFileForTransfer(const std::string& filename);
- virtual void expectVFileForRequest(const std::string& filename);
- virtual bool validateVFileForRequest(const std::string& filename);
- */
-
- virtual void processReceiveData (LLMessageSystem *mesgsys, void **user_data);
- virtual void sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host);
-
-// file sending routines
- virtual void processFileRequest (LLMessageSystem *mesgsys, void **user_data);
- virtual void processConfirmation (LLMessageSystem *mesgsys, void **user_data);
- virtual void retransmitUnackedPackets ();
-
-// error handling
- void abortRequestById(U64 xfer_id, S32 result_code);
- virtual void processAbort (LLMessageSystem *mesgsys, void **user_data);
-
- virtual bool isHostFlooded(const LLHost & host);
-};
-
-extern LLXferManager* gXferManager;
-
-// initialization and garbage collection
-void start_xfer_manager();
-void cleanup_xfer_manager();
-
-// message system callbacks
-void process_confirm_packet (LLMessageSystem *mesgsys, void **user_data);
-void process_request_xfer (LLMessageSystem *mesgsys, void **user_data);
-void continue_file_receive(LLMessageSystem *mesgsys, void **user_data);
-void process_abort_xfer (LLMessageSystem *mesgsys, void **user_data);
-#endif
-
-
-
+/**
+ * @file llxfermanager.h
+ * @brief definition of LLXferManager class for a keeping track of
+ * multiple xfers
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLXFERMANAGER_H
+#define LL_LLXFERMANAGER_H
+
+/**
+ * this manager keeps both a send list and a receive list; anything with a
+ * LLXferManager can send and receive files via messages
+ */
+
+//Forward declaration to avoid circular dependencies
+class LLXfer;
+
+#include "llxfer.h"
+#include "message.h"
+#include "llassetstorage.h"
+#include "lldir.h"
+#include <deque>
+#include "llthrottle.h"
+
+class LLHostStatus
+{
+ public:
+ LLHost mHost;
+ S32 mNumActive;
+ S32 mNumPending;
+
+ LLHostStatus() {mNumActive = 0; mNumPending = 0;};
+ virtual ~LLHostStatus(){};
+};
+
+// Class stores ack information, to be put on list so we can throttle xfer rate.
+class LLXferAckInfo
+{
+public:
+ LLXferAckInfo(U32 dummy = 0)
+ {
+ mID = 0;
+ mPacketNum = -1;
+ }
+
+ U64 mID;
+ S32 mPacketNum;
+ LLHost mRemoteHost;
+};
+
+class LLXferManager
+{
+ protected:
+ S32 mMaxOutgoingXfersPerCircuit;
+ S32 mHardLimitOutgoingXfersPerCircuit; // At this limit, kill off the connection
+ S32 mMaxIncomingXfers;
+
+ bool mUseAckThrottling; // Use ack throttling to cap file xfer bandwidth
+ std::deque<LLXferAckInfo> mXferAckQueue;
+ LLThrottle mAckThrottle;
+ public:
+
+ // This enumeration is useful in the requestFile() to specify if
+ // an xfer must happen asap.
+ enum
+ {
+ LOW_PRIORITY = false,
+ HIGH_PRIORITY = true,
+ };
+
+ // Linked FIFO list, add to the front and pull from back
+ typedef std::deque<LLXfer *> xfer_list_t;
+ xfer_list_t mSendList;
+ xfer_list_t mReceiveList;
+
+ typedef std::list<LLHostStatus*> status_list_t;
+ status_list_t mOutgoingHosts;
+
+ protected:
+ // implementation methods
+ virtual void startPendingDownloads();
+ virtual void addToList(LLXfer* xferp, xfer_list_t & xfer_list, bool is_priority);
+ std::multiset<std::string> mExpectedTransfers; // files that are authorized to transfer out
+ std::multiset<std::string> mExpectedRequests; // files that are authorized to be downloaded on top of
+ std::multiset<std::string> mExpectedVFileTransfers; // files that are authorized to transfer out
+ std::multiset<std::string> mExpectedVFileRequests; // files that are authorized to be downloaded on top of
+
+ public:
+ LLXferManager();
+ virtual ~LLXferManager();
+
+ virtual void init();
+ virtual void cleanup();
+
+ void setUseAckThrottling(const bool use);
+ void setAckThrottleBPS(const F32 bps);
+
+// list management routines
+ virtual LLXfer *findXferByID(U64 id, xfer_list_t & xfer_list);
+ virtual void removeXfer (LLXfer *delp, xfer_list_t & xfer_list);
+
+ LLHostStatus * findHostStatus(const LLHost &host);
+ virtual S32 numActiveXfers(const LLHost &host);
+ virtual S32 numPendingXfers(const LLHost &host);
+
+ virtual void changeNumActiveXfers(const LLHost &host, S32 delta);
+
+ virtual void setMaxOutgoingXfersPerCircuit (S32 max_num);
+ virtual void setHardLimitOutgoingXfersPerCircuit(S32 max_num);
+ virtual void setMaxIncomingXfers(S32 max_num);
+ virtual void updateHostStatus();
+ virtual void printHostStatus();
+
+// general utility routines
+ virtual void registerCallbacks(LLMessageSystem *mesgsys);
+ virtual U64 getNextID ();
+ virtual S32 encodePacketNum(S32 packet_num, bool is_eof);
+ virtual S32 decodePacketNum(S32 packet_num);
+ virtual bool isLastPacket(S32 packet_num);
+
+// file requesting routines
+// .. to file
+ virtual U64 requestFile(const std::string& local_filename,
+ const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost& remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void**,S32,LLExtStat), void** user_data,
+ bool is_priority = false,
+ bool use_big_packets = false);
+ /*
+// .. to memory
+ virtual void requestFile(const std::string& remote_filename,
+ ELLPath remote_path,
+ const LLHost &remote_host,
+ bool delete_remote_on_completion,
+ void (*callback)(void*, S32, void**, S32, LLExtStat),
+ void** user_data,
+ bool is_priority = false);
+ */
+// vfile requesting
+// .. to vfile
+ virtual void requestVFile(const LLUUID &local_id, const LLUUID& remote_id,
+ LLAssetType::EType type,
+ const LLHost& remote_host,
+ void (*callback)(void**,S32,LLExtStat), void** user_data,
+ bool is_priority = false);
+ /**
+ When arbitrary files are requested to be transfered (by giving a dir of LL_PATH_NONE)
+ they must be "expected", but having something pre-authorize them. This pair of functions
+ maintains a pre-authorized list. The first function adds something to the list, the second
+ checks if is authorized, removing it if so. In this way, a file is only authorized for
+ a single use.
+ */
+ virtual void expectFileForTransfer(const std::string& filename);
+ virtual bool validateFileForTransfer(const std::string& filename);
+ /**
+ Same idea, but for the viewer about to call InitiateDownload to track what it requested.
+ */
+ virtual void expectFileForRequest(const std::string& filename);
+ virtual bool validateFileForRequest(const std::string& filename);
+
+ /**
+ Same idea but for VFiles, kept separate to avoid namespace overlap
+ */
+ /* Present in fireengine, not used by viewer
+ virtual void expectVFileForTransfer(const std::string& filename);
+ virtual bool validateVFileForTransfer(const std::string& filename);
+ virtual void expectVFileForRequest(const std::string& filename);
+ virtual bool validateVFileForRequest(const std::string& filename);
+ */
+
+ virtual void processReceiveData (LLMessageSystem *mesgsys, void **user_data);
+ virtual void sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 packetnum, const LLHost &remote_host);
+
+// file sending routines
+ virtual void processFileRequest (LLMessageSystem *mesgsys, void **user_data);
+ virtual void processConfirmation (LLMessageSystem *mesgsys, void **user_data);
+ virtual void retransmitUnackedPackets ();
+
+// error handling
+ void abortRequestById(U64 xfer_id, S32 result_code);
+ virtual void processAbort (LLMessageSystem *mesgsys, void **user_data);
+
+ virtual bool isHostFlooded(const LLHost & host);
+};
+
+extern LLXferManager* gXferManager;
+
+// initialization and garbage collection
+void start_xfer_manager();
+void cleanup_xfer_manager();
+
+// message system callbacks
+void process_confirm_packet (LLMessageSystem *mesgsys, void **user_data);
+void process_request_xfer (LLMessageSystem *mesgsys, void **user_data);
+void continue_file_receive(LLMessageSystem *mesgsys, void **user_data);
+void process_abort_xfer (LLMessageSystem *mesgsys, void **user_data);
+#endif
+
+
+
diff --git a/indra/llmessage/llxorcipher.cpp b/indra/llmessage/llxorcipher.cpp
index 17651b1ecf..2770200fe5 100644
--- a/indra/llmessage/llxorcipher.cpp
+++ b/indra/llmessage/llxorcipher.cpp
@@ -1,128 +1,128 @@
-/**
- * @file llxorcipher.cpp
- * @brief Implementation of LLXORCipher
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llxorcipher.h"
-
-#include "llerror.h"
-
-///----------------------------------------------------------------------------
-/// Class LLXORCipher
-///----------------------------------------------------------------------------
-
-LLXORCipher::LLXORCipher(const U8* pad, U32 pad_len) :
- mPad(NULL),
- mHead(NULL),
- mPadLen(0)
-{
- init(pad, pad_len);
-}
-
-// Destroys the object
-LLXORCipher::~LLXORCipher()
-{
- init(NULL, 0);
-}
-
-LLXORCipher::LLXORCipher(const LLXORCipher& cipher) :
- mPad(NULL),
- mHead(NULL),
- mPadLen(0)
-{
- init(cipher.mPad, cipher.mPadLen);
-}
-
-LLXORCipher& LLXORCipher::operator=(const LLXORCipher& cipher)
-{
- if(this == &cipher) return *this;
- init(cipher.mPad, cipher.mPadLen);
- return *this;
-}
-
-U32 LLXORCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
-{
- if(!src || !src_len || !dst || !dst_len || !mPad) return 0;
- U8* pad_end = mPad + mPadLen;
- U32 count = src_len;
- while(count--)
- {
- *dst++ = *src++ ^ *mHead++;
- if(mHead >= pad_end) mHead = mPad;
- }
- return src_len;
-}
-
-U32 LLXORCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
-{
- // xor is a symetric cipher, thus, just call the other function.
- return encrypt(src, src_len, dst, dst_len);
-}
-
-U32 LLXORCipher::requiredEncryptionSpace(U32 len) const
-{
- return len;
-}
-
-void LLXORCipher::init(const U8* pad, U32 pad_len)
-{
- if(mPad)
- {
- delete [] mPad;
- mPad = NULL;
- mPadLen = 0;
- }
- if(pad && pad_len)
- {
- mPadLen = pad_len;
- mPad = new U8[mPadLen];
- if (mPad != NULL)
- {
- memcpy(mPad, pad, mPadLen); /* Flawfinder : ignore */
- }
- }
- mHead = mPad;
-}
-
-#ifdef _DEBUG
-// static
-bool LLXORCipher::testHarness()
-{
- const U32 PAD_LEN = 3;
- const U8 PAD[] = "abc";
- const S32 MSG_LENGTH = 12;
- const char MESSAGE[MSG_LENGTH+1] = "gesundheight"; /* Flawfinder : ignore */
- U8 encrypted[MSG_LENGTH];
- U8 decrypted[MSG_LENGTH];
-
- LLXORCipher cipher(PAD, PAD_LEN);
- cipher.encrypt((U8*)MESSAGE, MSG_LENGTH, encrypted, MSG_LENGTH);
- cipher.decrypt(encrypted, MSG_LENGTH, decrypted, MSG_LENGTH);
-
- if(0 != memcmp((void*)MESSAGE, decrypted, MSG_LENGTH)) return false;
- return true;
-}
-#endif
+/**
+ * @file llxorcipher.cpp
+ * @brief Implementation of LLXORCipher
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llxorcipher.h"
+
+#include "llerror.h"
+
+///----------------------------------------------------------------------------
+/// Class LLXORCipher
+///----------------------------------------------------------------------------
+
+LLXORCipher::LLXORCipher(const U8* pad, U32 pad_len) :
+ mPad(NULL),
+ mHead(NULL),
+ mPadLen(0)
+{
+ init(pad, pad_len);
+}
+
+// Destroys the object
+LLXORCipher::~LLXORCipher()
+{
+ init(NULL, 0);
+}
+
+LLXORCipher::LLXORCipher(const LLXORCipher& cipher) :
+ mPad(NULL),
+ mHead(NULL),
+ mPadLen(0)
+{
+ init(cipher.mPad, cipher.mPadLen);
+}
+
+LLXORCipher& LLXORCipher::operator=(const LLXORCipher& cipher)
+{
+ if(this == &cipher) return *this;
+ init(cipher.mPad, cipher.mPadLen);
+ return *this;
+}
+
+U32 LLXORCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ if(!src || !src_len || !dst || !dst_len || !mPad) return 0;
+ U8* pad_end = mPad + mPadLen;
+ U32 count = src_len;
+ while(count--)
+ {
+ *dst++ = *src++ ^ *mHead++;
+ if(mHead >= pad_end) mHead = mPad;
+ }
+ return src_len;
+}
+
+U32 LLXORCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
+{
+ // xor is a symetric cipher, thus, just call the other function.
+ return encrypt(src, src_len, dst, dst_len);
+}
+
+U32 LLXORCipher::requiredEncryptionSpace(U32 len) const
+{
+ return len;
+}
+
+void LLXORCipher::init(const U8* pad, U32 pad_len)
+{
+ if(mPad)
+ {
+ delete [] mPad;
+ mPad = NULL;
+ mPadLen = 0;
+ }
+ if(pad && pad_len)
+ {
+ mPadLen = pad_len;
+ mPad = new U8[mPadLen];
+ if (mPad != NULL)
+ {
+ memcpy(mPad, pad, mPadLen); /* Flawfinder : ignore */
+ }
+ }
+ mHead = mPad;
+}
+
+#ifdef _DEBUG
+// static
+bool LLXORCipher::testHarness()
+{
+ const U32 PAD_LEN = 3;
+ const U8 PAD[] = "abc";
+ const S32 MSG_LENGTH = 12;
+ const char MESSAGE[MSG_LENGTH+1] = "gesundheight"; /* Flawfinder : ignore */
+ U8 encrypted[MSG_LENGTH];
+ U8 decrypted[MSG_LENGTH];
+
+ LLXORCipher cipher(PAD, PAD_LEN);
+ cipher.encrypt((U8*)MESSAGE, MSG_LENGTH, encrypted, MSG_LENGTH);
+ cipher.decrypt(encrypted, MSG_LENGTH, decrypted, MSG_LENGTH);
+
+ if(0 != memcmp((void*)MESSAGE, decrypted, MSG_LENGTH)) return false;
+ return true;
+}
+#endif
diff --git a/indra/llmessage/llxorcipher.h b/indra/llmessage/llxorcipher.h
index cd1fed3ba4..14cea5dc02 100644
--- a/indra/llmessage/llxorcipher.h
+++ b/indra/llmessage/llxorcipher.h
@@ -1,67 +1,67 @@
-/**
- * @file llxorcipher.h
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LLXORCIPHER_H
-#define LLXORCIPHER_H
-
-#include "llcipher.h"
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLXORCipher
-//
-// Implementation of LLCipher which encrypts using a XOR pad.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLXORCipher : public LLCipher
-{
-public:
- LLXORCipher(const U8* pad, U32 pad_len);
- LLXORCipher(const LLXORCipher& cipher);
- virtual ~LLXORCipher();
- LLXORCipher& operator=(const LLXORCipher& cipher);
-
- // Cipher functions
- U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override;
- U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override;
- U32 requiredEncryptionSpace(U32 src_len) const override;
-
- // special syntactic-sugar since xor can be performed in place.
- bool encrypt(U8* buf, U32 len) { return encrypt((const U8*)buf, len, buf, len) > 0; }
- bool decrypt(U8* buf, U32 len) { return decrypt((const U8*)buf, len, buf, len) > 0; }
-
-#ifdef _DEBUG
- // This function runs tests to make sure the crc is
- // working. Returns true if it is.
- static bool testHarness();
-#endif
-
-protected:
- void init(const U8* pad, U32 pad_len);
- U8* mPad;
- U8* mHead;
- U32 mPadLen;
-};
-
-#endif
+/**
+ * @file llxorcipher.h
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLXORCIPHER_H
+#define LLXORCIPHER_H
+
+#include "llcipher.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLXORCipher
+//
+// Implementation of LLCipher which encrypts using a XOR pad.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLXORCipher : public LLCipher
+{
+public:
+ LLXORCipher(const U8* pad, U32 pad_len);
+ LLXORCipher(const LLXORCipher& cipher);
+ virtual ~LLXORCipher();
+ LLXORCipher& operator=(const LLXORCipher& cipher);
+
+ // Cipher functions
+ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override;
+ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override;
+ U32 requiredEncryptionSpace(U32 src_len) const override;
+
+ // special syntactic-sugar since xor can be performed in place.
+ bool encrypt(U8* buf, U32 len) { return encrypt((const U8*)buf, len, buf, len) > 0; }
+ bool decrypt(U8* buf, U32 len) { return decrypt((const U8*)buf, len, buf, len) > 0; }
+
+#ifdef _DEBUG
+ // This function runs tests to make sure the crc is
+ // working. Returns true if it is.
+ static bool testHarness();
+#endif
+
+protected:
+ void init(const U8* pad, U32 pad_len);
+ U8* mPad;
+ U8* mHead;
+ U32 mPadLen;
+};
+
+#endif
diff --git a/indra/llmessage/machine.cpp b/indra/llmessage/machine.cpp
index 1e9c9c3c9a..feb4ebfa8b 100644
--- a/indra/llmessage/machine.cpp
+++ b/indra/llmessage/machine.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file machine.cpp
* @brief LLMachine class header file
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,27 +30,27 @@
#include "llerror.h"
void LLMachine::setMachinePort(S32 port)
-{
- if (port < 0)
- {
- LL_INFOS() << "Can't assign a negative number to LLMachine::mPort" << LL_ENDL;
- mHost.setPort(0);
- }
- else
- {
- mHost.setPort(port);
- }
+{
+ if (port < 0)
+ {
+ LL_INFOS() << "Can't assign a negative number to LLMachine::mPort" << LL_ENDL;
+ mHost.setPort(0);
+ }
+ else
+ {
+ mHost.setPort(port);
+ }
}
-void LLMachine::setControlPort( S32 port )
+void LLMachine::setControlPort( S32 port )
{
- if (port < 0)
- {
- LL_INFOS() << "Can't assign a negative number to LLMachine::mControlPort" << LL_ENDL;
- mControlPort = 0;
- }
- else
- {
- mControlPort = port;
- }
+ if (port < 0)
+ {
+ LL_INFOS() << "Can't assign a negative number to LLMachine::mControlPort" << LL_ENDL;
+ mControlPort = 0;
+ }
+ else
+ {
+ mControlPort = port;
+ }
}
diff --git a/indra/llmessage/machine.h b/indra/llmessage/machine.h
index 831503741c..67e890d19a 100644
--- a/indra/llmessage/machine.h
+++ b/indra/llmessage/machine.h
@@ -1,95 +1,95 @@
-/**
- * @file machine.h
- * @brief LLMachine class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_MACHINE_H
-#define LL_MACHINE_H
-
-#include "net.h"
-#include "llhost.h"
-
-typedef enum e_machine_type
-{
- MT_NULL,
- MT_SIMULATOR,
- MT_VIEWER,
- MT_SPACE_SERVER,
- MT_OBJECT_REPOSITORY,
- MT_PROXY,
- MT_EOF
-} EMachineType;
-
-const U32 ADDRESS_STRING_SIZE = 12;
-
-class LLMachine
-{
-public:
- LLMachine()
- : mMachineType(MT_NULL), mControlPort(0) {}
-
- LLMachine(EMachineType machine_type, U32 ip, S32 port)
- : mMachineType(machine_type), mControlPort(0), mHost(ip,port) {}
-
- LLMachine(EMachineType machine_type, const LLHost &host)
- : mMachineType(machine_type) {mHost = host; mControlPort = 0;}
-
- ~LLMachine() {}
-
- // get functions
- EMachineType getMachineType() const { return mMachineType; }
- U32 getMachineIP() const { return mHost.getAddress(); }
- S32 getMachinePort() const { return mHost.getPort(); }
- const LLHost &getMachineHost() const { return mHost; }
- // The control port is the listen port of the parent process that
- // launched this machine. 0 means none or not known.
- const S32 &getControlPort() const { return mControlPort; }
- bool isValid() const { return (mHost.getPort() != 0); } // true if corresponds to functioning machine
-
- // set functions
- void setMachineType(EMachineType machine_type) { mMachineType = machine_type; }
- void setMachineIP(U32 ip) { mHost.setAddress(ip); }
- void setMachineHost(const LLHost &host) { mHost = host; }
-
- void setMachinePort(S32 port);
- void setControlPort( S32 port );
-
-
- // member variables
-
-// Someday these should be made private.
-// When they are, some of the code that breaks should
-// become member functions of LLMachine -- Leviathan
-//private:
-
- // I fixed the others, somebody should fix these! - djs
- EMachineType mMachineType;
-
-protected:
-
- S32 mControlPort;
- LLHost mHost;
-};
-
-#endif
+/**
+ * @file machine.h
+ * @brief LLMachine class header file
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_MACHINE_H
+#define LL_MACHINE_H
+
+#include "net.h"
+#include "llhost.h"
+
+typedef enum e_machine_type
+{
+ MT_NULL,
+ MT_SIMULATOR,
+ MT_VIEWER,
+ MT_SPACE_SERVER,
+ MT_OBJECT_REPOSITORY,
+ MT_PROXY,
+ MT_EOF
+} EMachineType;
+
+const U32 ADDRESS_STRING_SIZE = 12;
+
+class LLMachine
+{
+public:
+ LLMachine()
+ : mMachineType(MT_NULL), mControlPort(0) {}
+
+ LLMachine(EMachineType machine_type, U32 ip, S32 port)
+ : mMachineType(machine_type), mControlPort(0), mHost(ip,port) {}
+
+ LLMachine(EMachineType machine_type, const LLHost &host)
+ : mMachineType(machine_type) {mHost = host; mControlPort = 0;}
+
+ ~LLMachine() {}
+
+ // get functions
+ EMachineType getMachineType() const { return mMachineType; }
+ U32 getMachineIP() const { return mHost.getAddress(); }
+ S32 getMachinePort() const { return mHost.getPort(); }
+ const LLHost &getMachineHost() const { return mHost; }
+ // The control port is the listen port of the parent process that
+ // launched this machine. 0 means none or not known.
+ const S32 &getControlPort() const { return mControlPort; }
+ bool isValid() const { return (mHost.getPort() != 0); } // true if corresponds to functioning machine
+
+ // set functions
+ void setMachineType(EMachineType machine_type) { mMachineType = machine_type; }
+ void setMachineIP(U32 ip) { mHost.setAddress(ip); }
+ void setMachineHost(const LLHost &host) { mHost = host; }
+
+ void setMachinePort(S32 port);
+ void setControlPort( S32 port );
+
+
+ // member variables
+
+// Someday these should be made private.
+// When they are, some of the code that breaks should
+// become member functions of LLMachine -- Leviathan
+//private:
+
+ // I fixed the others, somebody should fix these! - djs
+ EMachineType mMachineType;
+
+protected:
+
+ S32 mControlPort;
+ LLHost mHost;
+};
+
+#endif
diff --git a/indra/llmessage/mean_collision_data.h b/indra/llmessage/mean_collision_data.h
index 29de091603..5b5b3f2fd2 100644
--- a/indra/llmessage/mean_collision_data.h
+++ b/indra/llmessage/mean_collision_data.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file mean_collision_data.h
* @brief data type to log interactions between stuff and agents that
* might be community standards violations
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,60 +36,60 @@ const S32 MAX_MEAN_COLLISIONS = 5;
typedef enum e_mean_collision_types
{
- MEAN_INVALID,
- MEAN_BUMP,
- MEAN_LLPUSHOBJECT,
- MEAN_SELECTED_OBJECT_COLLIDE,
- MEAN_SCRIPTED_OBJECT_COLLIDE,
- MEAN_PHYSICAL_OBJECT_COLLIDE,
- MEAN_EOF
+ MEAN_INVALID,
+ MEAN_BUMP,
+ MEAN_LLPUSHOBJECT,
+ MEAN_SELECTED_OBJECT_COLLIDE,
+ MEAN_SCRIPTED_OBJECT_COLLIDE,
+ MEAN_PHYSICAL_OBJECT_COLLIDE,
+ MEAN_EOF
} EMeanCollisionType;
class LLMeanCollisionData
{
public:
- LLMeanCollisionData(const LLUUID &victim, const LLUUID &perp, time_t time, EMeanCollisionType type, F32 mag)
- : mVictim(victim), mPerp(perp), mTime(time), mType(type), mMag(mag)
- {
- }
-
- LLMeanCollisionData(LLMeanCollisionData *mcd)
- : mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
- mFullName(mcd->mFullName)
- {
- }
-
- friend std::ostream& operator<<(std::ostream& s, const LLMeanCollisionData &a)
- {
- switch(a.mType)
- {
- case MEAN_BUMP:
- s << "Mean Collision: " << a.mPerp << " bumped " << a.mVictim << " with a velocity of " << a.mMag << " at " << ctime(&a.mTime);
- break;
- case MEAN_LLPUSHOBJECT:
- s << "Mean Collision: " << a.mPerp << " llPushObject-ed " << a.mVictim << " with a total force of " << a.mMag << " at "<< ctime(&a.mTime);
- break;
- case MEAN_SELECTED_OBJECT_COLLIDE:
- s << "Mean Collision: " << a.mPerp << " dragged an object into " << a.mVictim << " with a velocity of " << a.mMag << " at "<< ctime(&a.mTime);
- break;
- case MEAN_SCRIPTED_OBJECT_COLLIDE:
- s << "Mean Collision: " << a.mPerp << " smacked " << a.mVictim << " with a scripted object with velocity of " << a.mMag << " at "<< ctime(&a.mTime);
- break;
- case MEAN_PHYSICAL_OBJECT_COLLIDE:
- s << "Mean Collision: " << a.mPerp << " smacked " << a.mVictim << " with a physical object with velocity of " << a.mMag << " at "<< ctime(&a.mTime);
- break;
- default:
- break;
- }
- return s;
- }
+ LLMeanCollisionData(const LLUUID &victim, const LLUUID &perp, time_t time, EMeanCollisionType type, F32 mag)
+ : mVictim(victim), mPerp(perp), mTime(time), mType(type), mMag(mag)
+ {
+ }
+
+ LLMeanCollisionData(LLMeanCollisionData *mcd)
+ : mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
+ mFullName(mcd->mFullName)
+ {
+ }
+
+ friend std::ostream& operator<<(std::ostream& s, const LLMeanCollisionData &a)
+ {
+ switch(a.mType)
+ {
+ case MEAN_BUMP:
+ s << "Mean Collision: " << a.mPerp << " bumped " << a.mVictim << " with a velocity of " << a.mMag << " at " << ctime(&a.mTime);
+ break;
+ case MEAN_LLPUSHOBJECT:
+ s << "Mean Collision: " << a.mPerp << " llPushObject-ed " << a.mVictim << " with a total force of " << a.mMag << " at "<< ctime(&a.mTime);
+ break;
+ case MEAN_SELECTED_OBJECT_COLLIDE:
+ s << "Mean Collision: " << a.mPerp << " dragged an object into " << a.mVictim << " with a velocity of " << a.mMag << " at "<< ctime(&a.mTime);
+ break;
+ case MEAN_SCRIPTED_OBJECT_COLLIDE:
+ s << "Mean Collision: " << a.mPerp << " smacked " << a.mVictim << " with a scripted object with velocity of " << a.mMag << " at "<< ctime(&a.mTime);
+ break;
+ case MEAN_PHYSICAL_OBJECT_COLLIDE:
+ s << "Mean Collision: " << a.mPerp << " smacked " << a.mVictim << " with a physical object with velocity of " << a.mMag << " at "<< ctime(&a.mTime);
+ break;
+ default:
+ break;
+ }
+ return s;
+ }
- LLUUID mVictim;
- LLUUID mPerp;
- time_t mTime;
- EMeanCollisionType mType;
- F32 mMag;
- std::string mFullName;
+ LLUUID mVictim;
+ LLUUID mPerp;
+ time_t mTime;
+ EMeanCollisionType mType;
+ F32 mMag;
+ std::string mFullName;
};
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index 272bf9b672..b57f8f4513 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -1,4055 +1,4055 @@
-/**
- * @file message.cpp
- * @brief LLMessageSystem class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "message.h"
-
-// system library includes
-#if !LL_WINDOWS
-// following header files required for inet_addr()
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#endif
-#include <iomanip>
-#include <iterator>
-#include <sstream>
-
-#include "llapr.h"
-#include "apr_portable.h"
-#include "apr_network_io.h"
-#include "apr_poll.h"
-
-// linden library headers
-#include "llapp.h"
-#include "indra_constants.h"
-#include "lldir.h"
-#include "llerror.h"
-#include "llfasttimer.h"
-#include "llhttpnodeadapter.h"
-#include "llmd5.h"
-#include "llmessagebuilder.h"
-#include "llmessageconfig.h"
-#include "lltemplatemessagedispatcher.h"
-#include "llpumpio.h"
-#include "lltemplatemessagebuilder.h"
-#include "lltemplatemessagereader.h"
-#include "lltrustedmessageservice.h"
-#include "llmessagetemplate.h"
-#include "llmessagetemplateparser.h"
-#include "llsd.h"
-#include "llsdmessagebuilder.h"
-#include "llsdmessagereader.h"
-#include "llsdserialize.h"
-#include "llstring.h"
-#include "lltransfermanager.h"
-#include "lluuid.h"
-#include "llxfermanager.h"
-#include "llquaternion.h"
-#include "u64.h"
-#include "v3dmath.h"
-#include "v3math.h"
-#include "v4math.h"
-#include "lltransfertargetvfile.h"
-#include "llcorehttputil.h"
-#include "llpounceable.h"
-
-// Constants
-//const char* MESSAGE_LOG_FILENAME = "message.log";
-static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f);
-static const S32 TRUST_TIME_WINDOW = 3;
-
-// *NOTE: This needs to be moved into a seperate file so that it never gets
-// included in the viewer. 30 Sep 2002 mark
-// *NOTE: I don't think it's important that the messgage system tracks
-// this since it must get set externally. 2004.08.25 Phoenix.
-static std::string g_shared_secret;
-std::string get_shared_secret();
-
-class LLMessagePollInfo
-{
-public:
- apr_socket_t *mAPRSocketp;
- apr_pollfd_t mPollFD;
-};
-
-class LLMessageHandlerBridge : public LLHTTPNode
-{
- virtual bool validate(const std::string& name, LLSD& context) const
- { return true; }
-
- virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context,
- const LLSD& input) const;
-};
-
-//virtual
-void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response,
- const LLSD& context, const LLSD& input) const
-{
- std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
- char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
-
- LL_DEBUGS() << "Setting mLastSender " << input["sender"].asString() << LL_ENDL;
- gMessageSystem->mLastSender = LLHost(input["sender"].asString());
- gMessageSystem->mPacketsIn += 1;
- gMessageSystem->mLLSDMessageReader->setMessage(namePtr, input["body"]);
- LockMessageReader rdr(gMessageSystem->mMessageReader, gMessageSystem->mLLSDMessageReader);
-
- if(gMessageSystem->callHandler(namePtr, false, gMessageSystem))
- {
- response->result(LLSD());
- }
- else
- {
- response->notFound();
- }
-}
-
-LLHTTPRegistration<LLMessageHandlerBridge>
- gHTTPRegistrationMessageWildcard("/message/<message-name>");
-
-//virtual
-LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
-{
- // even abstract base classes need a concrete destructor
-}
-
-static const char* nullToEmpty(const char* s)
-{
- static char emptyString[] = "";
- return s? s : emptyString;
-}
-
-void LLMessageSystem::init()
-{
- // initialize member variables
- mVerboseLog = false;
-
- mbError = false;
- mErrorCode = 0;
- mSendReliable = false;
-
- mUnackedListDepth = 0;
- mUnackedListSize = 0;
- mDSMaxListDepth = 0;
-
- mNumberHighFreqMessages = 0;
- mNumberMediumFreqMessages = 0;
- mNumberLowFreqMessages = 0;
- mPacketsIn = mPacketsOut = 0;
- mBytesIn = mBytesOut = 0;
- mCompressedPacketsIn = mCompressedPacketsOut = 0;
- mReliablePacketsIn = mReliablePacketsOut = 0;
-
- mCompressedBytesIn = 0;
- mCompressedBytesOut = 0;
- mUncompressedBytesIn = 0;
- mUncompressedBytesOut = 0;
- mTotalBytesIn = 0;
- mTotalBytesOut = 0;
-
- mDroppedPackets = 0; // total dropped packets in
- mResentPackets = 0; // total resent packets out
- mFailedResendPackets = 0; // total resend failure packets out
- mOffCircuitPackets = 0; // total # of off-circuit packets rejected
- mInvalidOnCircuitPackets = 0; // total # of on-circuit packets rejected
-
- mOurCircuitCode = 0;
-
- mIncomingCompressedSize = 0;
- mCurrentRecvPacketID = 0;
-
- mMessageFileVersionNumber = 0.f;
-
- mTimingCallback = NULL;
- mTimingCallbackData = NULL;
-
- mMessageBuilder = NULL;
- LockMessageReader(mMessageReader, NULL);
-}
-
-// Read file and build message templates
-LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
- S32 version_major,
- S32 version_minor,
- S32 version_patch,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval, const F32 circuit_timeout) :
- mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)),
- mLastMessageFromTrustedMessageService(false)
-{
- init();
-
- mSendSize = 0;
-
- mSystemVersionMajor = version_major;
- mSystemVersionMinor = version_minor;
- mSystemVersionPatch = version_patch;
- mSystemVersionServer = 0;
- mVersionFlags = 0x0;
-
- // default to not accepting packets from not alive circuits
- mbProtected = true;
-
- // default to blocking trusted connections on a public interface if one is specified
- mBlockUntrustedInterface = true;
-
- mSendPacketFailureCount = 0;
-
- mCircuitPrintFreq = F32Seconds(60.f);
-
- loadTemplateFile(filename, failure_is_fatal);
-
- mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
- mLLSDMessageBuilder = new LLSDMessageBuilder();
- mMessageBuilder = NULL;
-
- mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
- mLLSDMessageReader = new LLSDMessageReader();
-
- // initialize various bits of net info
- mSocket = 0;
- mPort = port;
-
- S32 error = start_net(mSocket, mPort);
- if (error != 0)
- {
- mbError = true;
- mErrorCode = error;
- }
-// LL_DEBUGS("Messaging") << << "*** port: " << mPort << LL_ENDL;
-
- //
- // Create the data structure that we can poll on
- //
- if (!gAPRPoolp)
- {
- LL_ERRS("Messaging") << "No APR pool before message system initialization!" << LL_ENDL;
- ll_init_apr();
- }
- apr_socket_t *aprSocketp = NULL;
- apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
-
- mPollInfop = new LLMessagePollInfo;
- mPollInfop->mAPRSocketp = aprSocketp;
- mPollInfop->mPollFD.p = gAPRPoolp;
- mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
- mPollInfop->mPollFD.reqevents = APR_POLLIN;
- mPollInfop->mPollFD.rtnevents = 0;
- mPollInfop->mPollFD.desc.s = aprSocketp;
- mPollInfop->mPollFD.client_data = NULL;
-
- F64Seconds mt_sec = getMessageTimeSeconds();
- mResendDumpTime = mt_sec;
- mMessageCountTime = mt_sec;
- mCircuitPrintTime = mt_sec;
- mCurrentMessageTime = F64Seconds(mt_sec);
-
- // Constants for dumping output based on message processing time/count
- mNumMessageCounts = 0;
- mMaxMessageCounts = 200; // >= 0 means dump warnings
- mMaxMessageTime = F32Seconds(1.f);
-
- mTrueReceiveSize = 0;
-
- mReceiveTime = F32Seconds(0.f);
-}
-
-
-
-// Read file and build message templates
-void LLMessageSystem::loadTemplateFile(const std::string& filename, bool failure_is_fatal)
-{
- if(filename.empty())
- {
- LL_ERRS("Messaging") << "No template filename specified" << LL_ENDL;
- mbError = true;
- return;
- }
-
- std::string template_body;
- if(!_read_file_into_string(template_body, filename))
- {
- if (failure_is_fatal) {
- LL_ERRS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
- } else {
- LL_WARNS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
- }
- mbError = true;
- return;
- }
-
- LLTemplateTokenizer tokens(template_body);
- LLTemplateParser parsed(tokens);
- mMessageFileVersionNumber = parsed.getVersion();
- S32 count = 0;
- for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
- iter != parsed.getMessagesEnd();
- iter++)
- {
- addTemplate(*iter);
- count++;
- }
- LL_INFOS("Messaging") << "Read " << count << " messages from " << filename << LL_ENDL;
-}
-
-
-LLMessageSystem::~LLMessageSystem()
-{
- mMessageTemplates.clear(); // don't delete templates.
- for_each(mMessageNumbers.begin(), mMessageNumbers.end(), DeletePairedPointer());
- mMessageNumbers.clear();
-
- if (!mbError)
- {
- end_net(mSocket);
- }
- mSocket = 0;
-
- delete mTemplateMessageReader;
- mTemplateMessageReader = NULL;
-
- delete mTemplateMessageBuilder;
- mTemplateMessageBuilder = NULL;
- mMessageBuilder = NULL;
-
- delete mLLSDMessageReader;
- mLLSDMessageReader = NULL;
-
- delete mLLSDMessageBuilder;
- mLLSDMessageBuilder = NULL;
-
- delete mPollInfop;
- mPollInfop = NULL;
-
- mIncomingCompressedSize = 0;
- mCurrentRecvPacketID = 0;
-}
-
-void LLMessageSystem::clearReceiveState()
-{
- mCurrentRecvPacketID = 0;
- mIncomingCompressedSize = 0;
- mLastSender.invalidate();
- mLastReceivingIF.invalidate();
- mMessageReader->clearMessage();
- mLastMessageFromTrustedMessageService = false;
-}
-
-
-bool LLMessageSystem::poll(F32 seconds)
-{
- S32 num_socks;
- apr_status_t status;
- status = apr_poll(&(mPollInfop->mPollFD), 1, &num_socks,(U64)(seconds*1000000.f));
- if (status != APR_TIMEUP)
- {
- ll_apr_warn_status(status);
- }
- if (num_socks)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-bool LLMessageSystem::isTrustedSender(const LLHost& host) const
-{
- LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
- if(NULL == cdp)
- {
- return false;
- }
- return cdp->getTrusted();
-}
-
-void LLMessageSystem::receivedMessageFromTrustedSender()
-{
- mLastMessageFromTrustedMessageService = true;
-}
-
-bool LLMessageSystem::isTrustedSender() const
-{
- return mLastMessageFromTrustedMessageService ||
- isTrustedSender(getSender());
-}
-
-static LLMessageSystem::message_template_name_map_t::const_iterator
-findTemplate(const LLMessageSystem::message_template_name_map_t& templates,
- std::string name)
-{
- const char* namePrehash = LLMessageStringTable::getInstance()->getString(name.c_str());
- if(NULL == namePrehash) {return templates.end();}
- return templates.find(namePrehash);
-}
-
-bool LLMessageSystem::isTrustedMessage(const std::string& name) const
-{
- message_template_name_map_t::const_iterator iter =
- findTemplate(mMessageTemplates, name);
- if(iter == mMessageTemplates.end()) {return false;}
- return iter->second->getTrust() == MT_TRUST;
-}
-
-bool LLMessageSystem::isUntrustedMessage(const std::string& name) const
-{
- message_template_name_map_t::const_iterator iter =
- findTemplate(mMessageTemplates, name);
- if(iter == mMessageTemplates.end()) {return false;}
- return iter->second->getTrust() == MT_NOTRUST;
-}
-
-LLCircuitData* LLMessageSystem::findCircuit(const LLHost& host,
- bool resetPacketId)
-{
- LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- // This packet comes from a circuit we don't know about.
-
- // Are we rejecting off-circuit packets?
- if (mbProtected)
- {
- // cdp is already NULL, so we don't need to unset it.
- }
- else
- {
- // nope, open the new circuit
- cdp = mCircuitInfo.addCircuitData(host, mCurrentRecvPacketID);
-
- if(resetPacketId)
- {
- // I added this - I think it's correct - DJS
- // reset packet in ID
- cdp->setPacketInID(mCurrentRecvPacketID);
- }
- // And claim the packet is on the circuit we just added.
- }
- }
- else
- {
- // this is an old circuit. . . is it still alive?
- if (!cdp->isAlive())
- {
- // nope. don't accept if we're protected
- if (mbProtected)
- {
- // don't accept packets from unexpected sources
- cdp = NULL;
- }
- else
- {
- // wake up the circuit
- cdp->setAlive(true);
-
- if(resetPacketId)
- {
- // reset packet in ID
- cdp->setPacketInID(mCurrentRecvPacketID);
- }
- }
- }
- }
- return cdp;
-}
-
-// Returns true if a valid, on-circuit message has been received.
-// Requiring a non-const LockMessageChecker reference ensures that
-// mMessageReader has been set to mTemplateMessageReader.
-bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
-{
- // Pump
- bool valid_packet = false;
-
- LLTransferTargetVFile::updateQueue();
-
- if (!mNumMessageCounts)
- {
- // This is the first message being handled after a resetReceiveCounts,
- // we must be starting the message processing loop. Reset the timers.
- mCurrentMessageTime = totalTime();
- mMessageCountTime = getMessageTimeSeconds();
- }
-
- // loop until either no packets or a valid packet
- // i.e., burn through packets from unregistered circuits
- S32 receive_size = 0;
- do
- {
- clearReceiveState();
-
- bool recv_reliable = false;
- bool recv_resent = false;
- S32 acks = 0;
- S32 true_rcv_size = 0;
-
- U8* buffer = mTrueReceiveBuffer;
-
- mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer);
- // If you want to dump all received packets into SecondLife.log, uncomment this
- //dumpPacketToLog();
-
- receive_size = mTrueReceiveSize;
- mLastSender = mPacketRing.getLastSender();
- mLastReceivingIF = mPacketRing.getLastReceivingInterface();
-
- if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
- {
- // A receive size of zero is OK, that means that there are no more packets available.
- // Ones that are non-zero but below the minimum packet size are worrisome.
- if (receive_size > 0)
- {
- LL_WARNS("Messaging") << "Invalid (too short) packet discarded " << receive_size << LL_ENDL;
- callExceptionFunc(MX_PACKET_TOO_SHORT);
- }
- // no data in packet receive buffer
- valid_packet = false;
- }
- else
- {
- LLHost host;
- LLCircuitData* cdp;
-
- // note if packet acks are appended.
- if(buffer[0] & LL_ACK_FLAG)
- {
- acks += buffer[--receive_size];
- true_rcv_size = receive_size;
- if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
- {
- receive_size -= acks * sizeof(TPACKETID);
- }
- else
- {
- // mal-formed packet. ignore it and continue with
- // the next one
- LL_WARNS("Messaging") << "Malformed packet received. Packet size "
- << receive_size << " with invalid no. of acks " << acks
- << LL_ENDL;
- valid_packet = false;
- continue;
- }
- }
-
- // process the message as normal
- mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
- mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
- host = getSender();
-
- const bool resetPacketId = true;
- cdp = findCircuit(host, resetPacketId);
-
- // At this point, cdp is now a pointer to the circuit that
- // this message came in on if it's valid, and NULL if the
- // circuit was bogus.
-
- if(cdp && (acks > 0) && ((S32)(acks * sizeof(TPACKETID)) < (true_rcv_size)))
- {
- TPACKETID packet_id;
- U32 mem_id=0;
- for(S32 i = 0; i < acks; ++i)
- {
- true_rcv_size -= sizeof(TPACKETID);
- memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/
- sizeof(TPACKETID));
- packet_id = ntohl(mem_id);
- //LL_INFOS("Messaging") << "got ack: " << packet_id << LL_ENDL;
- cdp->ackReliablePacket(packet_id);
- }
- if (!cdp->getUnackedPacketCount())
- {
- // Remove this circuit from the list of circuits with unacked packets
- mCircuitInfo.mUnackedCircuitMap.erase(cdp->mHost);
- }
- }
-
- if (buffer[0] & LL_RELIABLE_FLAG)
- {
- recv_reliable = true;
- }
- if (buffer[0] & LL_RESENT_FLAG)
- {
- recv_resent = true;
- if (cdp && cdp->isDuplicateResend(mCurrentRecvPacketID))
- {
- // We need to ACK here to suppress
- // further resends of packets we've
- // already seen.
- if (recv_reliable)
- {
- //mAckList.addData(new LLPacketAck(host, mCurrentRecvPacketID));
- // ***************************************
- // TESTING CODE
- //if(mCircuitInfo.mCurrentCircuit->mHost != host)
- //{
- // LL_WARNS("Messaging") << "DISCARDED PACKET HOST MISMATCH! HOST: "
- // << host << " CIRCUIT: "
- // << mCircuitInfo.mCurrentCircuit->mHost
- // << LL_ENDL;
- //}
- // ***************************************
- //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID);
- cdp->collectRAck(mCurrentRecvPacketID);
- }
-
- LL_DEBUGS("Messaging") << "Discarding duplicate resend from " << host << LL_ENDL;
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string tbuf;
- tbuf = llformat( "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID);
- str << tbuf << "(unknown)"
- << (recv_reliable ? " reliable" : "")
- << " resent "
- << ((acks > 0) ? "acks" : "")
- << " DISCARD DUPLICATE";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
- mPacketsIn++;
- valid_packet = false;
- continue;
- }
- }
-
- // UseCircuitCode can be a valid, off-circuit packet.
- // But we don't want to acknowledge UseCircuitCode until the circuit is
- // available, which is why the acknowledgement test is done above. JC
- bool trusted = cdp && cdp->getTrusted();
- valid_packet = mTemplateMessageReader->validateMessage(
- buffer,
- receive_size,
- host,
- trusted);
- if (!valid_packet)
- {
- clearReceiveState();
- }
-
- // UseCircuitCode is allowed in even from an invalid circuit, so that
- // we can toss circuits around.
- if(
- valid_packet &&
- !cdp &&
- (mTemplateMessageReader->getMessageName() !=
- _PREHASH_UseCircuitCode))
- {
- logMsgFromInvalidCircuit( host, recv_reliable );
- clearReceiveState();
- valid_packet = false;
- }
-
- if(
- valid_packet &&
- cdp &&
- !cdp->getTrusted() &&
- mTemplateMessageReader->isTrusted())
- {
- logTrustedMsgFromUntrustedCircuit( host );
- clearReceiveState();
-
- sendDenyTrustedCircuit(host);
- valid_packet = false;
- }
-
- if( valid_packet )
- {
- logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 );
- valid_packet = mTemplateMessageReader->readMessage(buffer, host);
- }
-
- // It's possible that the circuit went away, because ANY message can disable the circuit
- // (for example, UseCircuit, CloseCircuit, DisableSimulator). Find it again.
- cdp = mCircuitInfo.findCircuit(host);
-
- if (valid_packet)
- {
- mPacketsIn++;
- mBytesIn += mTrueReceiveSize;
-
- // ACK here for valid packets that we've seen
- // for the first time.
- if (cdp && recv_reliable)
- {
- // Add to the recently received list for duplicate suppression
- cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs();
-
- // Put it onto the list of packets to be acked
- cdp->collectRAck(mCurrentRecvPacketID);
- mReliablePacketsIn++;
- }
- }
- else
- {
- if (mbProtected && (!cdp))
- {
- LL_WARNS("Messaging") << "Invalid Packet from invalid circuit " << host << LL_ENDL;
- mOffCircuitPackets++;
- }
- else
- {
- mInvalidOnCircuitPackets++;
- }
- }
- }
- } while (!valid_packet && receive_size > 0);
-
- F64Seconds mt_sec = getMessageTimeSeconds();
- // Check to see if we need to print debug info
- if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
- {
- dumpCircuitInfo();
- mCircuitPrintTime = mt_sec;
- }
-
- if( !valid_packet )
- {
- clearReceiveState();
- }
-
- return valid_packet;
-}
-
-S32 LLMessageSystem::getReceiveBytes() const
-{
- if (getReceiveCompressedSize())
- {
- return getReceiveCompressedSize() * 8;
- }
- else
- {
- return getReceiveSize() * 8;
- }
-}
-
-
-void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time)
-{
- F64Seconds mt_sec = getMessageTimeSeconds();
- {
- gTransferManager.updateTransfers();
-
- if (gXferManager)
- {
- gXferManager->retransmitUnackedPackets();
- }
-
- if (gAssetStorage)
- {
- gAssetStorage->checkForTimeouts();
- }
- }
-
- bool dump = false;
- {
- // Check the status of circuits
- mCircuitInfo.updateWatchDogTimers(this);
-
- //resend any necessary packets
- mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize);
-
- //cycle through ack list for each host we need to send acks to
- mCircuitInfo.sendAcks(collect_time);
-
- if (!mDenyTrustedCircuitSet.empty())
- {
- LL_INFOS("Messaging") << "Sending queued DenyTrustedCircuit messages." << LL_ENDL;
- for (host_set_t::iterator hostit = mDenyTrustedCircuitSet.begin(); hostit != mDenyTrustedCircuitSet.end(); ++hostit)
- {
- reallySendDenyTrustedCircuit(*hostit);
- }
- mDenyTrustedCircuitSet.clear();
- }
-
- if (mMaxMessageCounts >= 0)
- {
- if (mNumMessageCounts >= mMaxMessageCounts)
- {
- dump = true;
- }
- }
-
- if (mMaxMessageTime >= F32Seconds(0.f))
- {
- // This is one of the only places where we're required to get REAL message system time.
- mReceiveTime = getMessageTimeSeconds(true) - mMessageCountTime;
- if (mReceiveTime > mMaxMessageTime)
- {
- dump = true;
- }
- }
- }
-
- if (dump)
- {
- dumpReceiveCounts();
- }
- resetReceiveCounts();
-
- if ((mt_sec - mResendDumpTime) > CIRCUIT_DUMP_TIMEOUT)
- {
- mResendDumpTime = mt_sec;
- mCircuitInfo.dumpResends();
- }
-}
-
-void LLMessageSystem::copyMessageReceivedToSend()
-{
- // NOTE: babbage: switch builder to match reader to avoid
- // converting message format
- if(mMessageReader == mTemplateMessageReader)
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- else
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- mSendReliable = false;
- mMessageBuilder->newMessage(mMessageReader->getMessageName());
- mMessageReader->copyToBuilder(*mMessageBuilder);
-}
-
-LLSD LLMessageSystem::getReceivedMessageLLSD() const
-{
- LLSDMessageBuilder builder;
- mMessageReader->copyToBuilder(builder);
- return builder.getMessage();
-}
-
-LLSD LLMessageSystem::getBuiltMessageLLSD() const
-{
- LLSD result;
- if (mLLSDMessageBuilder == mMessageBuilder)
- {
- result = mLLSDMessageBuilder->getMessage();
- }
- else
- {
- // TODO: implement as below?
- LL_ERRS() << "Message not built as LLSD." << LL_ENDL;
- }
- return result;
-}
-
-LLSD LLMessageSystem::wrapReceivedTemplateData() const
-{
- if(mMessageReader == mTemplateMessageReader)
- {
- LLTemplateMessageBuilder builder(mMessageTemplates);
- builder.newMessage(mMessageReader->getMessageName());
- mMessageReader->copyToBuilder(builder);
- U8 buffer[MAX_BUFFER_SIZE];
- const U8 offset_to_data = 0;
- U32 size = builder.buildMessage(buffer, MAX_BUFFER_SIZE,
- offset_to_data);
- std::vector<U8> binary_data(buffer, buffer+size);
- LLSD wrapped_data = LLSD::emptyMap();
- wrapped_data["binary-template-data"] = binary_data;
- return wrapped_data;
- }
- else
- {
- return getReceivedMessageLLSD();
- }
-}
-
-LLSD LLMessageSystem::wrapBuiltTemplateData() const
-{
- LLSD result;
- if (mLLSDMessageBuilder == mMessageBuilder)
- {
- result = getBuiltMessageLLSD();
- }
- else
- {
- U8 buffer[MAX_BUFFER_SIZE];
- const U8 offset_to_data = 0;
- U32 size = mTemplateMessageBuilder->buildMessage(
- buffer, MAX_BUFFER_SIZE,
- offset_to_data);
- std::vector<U8> binary_data(buffer, buffer+size);
- LLSD wrapped_data = LLSD::emptyMap();
- wrapped_data["binary-template-data"] = binary_data;
- result = wrapped_data;
- }
- return result;
-}
-
-LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
-{
- const std::string& name = mMessageReader->getMessageName();
- LLSD message = wrapReceivedTemplateData();
-
- return LLStoredMessagePtr(new LLStoredMessage(name, message));
-}
-
-LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
-{
- const std::string& name = mMessageBuilder->getMessageName();
- LLSD message = wrapBuiltTemplateData();
-
- return LLStoredMessagePtr(new LLStoredMessage(name, message));
-}
-
-S32 LLMessageSystem::sendMessage(const LLHost &host, LLStoredMessagePtr message)
-{
- return sendMessage(host, message->mName.c_str(), message->mMessage);
-}
-
-
-void LLMessageSystem::clearMessage()
-{
- mSendReliable = false;
- mMessageBuilder->clearMessage();
-}
-
-// set block to add data to within current message
-void LLMessageSystem::nextBlockFast(const char *blockname)
-{
- mMessageBuilder->nextBlock(blockname);
-}
-
-void LLMessageSystem::nextBlock(const char *blockname)
-{
- nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
-}
-
-bool LLMessageSystem::isSendFull(const char* blockname)
-{
- char* stringTableName = NULL;
- if(NULL != blockname)
- {
- stringTableName = LLMessageStringTable::getInstance()->getString(blockname);
- }
- return isSendFullFast(stringTableName);
-}
-
-bool LLMessageSystem::isSendFullFast(const char* blockname)
-{
- return mMessageBuilder->isMessageFull(blockname);
-}
-
-
-// blow away the last block of a message, return false if that leaves no blocks or there wasn't a block to remove
-// TODO: Babbage: Remove this horror.
-bool LLMessageSystem::removeLastBlock()
-{
- return mMessageBuilder->removeLastBlock();
-}
-
-S32 LLMessageSystem::sendReliable(const LLHost &host)
-{
- return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
-}
-
-
-S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
- F32Seconds timeout;
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
- }
-
- constexpr S32 retries = 0;
- constexpr bool ping_based_timeout = false;
- return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
-}
-
-// send the message via a UDP packet
-S32 LLMessageSystem::sendReliable( const LLHost &host,
- S32 retries,
- bool ping_based_timeout,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data)
-{
- if (ping_based_timeout)
- {
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX));
- }
- }
-
- mSendReliable = true;
- mReliablePacketParams.set(host, retries, ping_based_timeout, timeout,
- callback, callback_data,
- const_cast<char*>(mMessageBuilder->getMessageName()));
- return sendMessage(host);
-}
-
-void LLMessageSystem::forwardMessage(const LLHost &host)
-{
- copyMessageReceivedToSend();
- sendMessage(host);
-}
-
-void LLMessageSystem::forwardReliable(const LLHost &host)
-{
- copyMessageReceivedToSend();
- sendReliable(host);
-}
-
-void LLMessageSystem::forwardReliable(const U32 circuit_code)
-{
- copyMessageReceivedToSend();
- sendReliable(findHost(circuit_code));
-}
-
-S32 LLMessageSystem::forwardReliable( const LLHost &host,
- S32 retries,
- bool ping_based_timeout,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data)
-{
- copyMessageReceivedToSend();
- return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
-}
-
-S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
-{
- F32Seconds timeout;
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
- F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
- }
- else
- {
- timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
- }
-
- S32 send_bytes = 0;
- if (mMessageBuilder->getMessageSize())
- {
- mSendReliable = true;
- // No need for ping-based retry as not going to retry
- mReliablePacketParams.set(host, 0, false, timeout, callback,
- callback_data,
- const_cast<char*>(mMessageBuilder->getMessageName()));
- send_bytes = sendMessage(host);
- clearMessage();
- }
- else
- {
- delete callback_data;
- }
- return send_bytes;
-}
-
-S32 LLMessageSystem::flushReliable(const LLHost &host)
-{
- S32 send_bytes = 0;
- if (mMessageBuilder->getMessageSize())
- {
- send_bytes = sendReliable(host);
- }
- clearMessage();
- return send_bytes;
-}
-
-// This can be called from signal handlers,
-// so should should not use LL_INFOS().
-S32 LLMessageSystem::sendMessage(const LLHost &host)
-{
- if (! mMessageBuilder->isBuilt())
- {
- mSendSize = mMessageBuilder->buildMessage(
- mSendBuffer,
- MAX_BUFFER_SIZE,
- 0);
- }
-
- if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message
- {
- return 0;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- // this is a new circuit!
- // are we protected?
- if (mbProtected)
- {
- // yup! don't send packets to an unknown circuit
- if(mVerboseLog)
- {
- LL_INFOS_ONCE("Messaging") << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t"
- << mMessageBuilder->getMessageName() << LL_ENDL;
- }
- LL_WARNS_ONCE("Messaging") << "sendMessage - Trying to send "
- << mMessageBuilder->getMessageName() << " on unknown circuit "
- << host << LL_ENDL;
- return 0;
- }
- else
- {
- // nope, open the new circuit
-
- cdp = mCircuitInfo.addCircuitData(host, 0);
- }
- }
- else
- {
- // this is an old circuit. . . is it still alive?
- if (!cdp->isAlive())
- {
- // nope. don't send to dead circuits
- if(mVerboseLog)
- {
- LL_INFOS("Messaging") << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t"
- << mMessageBuilder->getMessageName() << LL_ENDL;
- }
- LL_WARNS("Messaging") << "sendMessage - Trying to send message "
- << mMessageBuilder->getMessageName() << " to dead circuit "
- << host << LL_ENDL;
- return 0;
- }
- }
-
- // NOTE: babbage: LLSD message -> HTTP, template message -> UDP
- if(mMessageBuilder == mLLSDMessageBuilder)
- {
- LLSD message = mLLSDMessageBuilder->getMessage();
-
- UntrustedCallback_t cb = NULL;
- if ((mSendReliable) && (mReliablePacketParams.mCallback))
- {
- cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
- }
-
- LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
- boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
- host.getUntrustedSimulatorCap(),
- mLLSDMessageBuilder->getMessageName(), message, cb));
-
- mSendReliable = false;
- mReliablePacketParams.clear();
- return 1;
- }
-
- // zero out the flags and packetid. Subtract 1 here so that we do
- // not overwrite the offset if it was set set in buildMessage().
- memset(mSendBuffer, 0, LL_PACKET_ID_SIZE - 1);
-
- // add the send id to the front of the message
- cdp->nextPacketOutID();
-
- // Packet ID size is always 4
- *((S32*)&mSendBuffer[PHL_PACKET_ID]) = htonl(cdp->getPacketOutID());
-
- // Compress the message, which will usually reduce its size.
- U8 * buf_ptr = (U8 *)mSendBuffer;
- U32 buffer_length = mSendSize;
- mMessageBuilder->compressMessage(buf_ptr, buffer_length);
-
- if (buffer_length > 1500)
- {
- if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate)
- && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket))
- {
- LL_WARNS("Messaging") << "sendMessage - Trying to send "
- << ((buffer_length > 4000) ? "EXTRA " : "")
- << "BIG message " << mMessageBuilder->getMessageName() << " - "
- << buffer_length << LL_ENDL;
- }
- }
- if (mSendReliable)
- {
- buf_ptr[0] |= LL_RELIABLE_FLAG;
-
- if (!cdp->getUnackedPacketCount())
- {
- // We are adding the first packed onto the unacked packet list(s)
- // Add this circuit to the list of circuits with unacked packets
- mCircuitInfo.mUnackedCircuitMap[cdp->mHost] = cdp;
- }
-
- cdp->addReliablePacket(mSocket,buf_ptr,buffer_length, &mReliablePacketParams);
- mReliablePacketsOut++;
- }
-
- // tack packet acks onto the end of this message
- S32 space_left = (MTUBYTES - buffer_length) / sizeof(TPACKETID); // space left for packet ids
- S32 ack_count = (S32)cdp->mAcks.size();
- bool is_ack_appended = false;
- std::vector<TPACKETID> acks;
- if((space_left > 0) && (ack_count > 0) &&
- (mMessageBuilder->getMessageName() != _PREHASH_PacketAck))
- {
- buf_ptr[0] |= LL_ACK_FLAG;
- S32 append_ack_count = llmin(space_left, ack_count);
- const S32 MAX_ACKS = 250;
- append_ack_count = llmin(append_ack_count, MAX_ACKS);
- std::vector<TPACKETID>::iterator iter = cdp->mAcks.begin();
- std::vector<TPACKETID>::iterator last = cdp->mAcks.begin();
- last += append_ack_count;
- TPACKETID packet_id;
- for( ; iter != last ; ++iter)
- {
- // grab the next packet id.
- packet_id = (*iter);
- if(mVerboseLog)
- {
- acks.push_back(packet_id);
- }
-
- // put it on the end of the buffer
- packet_id = htonl(packet_id);
-
- if((S32)(buffer_length + sizeof(TPACKETID)) < MAX_BUFFER_SIZE)
- {
- memcpy(&buf_ptr[buffer_length], &packet_id, sizeof(TPACKETID)); /* Flawfinder: ignore */
- // Do the accounting
- buffer_length += sizeof(TPACKETID);
- }
- else
- {
- // Just reporting error is likely not enough. Need to
- // check how to abort or error out gracefully from
- // this function. XXXTBD
- // *NOTE: Actually hitting this error would indicate
- // the calculation above for space_left, ack_count,
- // append_acout_count is incorrect or that
- // MAX_BUFFER_SIZE has fallen below MTU which is bad
- // and probably programmer error.
- LL_ERRS("Messaging") << "Buffer packing failed due to size.." << LL_ENDL;
- }
- }
-
- // clean up the source
- cdp->mAcks.erase(cdp->mAcks.begin(), last);
-
- // tack the count in the final byte
- U8 count = (U8)append_ack_count;
- buf_ptr[buffer_length++] = count;
- is_ack_appended = true;
- }
-
- bool success;
- success = mPacketRing.sendPacket(mSocket, (char *)buf_ptr, buffer_length, host);
-
- if (!success)
- {
- mSendPacketFailureCount++;
- }
- else
- {
- // mCircuitInfo already points to the correct circuit data
- cdp->addBytesOut( (S32Bytes)buffer_length );
- }
-
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: -> " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID());
- str << buffer
- << mMessageBuilder->getMessageName()
- << (mSendReliable ? " reliable " : "");
- if(is_ack_appended)
- {
- str << "\tACKS:\t";
- std::ostream_iterator<TPACKETID> append(str, " ");
- std::copy(acks.begin(), acks.end(), append);
- }
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
-
-
- mPacketsOut++;
- mTotalBytesOut += buffer_length;
-
- mSendReliable = false;
- mReliablePacketParams.clear();
- return buffer_length;
-}
-
-void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, bool recv_reliable )
-{
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);
- str << buffer
- << nullToEmpty(mMessageReader->getMessageName())
- << (recv_reliable ? " reliable" : "")
- << " REJECTED";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
- // nope!
- // cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
-
- // Keep track of rejected messages as well
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- // mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = true;
- mNumMessageCounts++;
- }
-}
-
-S32 LLMessageSystem::sendMessage(
- const LLHost &host,
- const char* name,
- const LLSD& message)
-{
- if (!(host.isOk()))
- {
- LL_WARNS("Messaging") << "trying to send message to invalid host" << LL_ENDL;
- return 0;
- }
-
- UntrustedCallback_t cb = NULL;
- if ((mSendReliable) && (mReliablePacketParams.mCallback))
- {
- cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
- }
-
- LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
- boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
- host.getUntrustedSimulatorCap(), name, message, cb));
- return 1;
-}
-
-void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
-{
- // RequestTrustedCircuit is how we establish trust, so don't spam
- // if it's received on a trusted circuit. JC
- if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit"))
- {
- LL_WARNS("Messaging") << "Received trusted message on untrusted circuit. "
- << "Will reply with deny. "
- << "Message: " << nullToEmpty(mMessageReader->getMessageName())
- << " Host: " << host << LL_ENDL;
- }
-
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "got more than " << MAX_MESSAGE_COUNT_NUM
- << " packets without clearing counts"
- << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- //mMessageCountList[mNumMessageCounts].mMessageNum
- // = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes
- = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = true;
- mNumMessageCounts++;
- }
-}
-
-void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, bool recv_reliable, bool recv_resent, bool recv_acks )
-{
- if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
- {
- LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
- }
- else
- {
- // TODO: babbage: work out if we need these
- //mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
- mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
- mMessageCountList[mNumMessageCounts].mInvalid = false;
- mNumMessageCounts++;
- }
-
- if (cdp)
- {
- // update circuit packet ID tracking (missing/out of order packets)
- cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent );
- cdp->addBytesIn( (S32Bytes)mTrueReceiveSize );
- }
-
- if(mVerboseLog)
- {
- std::ostringstream str;
- str << "MSG: <- " << host;
- std::string buffer;
- buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID);
- str << buffer
- << nullToEmpty(mMessageReader->getMessageName())
- << (recv_reliable ? " reliable" : "")
- << (recv_resent ? " resent" : "")
- << (recv_acks ? " acks" : "");
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
- }
-}
-
-void LLMessageSystem::sanityCheck()
-{
-// TODO: babbage: reinstate
-
-// if (!mCurrentRMessageData)
-// {
-// LL_ERRS("Messaging") << "mCurrentRMessageData is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRMessageTemplate)
-// {
-// LL_ERRS("Messaging") << "mCurrentRMessageTemplate is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRTemplateBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentRTemplateBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentRDataBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentRDataBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSMessageData)
-// {
-// LL_ERRS("Messaging") << "mCurrentSMessageData is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSMessageTemplate)
-// {
-// LL_ERRS("Messaging") << "mCurrentSMessageTemplate is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSTemplateBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentSTemplateBlock is NULL" << LL_ENDL;
-// }
-
-// if (!mCurrentSDataBlock)
-// {
-// LL_ERRS("Messaging") << "mCurrentSDataBlock is NULL" << LL_ENDL;
-// }
-}
-
-void LLMessageSystem::showCircuitInfo()
-{
- LL_INFOS("Messaging") << mCircuitInfo << LL_ENDL;
-}
-
-
-void LLMessageSystem::dumpCircuitInfo()
-{
- LL_DEBUGS("Messaging") << mCircuitInfo << LL_ENDL;
-}
-
-/* virtual */
-U32 LLMessageSystem::getOurCircuitCode()
-{
- return mOurCircuitCode;
-}
-
-void LLMessageSystem::getCircuitInfo(LLSD& info) const
-{
- mCircuitInfo.getInfo(info);
-}
-
-// returns whether the given host is on a trusted circuit
-bool LLMessageSystem::getCircuitTrust(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->getTrusted();
- }
-
- return false;
-}
-
-// Activate a circuit, and set its trust level (true if trusted,
-// false if not).
-void LLMessageSystem::enableCircuit(const LLHost &host, bool trusted)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- cdp = mCircuitInfo.addCircuitData(host, 0);
- }
- else
- {
- cdp->setAlive(true);
- }
- cdp->setTrusted(trusted);
-}
-
-void LLMessageSystem::disableCircuit(const LLHost &host)
-{
- LL_INFOS("Messaging") << "LLMessageSystem::disableCircuit for " << host << LL_ENDL;
- U32 code = gMessageSystem->findCircuitCode( host );
-
- // Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
-
- // don't clean up 0 circuit code entries
- // because many hosts (neighbor sims, etc) can have the 0 circuit
- if (code)
- {
- //if (mCircuitCodes.checkKey(code))
- code_session_map_t::iterator it = mCircuitCodes.find(code);
- if(it != mCircuitCodes.end())
- {
- LL_INFOS("Messaging") << "Circuit " << code << " removed from list" << LL_ENDL;
- //mCircuitCodes.removeData(code);
- mCircuitCodes.erase(it);
- }
-
- U64 ip_port = 0;
- std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
- if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
- {
- ip_port = iter->second;
-
- gMessageSystem->mCircuitCodeToIPPort.erase(iter);
-
- U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
- U32 old_ip = (U32)(ip_port >> 32);
-
- LL_INFOS("Messaging") << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << LL_ENDL;
- gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
- }
- mCircuitInfo.removeCircuitData(host);
- }
- else
- {
- // Sigh, since we can open circuits which don't have circuit
- // codes, it's possible for this to happen...
-
- LL_WARNS("Messaging") << "Couldn't find circuit code for " << host << LL_ENDL;
- }
-
-}
-
-
-void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, bool allow)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- cdp->setAllowTimeout(allow);
- }
-}
-
-void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- cdp->setTimeoutCallback(callback_func, user_data);
- }
-}
-
-
-bool LLMessageSystem::checkCircuitBlocked(const U32 circuit)
-{
- LLHost host = findHost(circuit);
-
- if (!host.isOk())
- {
- LL_DEBUGS("Messaging") << "checkCircuitBlocked: Unknown circuit " << circuit << LL_ENDL;
- return true;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isBlocked();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitBlocked(circuit): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-bool LLMessageSystem::checkCircuitAlive(const U32 circuit)
-{
- LLHost host = findHost(circuit);
-
- if (!host.isOk())
- {
- LL_DEBUGS("Messaging") << "checkCircuitAlive: Unknown circuit " << circuit << LL_ENDL;
- return false;
- }
-
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isAlive();
- }
- else
- {
- LL_INFOS("Messaging") << "checkCircuitAlive(circuit): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-bool LLMessageSystem::checkCircuitAlive(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (cdp)
- {
- return cdp->isAlive();
- }
- else
- {
- LL_DEBUGS("Messaging") << "checkCircuitAlive(host): Unknown host - " << host << LL_ENDL;
- return false;
- }
-}
-
-
-void LLMessageSystem::setCircuitProtection(bool b_protect)
-{
- mbProtected = b_protect;
-}
-
-
-U32 LLMessageSystem::findCircuitCode(const LLHost &host)
-{
- U64 ip64 = (U64) host.getAddress();
- U64 port64 = (U64) host.getPort();
- U64 ip_port = (ip64 << 32) | port64;
-
- return get_if_there(mIPPortToCircuitCode, ip_port, U32(0));
-}
-
-LLHost LLMessageSystem::findHost(const U32 circuit_code)
-{
- if (mCircuitCodeToIPPort.count(circuit_code) > 0)
- {
- return LLHost(mCircuitCodeToIPPort[circuit_code]);
- }
- else
- {
- return LLHost();
- }
-}
-
-void LLMessageSystem::setMaxMessageTime(const F32 seconds)
-{
- mMaxMessageTime = F32Seconds(seconds);
-}
-
-void LLMessageSystem::setMaxMessageCounts(const S32 num)
-{
- mMaxMessageCounts = num;
-}
-
-
-std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
-{
- U32 i;
- if (msg.mbError)
- {
- s << "Message system not correctly initialized";
- }
- else
- {
- s << "Message system open on port " << msg.mPort << " and socket " << msg.mSocket << "\n";
-// s << "Message template file " << msg.mName << " loaded\n";
-
- s << "\nHigh frequency messages:\n";
-
- for (i = 1; msg.mMessageNumbers[i] && (i < 255); i++)
- {
- s << *(msg.mMessageNumbers[i]);
- }
-
- s << "\nMedium frequency messages:\n";
-
- for (i = (255 << 8) + 1; msg.mMessageNumbers[i] && (i < (255 << 8) + 255); i++)
- {
- s << *msg.mMessageNumbers[i];
- }
-
- s << "\nLow frequency messages:\n";
-
- for (i = (0xFFFF0000) + 1; msg.mMessageNumbers[i] && (i < 0xFFFFFFFF); i++)
- {
- s << *msg.mMessageNumbers[i];
- }
- }
- return s;
-}
-
-// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
-// callback registrations for when gMessageSystem is first assigned
-LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
-
-// update appropriate ping info
-void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U8 ping_id;
- msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
-
- LLCircuitData *cdp;
- cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
-
- // stop the appropriate timer
- if (cdp)
- {
- cdp->pingTimerStop(ping_id);
- }
-}
-
-void process_start_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U8 ping_id;
- msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
-
- LLCircuitData *cdp;
- cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
- if (cdp)
- {
- // Grab the packet id of the oldest unacked packet
- U32 packet_id;
- msgsystem->getU32Fast(_PREHASH_PingID, _PREHASH_OldestUnacked, packet_id);
- cdp->clearDuplicateList(packet_id);
- }
-
- // Send off the response
- msgsystem->newMessageFast(_PREHASH_CompletePingCheck);
- msgsystem->nextBlockFast(_PREHASH_PingID);
- msgsystem->addU8(_PREHASH_PingID, ping_id);
- msgsystem->sendMessage(msgsystem->getSender());
-}
-
-
-
-// Note: this is currently unused. --mark
-void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- U32 ip;
- U16 port;
-
- msgsystem->getIPAddrFast(_PREHASH_CircuitInfo, _PREHASH_IP, ip);
- msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
-
- // By default, OpenCircuit's are untrusted
- msgsystem->enableCircuit(LLHost(ip, port), false);
-}
-
-void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- msgsystem->disableCircuit(msgsystem->getSender());
-}
-
-// static
-/*
-void LLMessageSystem::processAssignCircuitCode(LLMessageSystem* msg, void**)
-{
- // if we already have a circuit code, we can bail
- if(msg->mOurCircuitCode) return;
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- if(session_id != msg->getMySessionID())
- {
- LL_WARNS("Messaging") << "AssignCircuitCode, bad session id. Expecting "
- << msg->getMySessionID() << " but got " << session_id
- << LL_ENDL;
- return;
- }
- U32 code;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
- if (!code)
- {
- LL_ERRS("Messaging") << "Assigning circuit code of zero!" << LL_ENDL;
- }
-
- msg->mOurCircuitCode = code;
- LL_INFOS("Messaging") << "Circuit code " << code << " assigned." << LL_ENDL;
-}
-*/
-
-// static
-void LLMessageSystem::processAddCircuitCode(LLMessageSystem* msg, void**)
-{
- U32 code;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- (void)msg->addCircuitCode(code, session_id);
-
- // Send the ack back
- //msg->newMessageFast(_PREHASH_AckAddCircuitCode);
- //msg->nextBlockFast(_PREHASH_CircuitCode);
- //msg->addU32Fast(_PREHASH_Code, code);
- //msg->sendMessage(msg->getSender());
-}
-
-bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id)
-{
- if(!code)
- {
- LL_WARNS("Messaging") << "addCircuitCode: zero circuit code" << LL_ENDL;
- return false;
- }
- code_session_map_t::iterator it = mCircuitCodes.find(code);
- if(it == mCircuitCodes.end())
- {
- LL_INFOS("Messaging") << "New circuit code " << code << " added" << LL_ENDL;
- //msg->mCircuitCodes[circuit_code] = circuit_code;
-
- mCircuitCodes.insert(code_session_map_t::value_type(code, session_id));
- }
- else
- {
- LL_INFOS("Messaging") << "Duplicate circuit code " << code << " added" << LL_ENDL;
- }
- return true;
-}
-
-//void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*/)
-//{
- // By default, we do nothing. This particular message is only handled by the spaceserver
-//}
-
-// static
-void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg,
- void** user)
-{
- U32 circuit_code_in;
- msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in);
-
- U32 ip = msg->getSenderIP();
- U32 port = msg->getSenderPort();
-
- U64 ip64 = ip;
- U64 port64 = port;
- U64 ip_port_in = (ip64 << 32) | port64;
-
- if (circuit_code_in)
- {
- //if (!msg->mCircuitCodes.checkKey(circuit_code_in))
- code_session_map_t::iterator it;
- it = msg->mCircuitCodes.find(circuit_code_in);
- if(it == msg->mCircuitCodes.end())
- {
- // Whoah, abort! We don't know anything about this circuit code.
- LL_WARNS("Messaging") << "UseCircuitCode for " << circuit_code_in
- << " received without AddCircuitCode message - aborting"
- << LL_ENDL;
- return;
- }
-
- LLUUID id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_ID, id);
- LLUUID session_id;
- msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
- if(session_id != (*it).second)
- {
- LL_WARNS("Messaging") << "UseCircuitCode unmatched session id. Got "
- << session_id << " but expected " << (*it).second
- << LL_ENDL;
- return;
- }
-
- // Clean up previous references to this ip/port or circuit
- U64 ip_port_old = get_if_there(msg->mCircuitCodeToIPPort, circuit_code_in, U64(0));
- U32 circuit_code_old = get_if_there(msg->mIPPortToCircuitCode, ip_port_in, U32(0));
-
- if (ip_port_old)
- {
- if ((ip_port_old == ip_port_in) && (circuit_code_old == circuit_code_in))
- {
- // Current information is the same as incoming info, ignore
- LL_INFOS("Messaging") << "Got duplicate UseCircuitCode for circuit " << circuit_code_in << " to " << msg->getSender() << LL_ENDL;
- return;
- }
-
- // Hmm, got a different IP and port for the same circuit code.
- U32 circut_code_old_ip_port = get_if_there(msg->mIPPortToCircuitCode, ip_port_old, U32(0));
- msg->mCircuitCodeToIPPort.erase(circut_code_old_ip_port);
- msg->mIPPortToCircuitCode.erase(ip_port_old);
- U32 old_port = (U32)(ip_port_old & (U64)0xFFFFFFFF);
- U32 old_ip = (U32)(ip_port_old >> 32);
- LL_INFOS("Messaging") << "Removing derelict lookup entry for circuit " << circuit_code_old << " to " << LLHost(old_ip, old_port) << LL_ENDL;
- }
-
- if (circuit_code_old)
- {
- LLHost cur_host(ip, port);
-
- LL_WARNS("Messaging") << "Disabling existing circuit for " << cur_host << LL_ENDL;
- msg->disableCircuit(cur_host);
- if (circuit_code_old == circuit_code_in)
- {
- LL_WARNS("Messaging") << "Asymmetrical circuit to ip/port lookup!" << LL_ENDL;
- LL_WARNS("Messaging") << "Multiple circuit codes for " << cur_host << " probably!" << LL_ENDL;
- LL_WARNS("Messaging") << "Permanently disabling circuit" << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Circuit code changed for " << msg->getSender()
- << " from " << circuit_code_old << " to "
- << circuit_code_in << LL_ENDL;
- }
- }
-
- // Since this comes from the viewer, it's untrusted, but it
- // passed the circuit code and session id check, so we will go
- // ahead and persist the ID associated.
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- bool had_circuit_already = cdp != nullptr;
-
- msg->enableCircuit(msg->getSender(), false);
- cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if(cdp)
- {
- cdp->setRemoteID(id);
- cdp->setRemoteSessionID(session_id);
- }
-
- if (!had_circuit_already)
- {
- //
- // HACK HACK HACK HACK HACK!
- //
- // This would NORMALLY happen inside logValidMsg, but at the point that this happens
- // inside logValidMsg, there's no circuit for this message yet. So the awful thing that
- // we do here is do it inside this message handler immediately AFTER the message is
- // handled.
- //
- // We COULD not do this, but then what happens is that some of the circuit bookkeeping
- // gets broken, especially the packets in count. That causes some later packets to flush
- // the RecentlyReceivedReliable list, resulting in an error in which UseCircuitCode
- // doesn't get properly duplicate suppressed. Not a BIG deal, but it's somewhat confusing
- // (and bad from a state point of view). DJS 9/23/04
- //
- cdp->checkPacketInID(gMessageSystem->mCurrentRecvPacketID, false ); // Since this is the first message on the circuit, by definition it's not resent.
- }
-
- msg->mIPPortToCircuitCode[ip_port_in] = circuit_code_in;
- msg->mCircuitCodeToIPPort[circuit_code_in] = ip_port_in;
-
- LL_INFOS("Messaging") << "Circuit code " << circuit_code_in << " from "
- << msg->getSender() << " for agent " << id << " in session "
- << session_id << LL_ENDL;
-
- const LLUseCircuitCodeResponder* responder =
- (const LLUseCircuitCodeResponder*) user;
- if(responder)
- {
- responder->complete(msg->getSender(), id);
- }
- }
- else
- {
- LL_WARNS("Messaging") << "Got zero circuit code in use_circuit_code" << LL_ENDL;
- }
-}
-
-// static
-void LLMessageSystem::processError(LLMessageSystem* msg, void**)
-{
- S32 error_code = 0;
- msg->getS32("Data", "Code", error_code);
- std::string error_token;
- msg->getString("Data", "Token", error_token);
-
- LLUUID error_id;
- msg->getUUID("Data", "ID", error_id);
- std::string error_system;
- msg->getString("Data", "System", error_system);
-
- std::string error_message;
- msg->getString("Data", "Message", error_message);
-
- LL_WARNS("Messaging") << "Message error from " << msg->getSender() << " - "
- << error_code << " " << error_token << " " << error_id << " \""
- << error_system << "\" \"" << error_message << "\"" << LL_ENDL;
-}
-
-
-static LLHTTPNode& messageRootNode()
-{
- static LLHTTPNode root_node;
- static bool initialized = false;
- if (!initialized) {
- initialized = true;
- LLHTTPRegistrar::buildAllServices(root_node);
- }
-
- return root_node;
-}
-
-//static
-void LLMessageSystem::dispatch(
- const std::string& msg_name,
- const LLSD& message)
-{
- LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create();
- dispatch(msg_name, message, responsep);
-}
-
-//static
-void LLMessageSystem::dispatch(
- const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
-{
- if ((gMessageSystem->mMessageTemplates.find
- (LLMessageStringTable::getInstance()->getString(msg_name.c_str())) ==
- gMessageSystem->mMessageTemplates.end()) &&
- !LLMessageConfig::isValidMessage(msg_name))
- {
- LL_WARNS("Messaging") << "Ignoring unknown message " << msg_name << LL_ENDL;
- responsep->notFound("Invalid message name");
- return;
- }
-
- std::string path = "/message/" + msg_name;
- LLSD context;
- const LLHTTPNode* handler = messageRootNode().traverse(path, context);
- if (!handler)
- {
- LL_WARNS("Messaging") << "LLMessageService::dispatch > no handler for "
- << path << LL_ENDL;
- return;
- }
- // enable this for output of message names
- LL_DEBUGS("Messaging") << "< \"" << msg_name << "\"" << LL_ENDL;
- LL_DEBUGS("Messaging") << "context: " << context << LL_ENDL;
- LL_DEBUGS("Messaging") << "message: " << message << LL_ENDL;
-
- handler->post(responsep, context, message);
-}
-
-//static
-void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
-{
- LLTemplateMessageDispatcher dispatcher(*(gMessageSystem->mTemplateMessageReader));
- dispatcher.dispatch(msg_name, message, responsep);
-}
-
-static void check_for_unrecognized_messages(
- const char* type,
- const LLSD& map,
- LLMessageSystem::message_template_name_map_t& templates)
-{
- for (LLSD::map_const_iterator iter = map.beginMap(),
- end = map.endMap();
- iter != end; ++iter)
- {
- const char* name = LLMessageStringTable::getInstance()->getString(iter->first.c_str());
-
- if (templates.find(name) == templates.end())
- {
- LL_INFOS("AppInit") << " " << type
- << " ban list contains unrecognized message "
- << name << LL_ENDL;
- }
- }
-}
-
-void LLMessageSystem::setMessageBans(
- const LLSD& trusted, const LLSD& untrusted)
-{
- LL_DEBUGS("AppInit") << "LLMessageSystem::setMessageBans:" << LL_ENDL;
- bool any_set = false;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; ++iter)
- {
- LLMessageTemplate* mt = iter->second;
-
- std::string name(mt->mName);
- bool ban_from_trusted
- = trusted.has(name) && trusted.get(name).asBoolean();
- bool ban_from_untrusted
- = untrusted.has(name) && untrusted.get(name).asBoolean();
-
- mt->mBanFromTrusted = ban_from_trusted;
- mt->mBanFromUntrusted = ban_from_untrusted;
-
- if (ban_from_trusted || ban_from_untrusted)
- {
- LL_INFOS("AppInit") << " " << name << " banned from "
- << (ban_from_trusted ? "TRUSTED " : " ")
- << (ban_from_untrusted ? "UNTRUSTED " : " ")
- << LL_ENDL;
- any_set = true;
- }
- }
-
- if (!any_set)
- {
- LL_DEBUGS("AppInit") << " no messages banned" << LL_ENDL;
- }
-
- check_for_unrecognized_messages("trusted", trusted, mMessageTemplates);
- check_for_unrecognized_messages("untrusted", untrusted, mMessageTemplates);
-}
-
-S32 LLMessageSystem::sendError(
- const LLHost& host,
- const LLUUID& agent_id,
- S32 code,
- const std::string& token,
- const LLUUID& id,
- const std::string& system,
- const std::string& message,
- const LLSD& data)
-{
- newMessage("Error");
- nextBlockFast(_PREHASH_AgentData);
- addUUIDFast(_PREHASH_AgentID, agent_id);
- nextBlockFast(_PREHASH_Data);
- addS32("Code", code);
- addString("Token", token);
- addUUID("ID", id);
- addString("System", system);
- std::string temp;
- temp = message;
- if(temp.size() > (size_t)MTUBYTES) temp.resize((size_t)MTUBYTES);
- addString("Message", message);
- LLPointer<LLSDBinaryFormatter> formatter = new LLSDBinaryFormatter;
- std::ostringstream ostr;
- formatter->format(data, ostr);
- temp = ostr.str();
- bool pack_data = true;
- static const std::string ERROR_MESSAGE_NAME("Error");
- if (LLMessageConfig::getMessageFlavor(ERROR_MESSAGE_NAME) ==
- LLMessageConfig::TEMPLATE_FLAVOR)
- {
- S32 msg_size = temp.size() + mMessageBuilder->getMessageSize();
- if(msg_size >= ETHERNET_MTU_BYTES)
- {
- pack_data = false;
- }
- }
- if(pack_data)
- {
- addBinaryData("Data", (void*)temp.c_str(), temp.size());
- }
- else
- {
- LL_WARNS("Messaging") << "Data and message were too large -- data removed."
- << LL_ENDL;
- addBinaryData("Data", NULL, 0);
- }
- return sendReliable(host);
-}
-
-void process_packet_ack(LLMessageSystem *msgsystem, void** /*user_data*/)
-{
- TPACKETID packet_id;
-
- LLHost host = msgsystem->getSender();
- LLCircuitData *cdp = msgsystem->mCircuitInfo.findCircuit(host);
- if (cdp)
- {
-
- S32 ack_count = msgsystem->getNumberOfBlocksFast(_PREHASH_Packets);
-
- for (S32 i = 0; i < ack_count; i++)
- {
- msgsystem->getU32Fast(_PREHASH_Packets, _PREHASH_ID, packet_id, i);
-// LL_DEBUGS("Messaging") << "ack recvd' from " << host << " for packet " << (TPACKETID)packet_id << LL_ENDL;
- cdp->ackReliablePacket(packet_id);
- }
- if (!cdp->getUnackedPacketCount())
- {
- // Remove this circuit from the list of circuits with unacked packets
- gMessageSystem->mCircuitInfo.mUnackedCircuitMap.erase(host);
- }
- }
-}
-
-
-/*
-void process_log_messages(LLMessageSystem* msg, void**)
-{
- U8 log_message;
-
- msg->getU8Fast(_PREHASH_Options, _PREHASH_Enable, log_message);
-
- if (log_message)
- {
- LL_INFOS("Messaging") << "Starting logging via message" << LL_ENDL;
- msg->startLogging();
- }
- else
- {
- LL_INFOS("Messaging") << "Stopping logging via message" << LL_ENDL;
- msg->stopLogging();
- }
-}*/
-
-// Make circuit trusted if the MD5 Digest matches, otherwise
-// notify remote end that they are not trusted.
-void process_create_trusted_circuit(LLMessageSystem *msg, void **)
-{
- // don't try to create trust on machines with no shared secret
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
-
- LLUUID remote_id;
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
-
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if (!cdp)
- {
- LL_WARNS("Messaging") << "Attempt to create trusted circuit without circuit data: "
- << msg->getSender() << LL_ENDL;
- return;
- }
-
- LLUUID local_id;
- local_id = cdp->getLocalEndPointID();
- if (remote_id == local_id)
- {
- // Don't respond to requests that use the same end point ID
- return;
- }
-
- U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
- U32 last_interface = msg->getReceivingInterface().getAddress();
- if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
- {
- if( msg->getBlockUntrustedInterface() )
- {
- LL_WARNS("Messaging") << "Ignoring CreateTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Processing CreateTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- }
- }
-
- char their_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest);
- if(size != MD5HEX_STR_BYTES)
- {
- // ignore requests which pack the wrong amount of data.
- return;
- }
- msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Digest, their_digest, MD5HEX_STR_BYTES);
- their_digest[MD5HEX_STR_SIZE - 1] = '\0';
- if(msg->isMatchingDigestForWindowAndUUIDs(their_digest, TRUST_TIME_WINDOW, local_id, remote_id))
- {
- cdp->setTrusted(true);
- LL_INFOS("Messaging") << "Trusted digest from " << msg->getSender() << LL_ENDL;
- return;
- }
- else if (cdp->getTrusted())
- {
- // The digest is bad, but this circuit is already trusted.
- // This means that this could just be the result of a stale deny sent from a while back, and
- // the message system is being slow. Don't bother sending the deny, as it may continually
- // ping-pong back and forth on a very hosed circuit.
- LL_WARNS("Messaging") << "Ignoring bad digest from known trusted circuit: " << their_digest
- << " host: " << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Bad digest from known circuit: " << their_digest
- << " host: " << msg->getSender() << LL_ENDL;
- msg->sendDenyTrustedCircuit(msg->getSender());
- return;
- }
-}
-
-void process_deny_trusted_circuit(LLMessageSystem *msg, void **)
-{
- // don't try to create trust on machines with no shared secret
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
-
- LLUUID remote_id;
- msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
-
- LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
- if (!cdp)
- {
- return;
- }
-
- LLUUID local_id;
- local_id = cdp->getLocalEndPointID();
- if (remote_id == local_id)
- {
- // Don't respond to requests that use the same end point ID
- return;
- }
-
- U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
- U32 last_interface = msg->getReceivingInterface().getAddress();
- if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
- {
- if( msg->getBlockUntrustedInterface() )
- {
- LL_WARNS("Messaging") << "Ignoring DenyTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- return;
- }
- else
- {
- LL_WARNS("Messaging") << "Processing DenyTrustedCircuit on public interface from host: "
- << msg->getSender() << LL_ENDL;
- }
- }
-
-
- // Assume that we require trust to proceed, so resend.
- // This catches the case where a circuit that was trusted
- // times out, and allows us to re-establish it, but does
- // mean that if our shared_secret or clock is wrong, we'll
- // spin.
- // *TODO: probably should keep a count of number of resends
- // per circuit, and stop resending after a while.
- LL_INFOS("Messaging") << "Got DenyTrustedCircuit. Sending CreateTrustedCircuit to "
- << msg->getSender() << LL_ENDL;
- msg->sendCreateTrustedCircuit(msg->getSender(), local_id, remote_id);
-}
-
-
-void dump_prehash_files()
-{
- U32 i;
- std::string filename("../../indra/llmessage/message_prehash.h");
- LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
- if (fp)
- {
- fprintf(
- fp,
- "/**\n"
- " * @file message_prehash.h\n"
- " * @brief header file of externs of prehashed variables plus defines.\n"
- " *\n"
- " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
- " * $/LicenseInfo$"
- " */\n\n"
- "#ifndef LL_MESSAGE_PREHASH_H\n#define LL_MESSAGE_PREHASH_H\n\n");
- fprintf(
- fp,
- "/**\n"
- " * Generated from message template version number %.3f\n"
- " */\n",
- gMessageSystem->mMessageFileVersionNumber);
- fprintf(fp, "\n\nextern F32 const gPrehashVersionNumber;\n\n");
- for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
- {
- fprintf(fp, "extern char const* const _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]);
- }
- }
- fprintf(fp, "\n\n#endif\n");
- fclose(fp);
- }
- filename = std::string("../../indra/llmessage/message_prehash.cpp");
- fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
- if (fp)
- {
- fprintf(
- fp,
- "/**\n"
- " * @file message_prehash.cpp\n"
- " * @brief file of prehashed variables\n"
- " *\n"
- " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
- " * $/LicenseInfo$"
- " */\n\n"
- "/**\n"
- " * Generated from message template version number %.3f\n"
- " */\n",
- gMessageSystem->mMessageFileVersionNumber);
- fprintf(fp, "#include \"linden_common.h\"\n");
- fprintf(fp, "#include \"message.h\"\n\n");
- fprintf(fp, "\n\nF32 const gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber);
- for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
- {
- fprintf(fp, "char const* const _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]);
- }
- }
- fclose(fp);
- }
-}
-
-bool start_messaging_system(
- const std::string& template_name,
- U32 port,
- S32 version_major,
- S32 version_minor,
- S32 version_patch,
- bool b_dump_prehash_file,
- const std::string& secret,
- const LLUseCircuitCodeResponder* responder,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval,
- const F32 circuit_timeout)
-{
- gMessageSystem = new LLMessageSystem(
- template_name,
- port,
- version_major,
- version_minor,
- version_patch,
- failure_is_fatal,
- circuit_heartbeat_interval,
- circuit_timeout);
- g_shared_secret.assign(secret);
-
- if (!gMessageSystem)
- {
- LL_ERRS("AppInit") << "Messaging system initialization failed." << LL_ENDL;
- return false;
- }
-
- // bail if system encountered an error.
- if(!gMessageSystem->isOK())
- {
- return false;
- }
-
- if (b_dump_prehash_file)
- {
- dump_prehash_files();
- exit(0);
- }
- else
- {
- if (gMessageSystem->mMessageFileVersionNumber != gPrehashVersionNumber)
- {
- LL_INFOS("AppInit") << "Message template version does not match prehash version number" << LL_ENDL;
- LL_INFOS("AppInit") << "Run simulator with -prehash command line option to rebuild prehash data" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("AppInit") << "Message template version matches prehash version number" << LL_ENDL;
- }
- }
-
- gMessageSystem->setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_OpenCircuit, open_circuit, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CloseCircuit, close_circuit, NULL);
-
- //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode);
- gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode);
- //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder);
- gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL);
- //gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit,
- process_create_trusted_circuit,
- NULL);
- gMessageSystem->setHandlerFuncFast(_PREHASH_DenyTrustedCircuit,
- process_deny_trusted_circuit,
- NULL);
- gMessageSystem->setHandlerFunc("Error", LLMessageSystem::processError);
-
- // We can hand this to the null_message_callback since it is a
- // trusted message, so it will automatically be denied if it isn't
- // trusted and ignored if it is -- exactly what we want.
- gMessageSystem->setHandlerFunc(
- "RequestTrustedCircuit",
- null_message_callback,
- NULL);
-
- // Initialize the transfer manager
- gTransferManager.init();
-
- return true;
-}
-
-void LLMessageSystem::startLogging()
-{
- mVerboseLog = true;
- std::ostringstream str;
- str << "START MESSAGE LOG" << std::endl;
- str << "Legend:" << std::endl;
- str << "\t<-\tincoming message" <<std::endl;
- str << "\t->\toutgoing message" << std::endl;
- str << " <> host size zero id name";
- LL_INFOS("Messaging") << str.str() << LL_ENDL;
-}
-
-void LLMessageSystem::stopLogging()
-{
- if(mVerboseLog)
- {
- mVerboseLog = false;
- LL_INFOS("Messaging") << "END MESSAGE LOG" << LL_ENDL;
- }
-}
-
-void LLMessageSystem::summarizeLogs(std::ostream& str)
-{
- std::string buffer;
- std::string tmp_str;
- F32 run_time = mMessageSystemTimer.getElapsedTimeF32();
- str << "START MESSAGE LOG SUMMARY" << std::endl;
- buffer = llformat( "Run time: %12.3f seconds", run_time);
-
- // Incoming
- str << buffer << std::endl << "Incoming:" << std::endl;
- tmp_str = U64_to_str(mTotalBytesIn);
- buffer = llformat( "Total bytes received: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesIn * 0.008f) / run_time);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mPacketsIn);
- buffer = llformat( "Total packets received: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32) mPacketsIn / run_time));
- str << buffer << std::endl;
- buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mReliablePacketsIn);
- buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(mCompressedPacketsIn);
- buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1));
- str << buffer << std::endl;
- S64 savings = mUncompressedBytesIn - mCompressedBytesIn;
- tmp_str = U64_to_str(savings);
- buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mCompressedPacketsIn +1));
- buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mPacketsIn+1));
- buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f));
-
- // Outgoing
- str << buffer << std::endl << std::endl << "Outgoing:" << std::endl;
- tmp_str = U64_to_str(mTotalBytesOut);
- buffer = llformat( "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesOut * 0.008f) / run_time );
- str << buffer << std::endl;
- tmp_str = U64_to_str(mPacketsOut);
- buffer = llformat( "Total packets sent: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32)mPacketsOut / run_time));
- str << buffer << std::endl;
- buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut);
- str << buffer << std::endl;
- tmp_str = U64_to_str(mReliablePacketsOut);
- buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(mCompressedPacketsOut);
- buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1));
- str << buffer << std::endl;
- savings = mUncompressedBytesOut - mCompressedBytesOut;
- tmp_str = U64_to_str(savings);
- buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mCompressedPacketsOut +1));
- buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1));
- str << buffer << std::endl;
- tmp_str = U64_to_str(savings/(mPacketsOut+1));
- buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f));
- str << buffer << std::endl << std::endl;
- buffer = llformat( "SendPacket failures: %20d", mSendPacketFailureCount);
- str << buffer << std::endl;
- buffer = llformat( "Dropped packets: %20d", mDroppedPackets);
- str << buffer << std::endl;
- buffer = llformat( "Resent packets: %20d", mResentPackets);
- str << buffer << std::endl;
- buffer = llformat( "Failed reliable resends: %20d", mFailedResendPackets);
- str << buffer << std::endl;
- buffer = llformat( "Off-circuit rejected packets: %17d", mOffCircuitPackets);
- str << buffer << std::endl;
- buffer = llformat( "On-circuit invalid packets: %17d", mInvalidOnCircuitPackets);
- str << buffer << std::endl << std::endl;
-
- str << "Decoding: " << std::endl;
- buffer = llformat( "%35s%10s%10s%10s%10s", "Message", "Count", "Time", "Max", "Avg");
- str << buffer << std:: endl;
- F32 avg;
- for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- const LLMessageTemplate* mt = iter->second;
- if(mt->mTotalDecoded > 0)
- {
- avg = mt->mTotalDecodeTime / (F32)mt->mTotalDecoded;
- buffer = llformat( "%35s%10u%10f%10f%10f", mt->mName, mt->mTotalDecoded, mt->mTotalDecodeTime, mt->mMaxDecodeTimePerMsg, avg);
- str << buffer << std::endl;
- }
- }
- str << "END MESSAGE LOG SUMMARY" << std::endl;
-}
-
-void end_messaging_system(bool print_summary)
-{
- gTransferManager.cleanup();
- LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
- if (gMessageSystem)
- {
- gMessageSystem->stopLogging();
-
- if (print_summary)
- {
- std::ostringstream str;
- gMessageSystem->summarizeLogs(str);
- LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
- }
-
- delete static_cast<LLMessageSystem*>(gMessageSystem);
- gMessageSystem = NULL;
- }
-}
-
-void LLMessageSystem::resetReceiveCounts()
-{
- mNumMessageCounts = 0;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- LLMessageTemplate* mt = iter->second;
- mt->mDecodeTimeThisFrame = 0.f;
- }
-}
-
-
-void LLMessageSystem::dumpReceiveCounts()
-{
- LLMessageTemplate *mt;
-
- for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- LLMessageTemplate* mt = iter->second;
- mt->mReceiveCount = 0;
- mt->mReceiveBytes = 0;
- mt->mReceiveInvalid = 0;
- }
-
- S32 i;
- for (i = 0; i < mNumMessageCounts; i++)
- {
- mt = get_ptr_in_map(mMessageNumbers,mMessageCountList[i].mMessageNum);
- if (mt)
- {
- mt->mReceiveCount++;
- mt->mReceiveBytes += mMessageCountList[i].mMessageBytes;
- if (mMessageCountList[i].mInvalid)
- {
- mt->mReceiveInvalid++;
- }
- }
- }
-
- if(mNumMessageCounts > 0)
- {
- LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL;
- for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
- end = mMessageTemplates.end();
- iter != end; iter++)
- {
- const LLMessageTemplate* mt = iter->second;
- if (mt->mReceiveCount > 0)
- {
- LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes
- << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL;
- }
- }
- }
-}
-
-
-
-bool LLMessageSystem::isClear() const
-{
- return mMessageBuilder->isClear();
-}
-
-
-S32 LLMessageSystem::flush(const LLHost &host)
-{
- if (mMessageBuilder->getMessageSize())
- {
- S32 sentbytes = sendMessage(host);
- clearMessage();
- return sentbytes;
- }
- else
- {
- return 0;
- }
-}
-
-U32 LLMessageSystem::getListenPort( void ) const
-{
- return mPort;
-}
-
-// TODO: babbage: remove this horror!
-S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
-{
- if(mMessageBuilder == mLLSDMessageBuilder)
- {
- // babbage: don't compress LLSD messages, so delta is 0
- return 0;
- }
-
- if (! mMessageBuilder->isBuilt())
- {
- mSendSize = mMessageBuilder->buildMessage(
- mSendBuffer,
- MAX_BUFFER_SIZE,
- 0);
- }
- // TODO: babbage: remove this horror
- mMessageBuilder->setBuilt(false);
-
- S32 count = mSendSize;
-
- S32 net_gain = 0;
- U8 num_zeroes = 0;
-
- U8 *inptr = (U8 *)mSendBuffer;
-
-// skip the packet id field
-
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
- {
- count--;
- inptr++;
- }
-
-// don't actually build, just test
-
-// sequential zero bytes are encoded as 0 [U8 count]
-// with 0 0 [count] representing wrap (>256 zeroes)
-
- while (count--)
- {
- if (!(*inptr)) // in a zero count
- {
- if (num_zeroes)
- {
- if (++num_zeroes > 254)
- {
- num_zeroes = 0;
- }
- net_gain--; // subseqent zeroes save one
- }
- else
- {
- net_gain++; // starting a zero count adds one
- num_zeroes = 1;
- }
- inptr++;
- }
- else
- {
- if (num_zeroes)
- {
- num_zeroes = 0;
- }
- inptr++;
- }
- }
- if (net_gain < 0)
- {
- return net_gain;
- }
- else
- {
- return 0;
- }
-}
-
-
-
-S32 LLMessageSystem::zeroCodeExpand(U8** data, S32* data_size)
-{
- if ((*data_size ) < LL_MINIMUM_VALID_PACKET_SIZE)
- {
- LL_WARNS("Messaging") << "zeroCodeExpand() called with data_size of " << *data_size
- << LL_ENDL;
- }
-
- mTotalBytesIn += *data_size;
-
- // if we're not zero-coded, simply return.
- if (!(*data[0] & LL_ZERO_CODE_FLAG))
- {
- return 0;
- }
-
- S32 in_size = *data_size;
- mCompressedPacketsIn++;
- mCompressedBytesIn += *data_size;
-
- *data[0] &= (~LL_ZERO_CODE_FLAG);
-
- S32 count = (*data_size);
-
- U8 *inptr = (U8 *)*data;
- U8 *outptr = (U8 *)mEncodedRecvBuffer;
-
-// skip the packet id field
-
- for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
- {
- count--;
- *outptr++ = *inptr++;
- }
-
-// reconstruct encoded packet, keeping track of net size gain
-
-// sequential zero bytes are encoded as 0 [U8 count]
-// with 0 0 [count] representing wrap (>256 zeroes)
-
- while (count--)
- {
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-1]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 1" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- break;
- }
- if (!((*outptr++ = *inptr++)))
- {
- while (((count--)) && (!(*inptr)))
- {
- *outptr++ = *inptr++;
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-256]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 2" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- count = -1;
- break;
- }
- memset(outptr,0,255);
- outptr += 255;
- }
-
- if (count < 0)
- {
- break;
- }
-
- else
- {
- if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-(*inptr)]))
- {
- LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 3" << LL_ENDL;
- callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
- outptr = mEncodedRecvBuffer;
- }
- memset(outptr,0,(*inptr) - 1);
- outptr += ((*inptr) - 1);
- inptr++;
- }
- }
- }
-
- *data = mEncodedRecvBuffer;
- *data_size = (S32)(outptr - mEncodedRecvBuffer);
- mUncompressedBytesIn += *data_size;
-
- return(in_size);
-}
-
-
-void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
-{
- if (mMessageTemplates.count(templatep->mName) > 0)
- {
- LL_ERRS("Messaging") << templatep->mName << " already used as a template name!"
- << LL_ENDL;
- }
- mMessageTemplates[templatep->mName] = templatep;
- mMessageNumbers[templatep->mMessageNumber] = templatep;
-}
-
-
-void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
-{
- LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
- if (msgtemplate)
- {
- msgtemplate->setHandlerFunc(handler_func, user_data);
- }
- else
- {
- LL_ERRS("Messaging") << name << " is not a known message name!" << LL_ENDL;
- }
-}
-
-bool LLMessageSystem::callHandler(const char *name,
- bool trustedSource, LLMessageSystem* msg)
-{
- name = LLMessageStringTable::getInstance()->getString(name);
- message_template_name_map_t::const_iterator iter;
- iter = mMessageTemplates.find(name);
- if(iter == mMessageTemplates.end())
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callHandler: unknown message "
- << name << LL_ENDL;
- return false;
- }
-
- const LLMessageTemplate* msg_template = iter->second;
- if (msg_template->isBanned(trustedSource))
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callHandler: banned message "
- << name
- << " from "
- << (trustedSource ? "trusted " : "untrusted ")
- << "source" << LL_ENDL;
- return false;
- }
-
- return msg_template->callHandlerFunc(msg);
-}
-
-
-void LLMessageSystem::setExceptionFunc(EMessageException e,
- msg_exception_callback func,
- void* data)
-{
- callbacks_t::iterator it = mExceptionCallbacks.find(e);
- if(it != mExceptionCallbacks.end())
- {
- mExceptionCallbacks.erase(it);
- }
- if(func)
- {
- mExceptionCallbacks.insert(callbacks_t::value_type(e, exception_t(func, data)));
- }
-}
-
-bool LLMessageSystem::callExceptionFunc(EMessageException exception)
-{
- callbacks_t::iterator it = mExceptionCallbacks.find(exception);
- if(it == mExceptionCallbacks.end())
- {
- return false;
- }
-
- exception_t& ex = it->second;
- msg_exception_callback ex_cb = ex.first;
-
- if (!ex_cb)
- {
- LL_WARNS("Messaging") << "LLMessageSystem::callExceptionFunc: bad message exception callback." << LL_ENDL;
- return false;
- }
-
- (ex_cb)(this, ex.second, exception);
-
- return true;
-}
-
-void LLMessageSystem::setTimingFunc(msg_timing_callback func, void* data)
-{
- mTimingCallback = func;
- mTimingCallbackData = data;
-}
-
-bool LLMessageSystem::isCircuitCodeKnown(U32 code) const
-{
- if(mCircuitCodes.find(code) == mCircuitCodes.end())
- return false;
- return true;
-}
-
-bool LLMessageSystem::isMessageFast(const char *msg)
-{
- return msg == mMessageReader->getMessageName();
-}
-
-
-char* LLMessageSystem::getMessageName()
-{
- return const_cast<char*>(mMessageReader->getMessageName());
-}
-
-const LLUUID& LLMessageSystem::getSenderID() const
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
- if (cdp)
- {
- return (cdp->mRemoteID);
- }
-
- return LLUUID::null;
-}
-
-const LLUUID& LLMessageSystem::getSenderSessionID() const
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
- if (cdp)
- {
- return (cdp->mRemoteSessionID);
- }
- return LLUUID::null;
-}
-
-bool LLMessageSystem::generateDigestForNumberAndUUIDs(
- char* digest,
- const U32 number,
- const LLUUID& id1,
- const LLUUID& id2) const
-{
- // *NOTE: This method is needlessly inefficient. Instead of
- // calling LLUUID::asString, it should just call
- // LLUUID::toString().
-
- const char *colon = ":";
- char tbuf[16]; /* Flawfinder: ignore */
- LLMD5 d;
- std::string id1string = id1.asString();
- std::string id2string = id2.asString();
- std::string shared_secret = get_shared_secret();
- unsigned char * secret = (unsigned char*)shared_secret.c_str();
- unsigned char * id1str = (unsigned char*)id1string.c_str();
- unsigned char * id2str = (unsigned char*)id2string.c_str();
-
- memset(digest, 0, MD5HEX_STR_SIZE);
-
- if( secret != NULL)
- {
- d.update(secret, (U32)strlen((char *) secret)); /* Flawfinder: ignore */
- }
-
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
-
- snprintf(tbuf, sizeof(tbuf),"%i", number); /* Flawfinder: ignore */
- d.update((unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
-
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
- if( (char*) id1str != NULL)
- {
- d.update(id1str, (U32)strlen((char *) id1str)); /* Flawfinder: ignore */
- }
- d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
-
- if( (char*) id2str != NULL)
- {
- d.update(id2str, (U32)strlen((char *) id2str)); /* Flawfinder: ignore */
- }
-
- d.finalize();
- d.hex_digest(digest);
- digest[MD5HEX_STR_SIZE - 1] = '\0';
-
- return true;
-}
-
-bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
-{
- if(0 == window) return false;
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << LL_ENDL;
- }
-
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- bool result = generateDigestForNumberAndUUIDs(digest, now, id1, id2);
-
- return result;
-}
-
-bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to compare complex digests on a machine without a shared secret!" << LL_ENDL;
- }
-
- char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- // Check 1 window ago, now, and one window from now to catch edge
- // conditions. Process them as current window, one window ago, and
- // one window in the future to catch the edges.
- const S32 WINDOW_BIN_COUNT = 3;
- U32 window_bin[WINDOW_BIN_COUNT];
- window_bin[0] = now;
- window_bin[1] = now - 1;
- window_bin[2] = now + 1;
- for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
- {
- generateDigestForNumberAndUUIDs(our_digest, window_bin[i], id2, id1);
- if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
- {
- return true;
- }
- }
- return false;
-}
-
-bool LLMessageSystem::generateDigestForNumber(char* digest, const U32 number) const
-{
- memset(digest, 0, MD5HEX_STR_SIZE);
-
- LLMD5 d;
- std::string shared_secret = get_shared_secret();
- d = LLMD5((const unsigned char *)shared_secret.c_str(), number);
- d.hex_digest(digest);
- digest[MD5HEX_STR_SIZE - 1] = '\0';
-
- return true;
-}
-
-bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << LL_ENDL;
- }
-
- U32 now = (U32)time(NULL);
-
- now /= window;
-
- bool result = generateDigestForNumber(digest, now);
-
- return result;
-}
-
-bool LLMessageSystem::isMatchingDigestForWindow(const char* digest, S32 const window) const
-{
- if(0 == window) return false;
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to compare simple digests on a machine without a shared secret!" << LL_ENDL;
- }
-
- char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- U32 now = (S32)time(NULL);
-
- now /= window;
-
- // Check 1 window ago, now, and one window from now to catch edge
- // conditions. Process them as current window, one window ago, and
- // one window in the future to catch the edges.
- const S32 WINDOW_BIN_COUNT = 3;
- U32 window_bin[WINDOW_BIN_COUNT];
- window_bin[0] = now;
- window_bin[1] = now - 1;
- window_bin[2] = now + 1;
- for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
- {
- generateDigestForNumber(our_digest, window_bin[i]);
- if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
- {
- return true;
- }
- }
- return false;
-}
-
-void LLMessageSystem::sendCreateTrustedCircuit(const LLHost &host, const LLUUID & id1, const LLUUID & id2)
-{
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty()) return;
- char digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
- if (id1.isNull())
- {
- LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the local end point ID" << LL_ENDL;
- return;
- }
- if (id2.isNull())
- {
- LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the remote end point ID" << LL_ENDL;
- return;
- }
- generateDigestForWindowAndUUIDs(digest, TRUST_TIME_WINDOW, id1, id2);
- newMessageFast(_PREHASH_CreateTrustedCircuit);
- nextBlockFast(_PREHASH_DataBlock);
- addUUIDFast(_PREHASH_EndPointID, id1);
- addBinaryDataFast(_PREHASH_Digest, digest, MD5HEX_STR_BYTES);
- LL_INFOS("Messaging") << "xmitting digest: " << digest << " Host: " << host << LL_ENDL;
- sendMessage(host);
-}
-
-void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host)
-{
- mDenyTrustedCircuitSet.insert(host);
-}
-
-void LLMessageSystem::reallySendDenyTrustedCircuit(const LLHost &host)
-{
- LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
- if (!cdp)
- {
- LL_WARNS("Messaging") << "Not sending DenyTrustedCircuit to host without a circuit." << LL_ENDL;
- return;
- }
- LL_INFOS("Messaging") << "Sending DenyTrustedCircuit to " << host << LL_ENDL;
- newMessageFast(_PREHASH_DenyTrustedCircuit);
- nextBlockFast(_PREHASH_DataBlock);
- addUUIDFast(_PREHASH_EndPointID, cdp->getLocalEndPointID());
- sendMessage(host);
-}
-
-void null_message_callback(LLMessageSystem *msg, void **data)
-{
- // Nothing should ever go here, but we use this to register messages
- // that we are expecting to see (and spinning on) at startup.
- return;
-}
-
-// Try to establish a bidirectional trust metric by pinging a host until it's
-// up, and then sending auth messages.
-void LLMessageSystem::establishBidirectionalTrust(const LLHost &host, S64 frame_count )
-{
- LockMessageChecker lmc(this);
-
- std::string shared_secret = get_shared_secret();
- if(shared_secret.empty())
- {
- LL_ERRS("Messaging") << "Trying to establish bidirectional trust on a machine without a shared secret!" << LL_ENDL;
- }
- LLTimer timeout;
-
- timeout.setTimerExpirySec(20.0);
- setHandlerFuncFast(_PREHASH_StartPingCheck, null_message_callback, NULL);
- setHandlerFuncFast(_PREHASH_CompletePingCheck, null_message_callback,
- NULL);
-
- while (! timeout.hasExpired())
- {
- newMessageFast(_PREHASH_StartPingCheck);
- nextBlockFast(_PREHASH_PingID);
- addU8Fast(_PREHASH_PingID, 0);
- addU32Fast(_PREHASH_OldestUnacked, 0);
- sendMessage(host);
- if (lmc.checkMessages( frame_count ))
- {
- if (isMessageFast(_PREHASH_CompletePingCheck) &&
- (getSender() == host))
- {
- break;
- }
- }
- lmc.processAcks();
- ms_sleep(1);
- }
-
- // Send a request, a deny, and give the host 2 seconds to complete
- // the trust handshake.
- newMessage("RequestTrustedCircuit");
- sendMessage(host);
- reallySendDenyTrustedCircuit(host);
- setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
- setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
-
- timeout.setTimerExpirySec(2.0);
- LLCircuitData* cdp = NULL;
- while(!timeout.hasExpired())
- {
- cdp = mCircuitInfo.findCircuit(host);
- if(!cdp) break; // no circuit anymore, no point continuing.
- if(cdp->getTrusted()) break; // circuit is trusted.
- lmc.checkMessages(frame_count);
- lmc.processAcks();
- ms_sleep(1);
- }
-}
-
-
-void LLMessageSystem::dumpPacketToLog()
-{
- LL_WARNS("Messaging") << "Packet Dump from:" << mPacketRing.getLastSender() << LL_ENDL;
- LL_WARNS("Messaging") << "Packet Size:" << mTrueReceiveSize << LL_ENDL;
- char line_buffer[256]; /* Flawfinder: ignore */
- S32 i;
- S32 cur_line_pos = 0;
- S32 cur_line = 0;
-
- for (i = 0; i < mTrueReceiveSize; i++)
- {
- S32 offset = cur_line_pos * 3;
- snprintf(line_buffer + offset, sizeof(line_buffer) - offset,
- "%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */
- cur_line_pos++;
- if (cur_line_pos >= 16)
- {
- cur_line_pos = 0;
- LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
- cur_line++;
- }
- }
- if (cur_line_pos)
- {
- LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
- }
-}
-
-
-//static
-U64Microseconds LLMessageSystem::getMessageTimeUsecs(const bool update)
-{
- if (gMessageSystem)
- {
- if (update)
- {
- gMessageSystem->mCurrentMessageTime = totalTime();
- }
- return gMessageSystem->mCurrentMessageTime;
- }
- else
- {
- return totalTime();
- }
-}
-
-//static
-F64Seconds LLMessageSystem::getMessageTimeSeconds(const bool update)
-{
- if (gMessageSystem)
- {
- if (update)
- {
- gMessageSystem->mCurrentMessageTime = totalTime();
- }
- return gMessageSystem->mCurrentMessageTime;
- }
- else
- {
- return F64Seconds(totalTime());
- }
-}
-
-std::string get_shared_secret()
-{
- static const std::string SHARED_SECRET_KEY("shared_secret");
- if(g_shared_secret.empty())
- {
- LLApp* app = LLApp::instance();
- if(app) return app->getOption(SHARED_SECRET_KEY);
- }
- return g_shared_secret;
-}
-
-typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
-
-void LLMessageSystem::newMessageFast(const char *name)
-{
- //LL_DEBUGS("Messaging") << "creating new message: " << name << LL_ENDL;
- LLMessageConfig::Flavor message_flavor =
- LLMessageConfig::getMessageFlavor(name);
- LLMessageConfig::Flavor server_flavor =
- LLMessageConfig::getServerDefaultFlavor();
-
- if(message_flavor == LLMessageConfig::TEMPLATE_FLAVOR)
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- else if (message_flavor == LLMessageConfig::LLSD_FLAVOR)
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- // NO_FLAVOR
- else
- {
- if (server_flavor == LLMessageConfig::LLSD_FLAVOR)
- {
- mMessageBuilder = mLLSDMessageBuilder;
- }
- // TEMPLATE_FLAVOR or NO_FLAVOR
- else
- {
- mMessageBuilder = mTemplateMessageBuilder;
- }
- }
- mSendReliable = false;
- mMessageBuilder->newMessage(name);
-}
-
-void LLMessageSystem::newMessage(const char *name)
-{
- newMessageFast(LLMessageStringTable::getInstance()->getString(name));
-}
-
-void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size)
-{
- mMessageBuilder->addBinaryData(varname, data, size);
-}
-
-void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size)
-{
- mMessageBuilder->addBinaryData(LLMessageStringTable::getInstance()->getString(varname),data, size);
-}
-
-void LLMessageSystem::addS8Fast(const char *varname, S8 v)
-{
- mMessageBuilder->addS8(varname, v);
-}
-
-void LLMessageSystem::addS8(const char *varname, S8 v)
-{
- mMessageBuilder->addS8(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU8Fast(const char *varname, U8 v)
-{
- mMessageBuilder->addU8(varname, v);
-}
-
-void LLMessageSystem::addU8(const char *varname, U8 v)
-{
- mMessageBuilder->addU8(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addS16Fast(const char *varname, S16 v)
-{
- mMessageBuilder->addS16(varname, v);
-}
-
-void LLMessageSystem::addS16(const char *varname, S16 v)
-{
- mMessageBuilder->addS16(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU16Fast(const char *varname, U16 v)
-{
- mMessageBuilder->addU16(varname, v);
-}
-
-void LLMessageSystem::addU16(const char *varname, U16 v)
-{
- mMessageBuilder->addU16(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addF32Fast(const char *varname, F32 v)
-{
- mMessageBuilder->addF32(varname, v);
-}
-
-void LLMessageSystem::addF32(const char *varname, F32 v)
-{
- mMessageBuilder->addF32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addS32Fast(const char *varname, S32 v)
-{
- mMessageBuilder->addS32(varname, v);
-}
-
-void LLMessageSystem::addS32(const char *varname, S32 v)
-{
- mMessageBuilder->addS32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU32Fast(const char *varname, U32 v)
-{
- mMessageBuilder->addU32(varname, v);
-}
-
-void LLMessageSystem::addU32(const char *varname, U32 v)
-{
- mMessageBuilder->addU32(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addU64Fast(const char *varname, U64 v)
-{
- mMessageBuilder->addU64(varname, v);
-}
-
-void LLMessageSystem::addU64(const char *varname, U64 v)
-{
- mMessageBuilder->addU64(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addF64Fast(const char *varname, F64 v)
-{
- mMessageBuilder->addF64(varname, v);
-}
-
-void LLMessageSystem::addF64(const char *varname, F64 v)
-{
- mMessageBuilder->addF64(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addIPAddrFast(const char *varname, U32 v)
-{
- mMessageBuilder->addIPAddr(varname, v);
-}
-
-void LLMessageSystem::addIPAddr(const char *varname, U32 v)
-{
- mMessageBuilder->addIPAddr(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addIPPortFast(const char *varname, U16 v)
-{
- mMessageBuilder->addIPPort(varname, v);
-}
-
-void LLMessageSystem::addIPPort(const char *varname, U16 v)
-{
- mMessageBuilder->addIPPort(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addBOOLFast(const char* varname, bool v)
-{
- mMessageBuilder->addBOOL(varname, v);
-}
-
-void LLMessageSystem::addBOOL(const char* varname, bool v)
-{
- mMessageBuilder->addBOOL(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addStringFast(const char* varname, const char* v)
-{
- mMessageBuilder->addString(varname, v);
-}
-
-void LLMessageSystem::addString(const char* varname, const char* v)
-{
- mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addStringFast(const char* varname, const std::string& v)
-{
- mMessageBuilder->addString(varname, v);
-}
-
-void LLMessageSystem::addString(const char* varname, const std::string& v)
-{
- mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v)
-{
- mMessageBuilder->addVector3(varname, v);
-}
-
-void LLMessageSystem::addVector3(const char *varname, const LLVector3& v)
-{
- mMessageBuilder->addVector3(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v)
-{
- mMessageBuilder->addVector4(varname, v);
-}
-
-void LLMessageSystem::addVector4(const char *varname, const LLVector4& v)
-{
- mMessageBuilder->addVector4(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v)
-{
- mMessageBuilder->addVector3d(varname, v);
-}
-
-void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v)
-{
- mMessageBuilder->addVector3d(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v)
-{
- mMessageBuilder->addQuat(varname, v);
-}
-
-void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v)
-{
- mMessageBuilder->addQuat(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-
-void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v)
-{
- mMessageBuilder->addUUID(varname, v);
-}
-
-void LLMessageSystem::addUUID(const char *varname, const LLUUID& v)
-{
- mMessageBuilder->addUUID(LLMessageStringTable::getInstance()->getString(varname), v);
-}
-
-S32 LLMessageSystem::getCurrentSendTotal() const
-{
- return mMessageBuilder->getMessageSize();
-}
-
-void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u,
- S32 blocknum)
-{
- mMessageReader->getS8(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getS8(const char *block, const char *var, S8 &u,
- S32 blocknum)
-{
- getS8Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u,
- S32 blocknum)
-{
- mMessageReader->getU8(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getU8(const char *block, const char *var, U8 &u,
- S32 blocknum)
-{
- getU8Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getBOOLFast(const char *block, const char *var, bool &b,
- S32 blocknum)
-{
- mMessageReader->getBOOL(block, var, b, blocknum);
-}
-
-void LLMessageSystem::getBOOL(const char *block, const char *var, bool &b,
- S32 blocknum)
-{
- getBOOLFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), b, blocknum);
-}
-
-void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d,
- S32 blocknum)
-{
- mMessageReader->getS16(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getS16(const char *block, const char *var, S16 &d,
- S32 blocknum)
-{
- getS16Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d,
- S32 blocknum)
-{
- mMessageReader->getU16(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU16(const char *block, const char *var, U16 &d,
- S32 blocknum)
-{
- getU16Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d,
- S32 blocknum)
-{
- mMessageReader->getS32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getS32(const char *block, const char *var, S32 &d,
- S32 blocknum)
-{
- getS32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d,
- S32 blocknum)
-{
- mMessageReader->getU32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU32(const char *block, const char *var, U32 &d,
- S32 blocknum)
-{
- getU32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d,
- S32 blocknum)
-{
- mMessageReader->getU64(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getU64(const char *block, const char *var, U64 &d,
- S32 blocknum)
-{
-
- getU64Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getBinaryDataFast(const char *blockname,
- const char *varname,
- void *datap, S32 size,
- S32 blocknum, S32 max_size)
-{
- mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum,
- max_size);
-}
-
-void LLMessageSystem::getBinaryData(const char *blockname,
- const char *varname,
- void *datap, S32 size,
- S32 blocknum, S32 max_size)
-{
- getBinaryDataFast(LLMessageStringTable::getInstance()->getString(blockname),
- LLMessageStringTable::getInstance()->getString(varname),
- datap, size, blocknum, max_size);
-}
-
-void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d,
- S32 blocknum)
-{
- mMessageReader->getF32(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getF32(const char *block, const char *var, F32 &d,
- S32 blocknum)
-{
- getF32Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d,
- S32 blocknum)
-{
- mMessageReader->getF64(block, var, d, blocknum);
-}
-
-void LLMessageSystem::getF64(const char *block, const char *var, F64 &d,
- S32 blocknum)
-{
- getF64Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), d, blocknum);
-}
-
-
-void LLMessageSystem::getVector3Fast(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- mMessageReader->getVector3(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector3(const char *block, const char *var,
- LLVector3 &v, S32 blocknum )
-{
- getVector3Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getVector4Fast(const char *block, const char *var,
- LLVector4 &v, S32 blocknum )
-{
- mMessageReader->getVector4(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector4(const char *block, const char *var,
- LLVector4 &v, S32 blocknum )
-{
- getVector4Fast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getVector3dFast(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- mMessageReader->getVector3d(block, var, v, blocknum);
-}
-
-void LLMessageSystem::getVector3d(const char *block, const char *var,
- LLVector3d &v, S32 blocknum )
-{
- getVector3dFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), v, blocknum);
-}
-
-void LLMessageSystem::getQuatFast(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum )
-{
- mMessageReader->getQuat(block, var, q, blocknum);
-}
-
-void LLMessageSystem::getQuat(const char *block, const char *var,
- LLQuaternion &q, S32 blocknum)
-{
- getQuatFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), q, blocknum);
-}
-
-void LLMessageSystem::getUUIDFast(const char *block, const char *var,
- LLUUID &u, S32 blocknum )
-{
- mMessageReader->getUUID(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u,
- S32 blocknum )
-{
- getUUIDFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getIPAddrFast(const char *block, const char *var,
- U32 &u, S32 blocknum)
-{
- mMessageReader->getIPAddr(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u,
- S32 blocknum)
-{
- getIPAddrFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u, blocknum);
-}
-
-void LLMessageSystem::getIPPortFast(const char *block, const char *var,
- U16 &u, S32 blocknum)
-{
- mMessageReader->getIPPort(block, var, u, blocknum);
-}
-
-void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u,
- S32 blocknum)
-{
- getIPPortFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), u,
- blocknum);
-}
-
-
-void LLMessageSystem::getStringFast(const char *block, const char *var,
- S32 buffer_size, char *s, S32 blocknum)
-{
- if(buffer_size <= 0)
- {
- LL_WARNS("Messaging") << "buffer_size <= 0" << LL_ENDL;
- }
- mMessageReader->getString(block, var, buffer_size, s, blocknum);
-}
-
-void LLMessageSystem::getString(const char *block, const char *var,
- S32 buffer_size, char *s, S32 blocknum )
-{
- getStringFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), buffer_size, s,
- blocknum);
-}
-
-void LLMessageSystem::getStringFast(const char *block, const char *var,
- std::string& outstr, S32 blocknum)
-{
- mMessageReader->getString(block, var, outstr, blocknum);
-}
-
-void LLMessageSystem::getString(const char *block, const char *var,
- std::string& outstr, S32 blocknum )
-{
- getStringFast(LLMessageStringTable::getInstance()->getString(block),
- LLMessageStringTable::getInstance()->getString(var), outstr,
- blocknum);
-}
-
-bool LLMessageSystem::has(const char *blockname) const
-{
- return getNumberOfBlocks(blockname) > 0;
-}
-
-S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
-{
- return mMessageReader->getNumberOfBlocks(blockname);
-}
-
-S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
-{
- return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
-}
-
-S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
-{
- return mMessageReader->getSize(blockname, varname);
-}
-
-S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
-{
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
- LLMessageStringTable::getInstance()->getString(varname));
-}
-
-// size in bytes of variable length data
-S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
- const char *varname) const
-{
- return mMessageReader->getSize(blockname, blocknum, varname);
-}
-
-S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
- const char *varname) const
-{
- return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
- LLMessageStringTable::getInstance()->getString(varname));
-}
-
-S32 LLMessageSystem::getReceiveSize() const
-{
- return mMessageReader->getMessageSize();
-}
-
-//static
-void LLMessageSystem::setTimeDecodes( bool b )
-{
- LLMessageReader::setTimeDecodes(b);
-}
-
-//static
-void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
-{
- LLMessageReader::setTimeDecodesSpamThreshold(seconds);
-}
-
-LockMessageChecker::LockMessageChecker(LLMessageSystem* msgsystem):
- // for the lifespan of this LockMessageChecker instance, use
- // LLTemplateMessageReader as msgsystem's mMessageReader
- LockMessageReader(msgsystem->mMessageReader, msgsystem->mTemplateMessageReader),
- mMessageSystem(msgsystem)
-{}
-
-// HACK! babbage: return true if message rxed via either UDP or HTTP
-// TODO: babbage: move gServicePump in to LLMessageSystem?
-bool LLMessageSystem::checkAllMessages(LockMessageChecker& lmc, S64 frame_count, LLPumpIO* http_pump)
-{
- if(lmc.checkMessages(frame_count))
- {
- return true;
- }
- U32 packetsIn = mPacketsIn;
- http_pump->pump();
- http_pump->callback();
- return (mPacketsIn - packetsIn) > 0;
-}
-
-void LLMessageSystem::banUdpMessage(const std::string& name)
-{
- message_template_name_map_t::iterator itt = mMessageTemplates.find(
- LLMessageStringTable::getInstance()->getString(name.c_str())
- );
- if(itt != mMessageTemplates.end())
- {
- itt->second->banUdp();
- }
- else
- {
- LL_WARNS() << "Attempted to ban an unknown message: " << name << "." << LL_ENDL;
- }
-}
-const LLHost& LLMessageSystem::getSender() const
-{
- return mLastSender;
-}
-
-void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
-{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
-
-
- if (url.empty())
- {
- LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
- return;
- }
-
- LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
- LLSD postData;
- postData["message"] = message;
- postData["body"] = body;
-
- LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
-
- LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
- LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
-
- if ((callback) && (!callback.empty()))
- callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
-}
-
-
-LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
- gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
-
+/**
+ * @file message.cpp
+ * @brief LLMessageSystem class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "message.h"
+
+// system library includes
+#if !LL_WINDOWS
+// following header files required for inet_addr()
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+#include <iomanip>
+#include <iterator>
+#include <sstream>
+
+#include "llapr.h"
+#include "apr_portable.h"
+#include "apr_network_io.h"
+#include "apr_poll.h"
+
+// linden library headers
+#include "llapp.h"
+#include "indra_constants.h"
+#include "lldir.h"
+#include "llerror.h"
+#include "llfasttimer.h"
+#include "llhttpnodeadapter.h"
+#include "llmd5.h"
+#include "llmessagebuilder.h"
+#include "llmessageconfig.h"
+#include "lltemplatemessagedispatcher.h"
+#include "llpumpio.h"
+#include "lltemplatemessagebuilder.h"
+#include "lltemplatemessagereader.h"
+#include "lltrustedmessageservice.h"
+#include "llmessagetemplate.h"
+#include "llmessagetemplateparser.h"
+#include "llsd.h"
+#include "llsdmessagebuilder.h"
+#include "llsdmessagereader.h"
+#include "llsdserialize.h"
+#include "llstring.h"
+#include "lltransfermanager.h"
+#include "lluuid.h"
+#include "llxfermanager.h"
+#include "llquaternion.h"
+#include "u64.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "lltransfertargetvfile.h"
+#include "llcorehttputil.h"
+#include "llpounceable.h"
+
+// Constants
+//const char* MESSAGE_LOG_FILENAME = "message.log";
+static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f);
+static const S32 TRUST_TIME_WINDOW = 3;
+
+// *NOTE: This needs to be moved into a seperate file so that it never gets
+// included in the viewer. 30 Sep 2002 mark
+// *NOTE: I don't think it's important that the messgage system tracks
+// this since it must get set externally. 2004.08.25 Phoenix.
+static std::string g_shared_secret;
+std::string get_shared_secret();
+
+class LLMessagePollInfo
+{
+public:
+ apr_socket_t *mAPRSocketp;
+ apr_pollfd_t mPollFD;
+};
+
+class LLMessageHandlerBridge : public LLHTTPNode
+{
+ virtual bool validate(const std::string& name, LLSD& context) const
+ { return true; }
+
+ virtual void post(LLHTTPNode::ResponsePtr response, const LLSD& context,
+ const LLSD& input) const;
+};
+
+//virtual
+void LLMessageHandlerBridge::post(LLHTTPNode::ResponsePtr response,
+ const LLSD& context, const LLSD& input) const
+{
+ std::string name = context[CONTEXT_REQUEST][CONTEXT_WILDCARD]["message-name"];
+ char* namePtr = LLMessageStringTable::getInstance()->getString(name.c_str());
+
+ LL_DEBUGS() << "Setting mLastSender " << input["sender"].asString() << LL_ENDL;
+ gMessageSystem->mLastSender = LLHost(input["sender"].asString());
+ gMessageSystem->mPacketsIn += 1;
+ gMessageSystem->mLLSDMessageReader->setMessage(namePtr, input["body"]);
+ LockMessageReader rdr(gMessageSystem->mMessageReader, gMessageSystem->mLLSDMessageReader);
+
+ if(gMessageSystem->callHandler(namePtr, false, gMessageSystem))
+ {
+ response->result(LLSD());
+ }
+ else
+ {
+ response->notFound();
+ }
+}
+
+LLHTTPRegistration<LLMessageHandlerBridge>
+ gHTTPRegistrationMessageWildcard("/message/<message-name>");
+
+//virtual
+LLUseCircuitCodeResponder::~LLUseCircuitCodeResponder()
+{
+ // even abstract base classes need a concrete destructor
+}
+
+static const char* nullToEmpty(const char* s)
+{
+ static char emptyString[] = "";
+ return s? s : emptyString;
+}
+
+void LLMessageSystem::init()
+{
+ // initialize member variables
+ mVerboseLog = false;
+
+ mbError = false;
+ mErrorCode = 0;
+ mSendReliable = false;
+
+ mUnackedListDepth = 0;
+ mUnackedListSize = 0;
+ mDSMaxListDepth = 0;
+
+ mNumberHighFreqMessages = 0;
+ mNumberMediumFreqMessages = 0;
+ mNumberLowFreqMessages = 0;
+ mPacketsIn = mPacketsOut = 0;
+ mBytesIn = mBytesOut = 0;
+ mCompressedPacketsIn = mCompressedPacketsOut = 0;
+ mReliablePacketsIn = mReliablePacketsOut = 0;
+
+ mCompressedBytesIn = 0;
+ mCompressedBytesOut = 0;
+ mUncompressedBytesIn = 0;
+ mUncompressedBytesOut = 0;
+ mTotalBytesIn = 0;
+ mTotalBytesOut = 0;
+
+ mDroppedPackets = 0; // total dropped packets in
+ mResentPackets = 0; // total resent packets out
+ mFailedResendPackets = 0; // total resend failure packets out
+ mOffCircuitPackets = 0; // total # of off-circuit packets rejected
+ mInvalidOnCircuitPackets = 0; // total # of on-circuit packets rejected
+
+ mOurCircuitCode = 0;
+
+ mIncomingCompressedSize = 0;
+ mCurrentRecvPacketID = 0;
+
+ mMessageFileVersionNumber = 0.f;
+
+ mTimingCallback = NULL;
+ mTimingCallbackData = NULL;
+
+ mMessageBuilder = NULL;
+ LockMessageReader(mMessageReader, NULL);
+}
+
+// Read file and build message templates
+LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
+ S32 version_major,
+ S32 version_minor,
+ S32 version_patch,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval, const F32 circuit_timeout) :
+ mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)),
+ mLastMessageFromTrustedMessageService(false)
+{
+ init();
+
+ mSendSize = 0;
+
+ mSystemVersionMajor = version_major;
+ mSystemVersionMinor = version_minor;
+ mSystemVersionPatch = version_patch;
+ mSystemVersionServer = 0;
+ mVersionFlags = 0x0;
+
+ // default to not accepting packets from not alive circuits
+ mbProtected = true;
+
+ // default to blocking trusted connections on a public interface if one is specified
+ mBlockUntrustedInterface = true;
+
+ mSendPacketFailureCount = 0;
+
+ mCircuitPrintFreq = F32Seconds(60.f);
+
+ loadTemplateFile(filename, failure_is_fatal);
+
+ mTemplateMessageBuilder = new LLTemplateMessageBuilder(mMessageTemplates);
+ mLLSDMessageBuilder = new LLSDMessageBuilder();
+ mMessageBuilder = NULL;
+
+ mTemplateMessageReader = new LLTemplateMessageReader(mMessageNumbers);
+ mLLSDMessageReader = new LLSDMessageReader();
+
+ // initialize various bits of net info
+ mSocket = 0;
+ mPort = port;
+
+ S32 error = start_net(mSocket, mPort);
+ if (error != 0)
+ {
+ mbError = true;
+ mErrorCode = error;
+ }
+// LL_DEBUGS("Messaging") << << "*** port: " << mPort << LL_ENDL;
+
+ //
+ // Create the data structure that we can poll on
+ //
+ if (!gAPRPoolp)
+ {
+ LL_ERRS("Messaging") << "No APR pool before message system initialization!" << LL_ENDL;
+ ll_init_apr();
+ }
+ apr_socket_t *aprSocketp = NULL;
+ apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
+
+ mPollInfop = new LLMessagePollInfo;
+ mPollInfop->mAPRSocketp = aprSocketp;
+ mPollInfop->mPollFD.p = gAPRPoolp;
+ mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
+ mPollInfop->mPollFD.reqevents = APR_POLLIN;
+ mPollInfop->mPollFD.rtnevents = 0;
+ mPollInfop->mPollFD.desc.s = aprSocketp;
+ mPollInfop->mPollFD.client_data = NULL;
+
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ mResendDumpTime = mt_sec;
+ mMessageCountTime = mt_sec;
+ mCircuitPrintTime = mt_sec;
+ mCurrentMessageTime = F64Seconds(mt_sec);
+
+ // Constants for dumping output based on message processing time/count
+ mNumMessageCounts = 0;
+ mMaxMessageCounts = 200; // >= 0 means dump warnings
+ mMaxMessageTime = F32Seconds(1.f);
+
+ mTrueReceiveSize = 0;
+
+ mReceiveTime = F32Seconds(0.f);
+}
+
+
+
+// Read file and build message templates
+void LLMessageSystem::loadTemplateFile(const std::string& filename, bool failure_is_fatal)
+{
+ if(filename.empty())
+ {
+ LL_ERRS("Messaging") << "No template filename specified" << LL_ENDL;
+ mbError = true;
+ return;
+ }
+
+ std::string template_body;
+ if(!_read_file_into_string(template_body, filename))
+ {
+ if (failure_is_fatal) {
+ LL_ERRS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
+ } else {
+ LL_WARNS("Messaging") << "Failed to open template: " << filename << LL_ENDL;
+ }
+ mbError = true;
+ return;
+ }
+
+ LLTemplateTokenizer tokens(template_body);
+ LLTemplateParser parsed(tokens);
+ mMessageFileVersionNumber = parsed.getVersion();
+ S32 count = 0;
+ for(LLTemplateParser::message_iterator iter = parsed.getMessagesBegin();
+ iter != parsed.getMessagesEnd();
+ iter++)
+ {
+ addTemplate(*iter);
+ count++;
+ }
+ LL_INFOS("Messaging") << "Read " << count << " messages from " << filename << LL_ENDL;
+}
+
+
+LLMessageSystem::~LLMessageSystem()
+{
+ mMessageTemplates.clear(); // don't delete templates.
+ for_each(mMessageNumbers.begin(), mMessageNumbers.end(), DeletePairedPointer());
+ mMessageNumbers.clear();
+
+ if (!mbError)
+ {
+ end_net(mSocket);
+ }
+ mSocket = 0;
+
+ delete mTemplateMessageReader;
+ mTemplateMessageReader = NULL;
+
+ delete mTemplateMessageBuilder;
+ mTemplateMessageBuilder = NULL;
+ mMessageBuilder = NULL;
+
+ delete mLLSDMessageReader;
+ mLLSDMessageReader = NULL;
+
+ delete mLLSDMessageBuilder;
+ mLLSDMessageBuilder = NULL;
+
+ delete mPollInfop;
+ mPollInfop = NULL;
+
+ mIncomingCompressedSize = 0;
+ mCurrentRecvPacketID = 0;
+}
+
+void LLMessageSystem::clearReceiveState()
+{
+ mCurrentRecvPacketID = 0;
+ mIncomingCompressedSize = 0;
+ mLastSender.invalidate();
+ mLastReceivingIF.invalidate();
+ mMessageReader->clearMessage();
+ mLastMessageFromTrustedMessageService = false;
+}
+
+
+bool LLMessageSystem::poll(F32 seconds)
+{
+ S32 num_socks;
+ apr_status_t status;
+ status = apr_poll(&(mPollInfop->mPollFD), 1, &num_socks,(U64)(seconds*1000000.f));
+ if (status != APR_TIMEUP)
+ {
+ ll_apr_warn_status(status);
+ }
+ if (num_socks)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool LLMessageSystem::isTrustedSender(const LLHost& host) const
+{
+ LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
+ if(NULL == cdp)
+ {
+ return false;
+ }
+ return cdp->getTrusted();
+}
+
+void LLMessageSystem::receivedMessageFromTrustedSender()
+{
+ mLastMessageFromTrustedMessageService = true;
+}
+
+bool LLMessageSystem::isTrustedSender() const
+{
+ return mLastMessageFromTrustedMessageService ||
+ isTrustedSender(getSender());
+}
+
+static LLMessageSystem::message_template_name_map_t::const_iterator
+findTemplate(const LLMessageSystem::message_template_name_map_t& templates,
+ std::string name)
+{
+ const char* namePrehash = LLMessageStringTable::getInstance()->getString(name.c_str());
+ if(NULL == namePrehash) {return templates.end();}
+ return templates.find(namePrehash);
+}
+
+bool LLMessageSystem::isTrustedMessage(const std::string& name) const
+{
+ message_template_name_map_t::const_iterator iter =
+ findTemplate(mMessageTemplates, name);
+ if(iter == mMessageTemplates.end()) {return false;}
+ return iter->second->getTrust() == MT_TRUST;
+}
+
+bool LLMessageSystem::isUntrustedMessage(const std::string& name) const
+{
+ message_template_name_map_t::const_iterator iter =
+ findTemplate(mMessageTemplates, name);
+ if(iter == mMessageTemplates.end()) {return false;}
+ return iter->second->getTrust() == MT_NOTRUST;
+}
+
+LLCircuitData* LLMessageSystem::findCircuit(const LLHost& host,
+ bool resetPacketId)
+{
+ LLCircuitData* cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ // This packet comes from a circuit we don't know about.
+
+ // Are we rejecting off-circuit packets?
+ if (mbProtected)
+ {
+ // cdp is already NULL, so we don't need to unset it.
+ }
+ else
+ {
+ // nope, open the new circuit
+ cdp = mCircuitInfo.addCircuitData(host, mCurrentRecvPacketID);
+
+ if(resetPacketId)
+ {
+ // I added this - I think it's correct - DJS
+ // reset packet in ID
+ cdp->setPacketInID(mCurrentRecvPacketID);
+ }
+ // And claim the packet is on the circuit we just added.
+ }
+ }
+ else
+ {
+ // this is an old circuit. . . is it still alive?
+ if (!cdp->isAlive())
+ {
+ // nope. don't accept if we're protected
+ if (mbProtected)
+ {
+ // don't accept packets from unexpected sources
+ cdp = NULL;
+ }
+ else
+ {
+ // wake up the circuit
+ cdp->setAlive(true);
+
+ if(resetPacketId)
+ {
+ // reset packet in ID
+ cdp->setPacketInID(mCurrentRecvPacketID);
+ }
+ }
+ }
+ }
+ return cdp;
+}
+
+// Returns true if a valid, on-circuit message has been received.
+// Requiring a non-const LockMessageChecker reference ensures that
+// mMessageReader has been set to mTemplateMessageReader.
+bool LLMessageSystem::checkMessages(LockMessageChecker&, S64 frame_count )
+{
+ // Pump
+ bool valid_packet = false;
+
+ LLTransferTargetVFile::updateQueue();
+
+ if (!mNumMessageCounts)
+ {
+ // This is the first message being handled after a resetReceiveCounts,
+ // we must be starting the message processing loop. Reset the timers.
+ mCurrentMessageTime = totalTime();
+ mMessageCountTime = getMessageTimeSeconds();
+ }
+
+ // loop until either no packets or a valid packet
+ // i.e., burn through packets from unregistered circuits
+ S32 receive_size = 0;
+ do
+ {
+ clearReceiveState();
+
+ bool recv_reliable = false;
+ bool recv_resent = false;
+ S32 acks = 0;
+ S32 true_rcv_size = 0;
+
+ U8* buffer = mTrueReceiveBuffer;
+
+ mTrueReceiveSize = mPacketRing.receivePacket(mSocket, (char *)mTrueReceiveBuffer);
+ // If you want to dump all received packets into SecondLife.log, uncomment this
+ //dumpPacketToLog();
+
+ receive_size = mTrueReceiveSize;
+ mLastSender = mPacketRing.getLastSender();
+ mLastReceivingIF = mPacketRing.getLastReceivingInterface();
+
+ if (receive_size < (S32) LL_MINIMUM_VALID_PACKET_SIZE)
+ {
+ // A receive size of zero is OK, that means that there are no more packets available.
+ // Ones that are non-zero but below the minimum packet size are worrisome.
+ if (receive_size > 0)
+ {
+ LL_WARNS("Messaging") << "Invalid (too short) packet discarded " << receive_size << LL_ENDL;
+ callExceptionFunc(MX_PACKET_TOO_SHORT);
+ }
+ // no data in packet receive buffer
+ valid_packet = false;
+ }
+ else
+ {
+ LLHost host;
+ LLCircuitData* cdp;
+
+ // note if packet acks are appended.
+ if(buffer[0] & LL_ACK_FLAG)
+ {
+ acks += buffer[--receive_size];
+ true_rcv_size = receive_size;
+ if(receive_size >= ((S32)(acks * sizeof(TPACKETID) + LL_MINIMUM_VALID_PACKET_SIZE)))
+ {
+ receive_size -= acks * sizeof(TPACKETID);
+ }
+ else
+ {
+ // mal-formed packet. ignore it and continue with
+ // the next one
+ LL_WARNS("Messaging") << "Malformed packet received. Packet size "
+ << receive_size << " with invalid no. of acks " << acks
+ << LL_ENDL;
+ valid_packet = false;
+ continue;
+ }
+ }
+
+ // process the message as normal
+ mIncomingCompressedSize = zeroCodeExpand(&buffer, &receive_size);
+ mCurrentRecvPacketID = ntohl(*((U32*)(&buffer[1])));
+ host = getSender();
+
+ const bool resetPacketId = true;
+ cdp = findCircuit(host, resetPacketId);
+
+ // At this point, cdp is now a pointer to the circuit that
+ // this message came in on if it's valid, and NULL if the
+ // circuit was bogus.
+
+ if(cdp && (acks > 0) && ((S32)(acks * sizeof(TPACKETID)) < (true_rcv_size)))
+ {
+ TPACKETID packet_id;
+ U32 mem_id=0;
+ for(S32 i = 0; i < acks; ++i)
+ {
+ true_rcv_size -= sizeof(TPACKETID);
+ memcpy(&mem_id, &mTrueReceiveBuffer[true_rcv_size], /* Flawfinder: ignore*/
+ sizeof(TPACKETID));
+ packet_id = ntohl(mem_id);
+ //LL_INFOS("Messaging") << "got ack: " << packet_id << LL_ENDL;
+ cdp->ackReliablePacket(packet_id);
+ }
+ if (!cdp->getUnackedPacketCount())
+ {
+ // Remove this circuit from the list of circuits with unacked packets
+ mCircuitInfo.mUnackedCircuitMap.erase(cdp->mHost);
+ }
+ }
+
+ if (buffer[0] & LL_RELIABLE_FLAG)
+ {
+ recv_reliable = true;
+ }
+ if (buffer[0] & LL_RESENT_FLAG)
+ {
+ recv_resent = true;
+ if (cdp && cdp->isDuplicateResend(mCurrentRecvPacketID))
+ {
+ // We need to ACK here to suppress
+ // further resends of packets we've
+ // already seen.
+ if (recv_reliable)
+ {
+ //mAckList.addData(new LLPacketAck(host, mCurrentRecvPacketID));
+ // ***************************************
+ // TESTING CODE
+ //if(mCircuitInfo.mCurrentCircuit->mHost != host)
+ //{
+ // LL_WARNS("Messaging") << "DISCARDED PACKET HOST MISMATCH! HOST: "
+ // << host << " CIRCUIT: "
+ // << mCircuitInfo.mCurrentCircuit->mHost
+ // << LL_ENDL;
+ //}
+ // ***************************************
+ //mCircuitInfo.mCurrentCircuit->mAcks.put(mCurrentRecvPacketID);
+ cdp->collectRAck(mCurrentRecvPacketID);
+ }
+
+ LL_DEBUGS("Messaging") << "Discarding duplicate resend from " << host << LL_ENDL;
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string tbuf;
+ tbuf = llformat( "\t%6d\t%6d\t%6d ", receive_size, (mIncomingCompressedSize ? mIncomingCompressedSize : receive_size), mCurrentRecvPacketID);
+ str << tbuf << "(unknown)"
+ << (recv_reliable ? " reliable" : "")
+ << " resent "
+ << ((acks > 0) ? "acks" : "")
+ << " DISCARD DUPLICATE";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+ mPacketsIn++;
+ valid_packet = false;
+ continue;
+ }
+ }
+
+ // UseCircuitCode can be a valid, off-circuit packet.
+ // But we don't want to acknowledge UseCircuitCode until the circuit is
+ // available, which is why the acknowledgement test is done above. JC
+ bool trusted = cdp && cdp->getTrusted();
+ valid_packet = mTemplateMessageReader->validateMessage(
+ buffer,
+ receive_size,
+ host,
+ trusted);
+ if (!valid_packet)
+ {
+ clearReceiveState();
+ }
+
+ // UseCircuitCode is allowed in even from an invalid circuit, so that
+ // we can toss circuits around.
+ if(
+ valid_packet &&
+ !cdp &&
+ (mTemplateMessageReader->getMessageName() !=
+ _PREHASH_UseCircuitCode))
+ {
+ logMsgFromInvalidCircuit( host, recv_reliable );
+ clearReceiveState();
+ valid_packet = false;
+ }
+
+ if(
+ valid_packet &&
+ cdp &&
+ !cdp->getTrusted() &&
+ mTemplateMessageReader->isTrusted())
+ {
+ logTrustedMsgFromUntrustedCircuit( host );
+ clearReceiveState();
+
+ sendDenyTrustedCircuit(host);
+ valid_packet = false;
+ }
+
+ if( valid_packet )
+ {
+ logValidMsg(cdp, host, recv_reliable, recv_resent, acks>0 );
+ valid_packet = mTemplateMessageReader->readMessage(buffer, host);
+ }
+
+ // It's possible that the circuit went away, because ANY message can disable the circuit
+ // (for example, UseCircuit, CloseCircuit, DisableSimulator). Find it again.
+ cdp = mCircuitInfo.findCircuit(host);
+
+ if (valid_packet)
+ {
+ mPacketsIn++;
+ mBytesIn += mTrueReceiveSize;
+
+ // ACK here for valid packets that we've seen
+ // for the first time.
+ if (cdp && recv_reliable)
+ {
+ // Add to the recently received list for duplicate suppression
+ cdp->mRecentlyReceivedReliablePackets[mCurrentRecvPacketID] = getMessageTimeUsecs();
+
+ // Put it onto the list of packets to be acked
+ cdp->collectRAck(mCurrentRecvPacketID);
+ mReliablePacketsIn++;
+ }
+ }
+ else
+ {
+ if (mbProtected && (!cdp))
+ {
+ LL_WARNS("Messaging") << "Invalid Packet from invalid circuit " << host << LL_ENDL;
+ mOffCircuitPackets++;
+ }
+ else
+ {
+ mInvalidOnCircuitPackets++;
+ }
+ }
+ }
+ } while (!valid_packet && receive_size > 0);
+
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ // Check to see if we need to print debug info
+ if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq)
+ {
+ dumpCircuitInfo();
+ mCircuitPrintTime = mt_sec;
+ }
+
+ if( !valid_packet )
+ {
+ clearReceiveState();
+ }
+
+ return valid_packet;
+}
+
+S32 LLMessageSystem::getReceiveBytes() const
+{
+ if (getReceiveCompressedSize())
+ {
+ return getReceiveCompressedSize() * 8;
+ }
+ else
+ {
+ return getReceiveSize() * 8;
+ }
+}
+
+
+void LLMessageSystem::processAcks(LockMessageChecker&, F32 collect_time)
+{
+ F64Seconds mt_sec = getMessageTimeSeconds();
+ {
+ gTransferManager.updateTransfers();
+
+ if (gXferManager)
+ {
+ gXferManager->retransmitUnackedPackets();
+ }
+
+ if (gAssetStorage)
+ {
+ gAssetStorage->checkForTimeouts();
+ }
+ }
+
+ bool dump = false;
+ {
+ // Check the status of circuits
+ mCircuitInfo.updateWatchDogTimers(this);
+
+ //resend any necessary packets
+ mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize);
+
+ //cycle through ack list for each host we need to send acks to
+ mCircuitInfo.sendAcks(collect_time);
+
+ if (!mDenyTrustedCircuitSet.empty())
+ {
+ LL_INFOS("Messaging") << "Sending queued DenyTrustedCircuit messages." << LL_ENDL;
+ for (host_set_t::iterator hostit = mDenyTrustedCircuitSet.begin(); hostit != mDenyTrustedCircuitSet.end(); ++hostit)
+ {
+ reallySendDenyTrustedCircuit(*hostit);
+ }
+ mDenyTrustedCircuitSet.clear();
+ }
+
+ if (mMaxMessageCounts >= 0)
+ {
+ if (mNumMessageCounts >= mMaxMessageCounts)
+ {
+ dump = true;
+ }
+ }
+
+ if (mMaxMessageTime >= F32Seconds(0.f))
+ {
+ // This is one of the only places where we're required to get REAL message system time.
+ mReceiveTime = getMessageTimeSeconds(true) - mMessageCountTime;
+ if (mReceiveTime > mMaxMessageTime)
+ {
+ dump = true;
+ }
+ }
+ }
+
+ if (dump)
+ {
+ dumpReceiveCounts();
+ }
+ resetReceiveCounts();
+
+ if ((mt_sec - mResendDumpTime) > CIRCUIT_DUMP_TIMEOUT)
+ {
+ mResendDumpTime = mt_sec;
+ mCircuitInfo.dumpResends();
+ }
+}
+
+void LLMessageSystem::copyMessageReceivedToSend()
+{
+ // NOTE: babbage: switch builder to match reader to avoid
+ // converting message format
+ if(mMessageReader == mTemplateMessageReader)
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ else
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ mSendReliable = false;
+ mMessageBuilder->newMessage(mMessageReader->getMessageName());
+ mMessageReader->copyToBuilder(*mMessageBuilder);
+}
+
+LLSD LLMessageSystem::getReceivedMessageLLSD() const
+{
+ LLSDMessageBuilder builder;
+ mMessageReader->copyToBuilder(builder);
+ return builder.getMessage();
+}
+
+LLSD LLMessageSystem::getBuiltMessageLLSD() const
+{
+ LLSD result;
+ if (mLLSDMessageBuilder == mMessageBuilder)
+ {
+ result = mLLSDMessageBuilder->getMessage();
+ }
+ else
+ {
+ // TODO: implement as below?
+ LL_ERRS() << "Message not built as LLSD." << LL_ENDL;
+ }
+ return result;
+}
+
+LLSD LLMessageSystem::wrapReceivedTemplateData() const
+{
+ if(mMessageReader == mTemplateMessageReader)
+ {
+ LLTemplateMessageBuilder builder(mMessageTemplates);
+ builder.newMessage(mMessageReader->getMessageName());
+ mMessageReader->copyToBuilder(builder);
+ U8 buffer[MAX_BUFFER_SIZE];
+ const U8 offset_to_data = 0;
+ U32 size = builder.buildMessage(buffer, MAX_BUFFER_SIZE,
+ offset_to_data);
+ std::vector<U8> binary_data(buffer, buffer+size);
+ LLSD wrapped_data = LLSD::emptyMap();
+ wrapped_data["binary-template-data"] = binary_data;
+ return wrapped_data;
+ }
+ else
+ {
+ return getReceivedMessageLLSD();
+ }
+}
+
+LLSD LLMessageSystem::wrapBuiltTemplateData() const
+{
+ LLSD result;
+ if (mLLSDMessageBuilder == mMessageBuilder)
+ {
+ result = getBuiltMessageLLSD();
+ }
+ else
+ {
+ U8 buffer[MAX_BUFFER_SIZE];
+ const U8 offset_to_data = 0;
+ U32 size = mTemplateMessageBuilder->buildMessage(
+ buffer, MAX_BUFFER_SIZE,
+ offset_to_data);
+ std::vector<U8> binary_data(buffer, buffer+size);
+ LLSD wrapped_data = LLSD::emptyMap();
+ wrapped_data["binary-template-data"] = binary_data;
+ result = wrapped_data;
+ }
+ return result;
+}
+
+LLStoredMessagePtr LLMessageSystem::getReceivedMessage() const
+{
+ const std::string& name = mMessageReader->getMessageName();
+ LLSD message = wrapReceivedTemplateData();
+
+ return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+LLStoredMessagePtr LLMessageSystem::getBuiltMessage() const
+{
+ const std::string& name = mMessageBuilder->getMessageName();
+ LLSD message = wrapBuiltTemplateData();
+
+ return LLStoredMessagePtr(new LLStoredMessage(name, message));
+}
+
+S32 LLMessageSystem::sendMessage(const LLHost &host, LLStoredMessagePtr message)
+{
+ return sendMessage(host, message->mName.c_str(), message->mMessage);
+}
+
+
+void LLMessageSystem::clearMessage()
+{
+ mSendReliable = false;
+ mMessageBuilder->clearMessage();
+}
+
+// set block to add data to within current message
+void LLMessageSystem::nextBlockFast(const char *blockname)
+{
+ mMessageBuilder->nextBlock(blockname);
+}
+
+void LLMessageSystem::nextBlock(const char *blockname)
+{
+ nextBlockFast(LLMessageStringTable::getInstance()->getString(blockname));
+}
+
+bool LLMessageSystem::isSendFull(const char* blockname)
+{
+ char* stringTableName = NULL;
+ if(NULL != blockname)
+ {
+ stringTableName = LLMessageStringTable::getInstance()->getString(blockname);
+ }
+ return isSendFullFast(stringTableName);
+}
+
+bool LLMessageSystem::isSendFullFast(const char* blockname)
+{
+ return mMessageBuilder->isMessageFull(blockname);
+}
+
+
+// blow away the last block of a message, return false if that leaves no blocks or there wasn't a block to remove
+// TODO: Babbage: Remove this horror.
+bool LLMessageSystem::removeLastBlock()
+{
+ return mMessageBuilder->removeLastBlock();
+}
+
+S32 LLMessageSystem::sendReliable(const LLHost &host)
+{
+ return sendReliable(host, LL_DEFAULT_RELIABLE_RETRIES, true, LL_PING_BASED_TIMEOUT_DUMMY, NULL, NULL);
+}
+
+
+S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+ F32Seconds timeout;
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+ F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
+ }
+
+ constexpr S32 retries = 0;
+ constexpr bool ping_based_timeout = false;
+ return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
+}
+
+// send the message via a UDP packet
+S32 LLMessageSystem::sendReliable( const LLHost &host,
+ S32 retries,
+ bool ping_based_timeout,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data)
+{
+ if (ping_based_timeout)
+ {
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX));
+ }
+ }
+
+ mSendReliable = true;
+ mReliablePacketParams.set(host, retries, ping_based_timeout, timeout,
+ callback, callback_data,
+ const_cast<char*>(mMessageBuilder->getMessageName()));
+ return sendMessage(host);
+}
+
+void LLMessageSystem::forwardMessage(const LLHost &host)
+{
+ copyMessageReceivedToSend();
+ sendMessage(host);
+}
+
+void LLMessageSystem::forwardReliable(const LLHost &host)
+{
+ copyMessageReceivedToSend();
+ sendReliable(host);
+}
+
+void LLMessageSystem::forwardReliable(const U32 circuit_code)
+{
+ copyMessageReceivedToSend();
+ sendReliable(findHost(circuit_code));
+}
+
+S32 LLMessageSystem::forwardReliable( const LLHost &host,
+ S32 retries,
+ bool ping_based_timeout,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data)
+{
+ copyMessageReceivedToSend();
+ return sendReliable(host, retries, ping_based_timeout, timeout, callback, callback_data);
+}
+
+S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data)
+{
+ F32Seconds timeout;
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS,
+ F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()));
+ }
+ else
+ {
+ timeout = LL_SEMIRELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX;
+ }
+
+ S32 send_bytes = 0;
+ if (mMessageBuilder->getMessageSize())
+ {
+ mSendReliable = true;
+ // No need for ping-based retry as not going to retry
+ mReliablePacketParams.set(host, 0, false, timeout, callback,
+ callback_data,
+ const_cast<char*>(mMessageBuilder->getMessageName()));
+ send_bytes = sendMessage(host);
+ clearMessage();
+ }
+ else
+ {
+ delete callback_data;
+ }
+ return send_bytes;
+}
+
+S32 LLMessageSystem::flushReliable(const LLHost &host)
+{
+ S32 send_bytes = 0;
+ if (mMessageBuilder->getMessageSize())
+ {
+ send_bytes = sendReliable(host);
+ }
+ clearMessage();
+ return send_bytes;
+}
+
+// This can be called from signal handlers,
+// so should should not use LL_INFOS().
+S32 LLMessageSystem::sendMessage(const LLHost &host)
+{
+ if (! mMessageBuilder->isBuilt())
+ {
+ mSendSize = mMessageBuilder->buildMessage(
+ mSendBuffer,
+ MAX_BUFFER_SIZE,
+ 0);
+ }
+
+ if (!(host.isOk())) // if port and ip are zero, don't bother trying to send the message
+ {
+ return 0;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ // this is a new circuit!
+ // are we protected?
+ if (mbProtected)
+ {
+ // yup! don't send packets to an unknown circuit
+ if(mVerboseLog)
+ {
+ LL_INFOS_ONCE("Messaging") << "MSG: -> " << host << "\tUNKNOWN CIRCUIT:\t"
+ << mMessageBuilder->getMessageName() << LL_ENDL;
+ }
+ LL_WARNS_ONCE("Messaging") << "sendMessage - Trying to send "
+ << mMessageBuilder->getMessageName() << " on unknown circuit "
+ << host << LL_ENDL;
+ return 0;
+ }
+ else
+ {
+ // nope, open the new circuit
+
+ cdp = mCircuitInfo.addCircuitData(host, 0);
+ }
+ }
+ else
+ {
+ // this is an old circuit. . . is it still alive?
+ if (!cdp->isAlive())
+ {
+ // nope. don't send to dead circuits
+ if(mVerboseLog)
+ {
+ LL_INFOS("Messaging") << "MSG: -> " << host << "\tDEAD CIRCUIT\t\t"
+ << mMessageBuilder->getMessageName() << LL_ENDL;
+ }
+ LL_WARNS("Messaging") << "sendMessage - Trying to send message "
+ << mMessageBuilder->getMessageName() << " to dead circuit "
+ << host << LL_ENDL;
+ return 0;
+ }
+ }
+
+ // NOTE: babbage: LLSD message -> HTTP, template message -> UDP
+ if(mMessageBuilder == mLLSDMessageBuilder)
+ {
+ LLSD message = mLLSDMessageBuilder->getMessage();
+
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(),
+ mLLSDMessageBuilder->getMessageName(), message, cb));
+
+ mSendReliable = false;
+ mReliablePacketParams.clear();
+ return 1;
+ }
+
+ // zero out the flags and packetid. Subtract 1 here so that we do
+ // not overwrite the offset if it was set set in buildMessage().
+ memset(mSendBuffer, 0, LL_PACKET_ID_SIZE - 1);
+
+ // add the send id to the front of the message
+ cdp->nextPacketOutID();
+
+ // Packet ID size is always 4
+ *((S32*)&mSendBuffer[PHL_PACKET_ID]) = htonl(cdp->getPacketOutID());
+
+ // Compress the message, which will usually reduce its size.
+ U8 * buf_ptr = (U8 *)mSendBuffer;
+ U32 buffer_length = mSendSize;
+ mMessageBuilder->compressMessage(buf_ptr, buffer_length);
+
+ if (buffer_length > 1500)
+ {
+ if((mMessageBuilder->getMessageName() != _PREHASH_ChildAgentUpdate)
+ && (mMessageBuilder->getMessageName() != _PREHASH_SendXferPacket))
+ {
+ LL_WARNS("Messaging") << "sendMessage - Trying to send "
+ << ((buffer_length > 4000) ? "EXTRA " : "")
+ << "BIG message " << mMessageBuilder->getMessageName() << " - "
+ << buffer_length << LL_ENDL;
+ }
+ }
+ if (mSendReliable)
+ {
+ buf_ptr[0] |= LL_RELIABLE_FLAG;
+
+ if (!cdp->getUnackedPacketCount())
+ {
+ // We are adding the first packed onto the unacked packet list(s)
+ // Add this circuit to the list of circuits with unacked packets
+ mCircuitInfo.mUnackedCircuitMap[cdp->mHost] = cdp;
+ }
+
+ cdp->addReliablePacket(mSocket,buf_ptr,buffer_length, &mReliablePacketParams);
+ mReliablePacketsOut++;
+ }
+
+ // tack packet acks onto the end of this message
+ S32 space_left = (MTUBYTES - buffer_length) / sizeof(TPACKETID); // space left for packet ids
+ S32 ack_count = (S32)cdp->mAcks.size();
+ bool is_ack_appended = false;
+ std::vector<TPACKETID> acks;
+ if((space_left > 0) && (ack_count > 0) &&
+ (mMessageBuilder->getMessageName() != _PREHASH_PacketAck))
+ {
+ buf_ptr[0] |= LL_ACK_FLAG;
+ S32 append_ack_count = llmin(space_left, ack_count);
+ const S32 MAX_ACKS = 250;
+ append_ack_count = llmin(append_ack_count, MAX_ACKS);
+ std::vector<TPACKETID>::iterator iter = cdp->mAcks.begin();
+ std::vector<TPACKETID>::iterator last = cdp->mAcks.begin();
+ last += append_ack_count;
+ TPACKETID packet_id;
+ for( ; iter != last ; ++iter)
+ {
+ // grab the next packet id.
+ packet_id = (*iter);
+ if(mVerboseLog)
+ {
+ acks.push_back(packet_id);
+ }
+
+ // put it on the end of the buffer
+ packet_id = htonl(packet_id);
+
+ if((S32)(buffer_length + sizeof(TPACKETID)) < MAX_BUFFER_SIZE)
+ {
+ memcpy(&buf_ptr[buffer_length], &packet_id, sizeof(TPACKETID)); /* Flawfinder: ignore */
+ // Do the accounting
+ buffer_length += sizeof(TPACKETID);
+ }
+ else
+ {
+ // Just reporting error is likely not enough. Need to
+ // check how to abort or error out gracefully from
+ // this function. XXXTBD
+ // *NOTE: Actually hitting this error would indicate
+ // the calculation above for space_left, ack_count,
+ // append_acout_count is incorrect or that
+ // MAX_BUFFER_SIZE has fallen below MTU which is bad
+ // and probably programmer error.
+ LL_ERRS("Messaging") << "Buffer packing failed due to size.." << LL_ENDL;
+ }
+ }
+
+ // clean up the source
+ cdp->mAcks.erase(cdp->mAcks.begin(), last);
+
+ // tack the count in the final byte
+ U8 count = (U8)append_ack_count;
+ buf_ptr[buffer_length++] = count;
+ is_ack_appended = true;
+ }
+
+ bool success;
+ success = mPacketRing.sendPacket(mSocket, (char *)buf_ptr, buffer_length, host);
+
+ if (!success)
+ {
+ mSendPacketFailureCount++;
+ }
+ else
+ {
+ // mCircuitInfo already points to the correct circuit data
+ cdp->addBytesOut( (S32Bytes)buffer_length );
+ }
+
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: -> " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mSendSize, buffer_length, cdp->getPacketOutID());
+ str << buffer
+ << mMessageBuilder->getMessageName()
+ << (mSendReliable ? " reliable " : "");
+ if(is_ack_appended)
+ {
+ str << "\tACKS:\t";
+ std::ostream_iterator<TPACKETID> append(str, " ");
+ std::copy(acks.begin(), acks.end(), append);
+ }
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+
+
+ mPacketsOut++;
+ mTotalBytesOut += buffer_length;
+
+ mSendReliable = false;
+ mReliablePacketParams.clear();
+ return buffer_length;
+}
+
+void LLMessageSystem::logMsgFromInvalidCircuit( const LLHost& host, bool recv_reliable )
+{
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize: mMessageReader->getMessageSize()), mCurrentRecvPacketID);
+ str << buffer
+ << nullToEmpty(mMessageReader->getMessageName())
+ << (recv_reliable ? " reliable" : "")
+ << " REJECTED";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+ // nope!
+ // cout << "Rejecting unexpected message " << mCurrentMessageTemplate->mName << " from " << hex << ip << " , " << dec << port << endl;
+
+ // Keep track of rejected messages as well
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ // mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = true;
+ mNumMessageCounts++;
+ }
+}
+
+S32 LLMessageSystem::sendMessage(
+ const LLHost &host,
+ const char* name,
+ const LLSD& message)
+{
+ if (!(host.isOk()))
+ {
+ LL_WARNS("Messaging") << "trying to send message to invalid host" << LL_ENDL;
+ return 0;
+ }
+
+ UntrustedCallback_t cb = NULL;
+ if ((mSendReliable) && (mReliablePacketParams.mCallback))
+ {
+ cb = boost::bind(mReliablePacketParams.mCallback, mReliablePacketParams.mCallbackData, _1);
+ }
+
+ LLCoros::instance().launch("LLMessageSystem::sendUntrustedSimulatorMessageCoro",
+ boost::bind(&LLMessageSystem::sendUntrustedSimulatorMessageCoro, this,
+ host.getUntrustedSimulatorCap(), name, message, cb));
+ return 1;
+}
+
+void LLMessageSystem::logTrustedMsgFromUntrustedCircuit( const LLHost& host )
+{
+ // RequestTrustedCircuit is how we establish trust, so don't spam
+ // if it's received on a trusted circuit. JC
+ if (strcmp(mMessageReader->getMessageName(), "RequestTrustedCircuit"))
+ {
+ LL_WARNS("Messaging") << "Received trusted message on untrusted circuit. "
+ << "Will reply with deny. "
+ << "Message: " << nullToEmpty(mMessageReader->getMessageName())
+ << " Host: " << host << LL_ENDL;
+ }
+
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "got more than " << MAX_MESSAGE_COUNT_NUM
+ << " packets without clearing counts"
+ << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ //mMessageCountList[mNumMessageCounts].mMessageNum
+ // = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes
+ = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = true;
+ mNumMessageCounts++;
+ }
+}
+
+void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, bool recv_reliable, bool recv_resent, bool recv_acks )
+{
+ if (mNumMessageCounts >= MAX_MESSAGE_COUNT_NUM)
+ {
+ LL_WARNS("Messaging") << "Got more than " << MAX_MESSAGE_COUNT_NUM << " packets without clearing counts" << LL_ENDL;
+ }
+ else
+ {
+ // TODO: babbage: work out if we need these
+ //mMessageCountList[mNumMessageCounts].mMessageNum = mCurrentRMessageTemplate->mMessageNumber;
+ mMessageCountList[mNumMessageCounts].mMessageBytes = mMessageReader->getMessageSize();
+ mMessageCountList[mNumMessageCounts].mInvalid = false;
+ mNumMessageCounts++;
+ }
+
+ if (cdp)
+ {
+ // update circuit packet ID tracking (missing/out of order packets)
+ cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent );
+ cdp->addBytesIn( (S32Bytes)mTrueReceiveSize );
+ }
+
+ if(mVerboseLog)
+ {
+ std::ostringstream str;
+ str << "MSG: <- " << host;
+ std::string buffer;
+ buffer = llformat( "\t%6d\t%6d\t%6d ", mMessageReader->getMessageSize(), (mIncomingCompressedSize ? mIncomingCompressedSize : mMessageReader->getMessageSize()), mCurrentRecvPacketID);
+ str << buffer
+ << nullToEmpty(mMessageReader->getMessageName())
+ << (recv_reliable ? " reliable" : "")
+ << (recv_resent ? " resent" : "")
+ << (recv_acks ? " acks" : "");
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+ }
+}
+
+void LLMessageSystem::sanityCheck()
+{
+// TODO: babbage: reinstate
+
+// if (!mCurrentRMessageData)
+// {
+// LL_ERRS("Messaging") << "mCurrentRMessageData is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRMessageTemplate)
+// {
+// LL_ERRS("Messaging") << "mCurrentRMessageTemplate is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRTemplateBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentRTemplateBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentRDataBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentRDataBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSMessageData)
+// {
+// LL_ERRS("Messaging") << "mCurrentSMessageData is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSMessageTemplate)
+// {
+// LL_ERRS("Messaging") << "mCurrentSMessageTemplate is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSTemplateBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentSTemplateBlock is NULL" << LL_ENDL;
+// }
+
+// if (!mCurrentSDataBlock)
+// {
+// LL_ERRS("Messaging") << "mCurrentSDataBlock is NULL" << LL_ENDL;
+// }
+}
+
+void LLMessageSystem::showCircuitInfo()
+{
+ LL_INFOS("Messaging") << mCircuitInfo << LL_ENDL;
+}
+
+
+void LLMessageSystem::dumpCircuitInfo()
+{
+ LL_DEBUGS("Messaging") << mCircuitInfo << LL_ENDL;
+}
+
+/* virtual */
+U32 LLMessageSystem::getOurCircuitCode()
+{
+ return mOurCircuitCode;
+}
+
+void LLMessageSystem::getCircuitInfo(LLSD& info) const
+{
+ mCircuitInfo.getInfo(info);
+}
+
+// returns whether the given host is on a trusted circuit
+bool LLMessageSystem::getCircuitTrust(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->getTrusted();
+ }
+
+ return false;
+}
+
+// Activate a circuit, and set its trust level (true if trusted,
+// false if not).
+void LLMessageSystem::enableCircuit(const LLHost &host, bool trusted)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ cdp = mCircuitInfo.addCircuitData(host, 0);
+ }
+ else
+ {
+ cdp->setAlive(true);
+ }
+ cdp->setTrusted(trusted);
+}
+
+void LLMessageSystem::disableCircuit(const LLHost &host)
+{
+ LL_INFOS("Messaging") << "LLMessageSystem::disableCircuit for " << host << LL_ENDL;
+ U32 code = gMessageSystem->findCircuitCode( host );
+
+ // Don't need to do this, as we're removing the circuit info anyway - djs 01/28/03
+
+ // don't clean up 0 circuit code entries
+ // because many hosts (neighbor sims, etc) can have the 0 circuit
+ if (code)
+ {
+ //if (mCircuitCodes.checkKey(code))
+ code_session_map_t::iterator it = mCircuitCodes.find(code);
+ if(it != mCircuitCodes.end())
+ {
+ LL_INFOS("Messaging") << "Circuit " << code << " removed from list" << LL_ENDL;
+ //mCircuitCodes.removeData(code);
+ mCircuitCodes.erase(it);
+ }
+
+ U64 ip_port = 0;
+ std::map<U32, U64>::iterator iter = gMessageSystem->mCircuitCodeToIPPort.find(code);
+ if (iter != gMessageSystem->mCircuitCodeToIPPort.end())
+ {
+ ip_port = iter->second;
+
+ gMessageSystem->mCircuitCodeToIPPort.erase(iter);
+
+ U32 old_port = (U32)(ip_port & (U64)0xFFFFFFFF);
+ U32 old_ip = (U32)(ip_port >> 32);
+
+ LL_INFOS("Messaging") << "Host " << LLHost(old_ip, old_port) << " circuit " << code << " removed from lookup table" << LL_ENDL;
+ gMessageSystem->mIPPortToCircuitCode.erase(ip_port);
+ }
+ mCircuitInfo.removeCircuitData(host);
+ }
+ else
+ {
+ // Sigh, since we can open circuits which don't have circuit
+ // codes, it's possible for this to happen...
+
+ LL_WARNS("Messaging") << "Couldn't find circuit code for " << host << LL_ENDL;
+ }
+
+}
+
+
+void LLMessageSystem::setCircuitAllowTimeout(const LLHost &host, bool allow)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ cdp->setAllowTimeout(allow);
+ }
+}
+
+void LLMessageSystem::setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost & host, void *user_data), void *user_data)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ cdp->setTimeoutCallback(callback_func, user_data);
+ }
+}
+
+
+bool LLMessageSystem::checkCircuitBlocked(const U32 circuit)
+{
+ LLHost host = findHost(circuit);
+
+ if (!host.isOk())
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitBlocked: Unknown circuit " << circuit << LL_ENDL;
+ return true;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isBlocked();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "checkCircuitBlocked(circuit): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+bool LLMessageSystem::checkCircuitAlive(const U32 circuit)
+{
+ LLHost host = findHost(circuit);
+
+ if (!host.isOk())
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitAlive: Unknown circuit " << circuit << LL_ENDL;
+ return false;
+ }
+
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isAlive();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "checkCircuitAlive(circuit): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+bool LLMessageSystem::checkCircuitAlive(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+ return cdp->isAlive();
+ }
+ else
+ {
+ LL_DEBUGS("Messaging") << "checkCircuitAlive(host): Unknown host - " << host << LL_ENDL;
+ return false;
+ }
+}
+
+
+void LLMessageSystem::setCircuitProtection(bool b_protect)
+{
+ mbProtected = b_protect;
+}
+
+
+U32 LLMessageSystem::findCircuitCode(const LLHost &host)
+{
+ U64 ip64 = (U64) host.getAddress();
+ U64 port64 = (U64) host.getPort();
+ U64 ip_port = (ip64 << 32) | port64;
+
+ return get_if_there(mIPPortToCircuitCode, ip_port, U32(0));
+}
+
+LLHost LLMessageSystem::findHost(const U32 circuit_code)
+{
+ if (mCircuitCodeToIPPort.count(circuit_code) > 0)
+ {
+ return LLHost(mCircuitCodeToIPPort[circuit_code]);
+ }
+ else
+ {
+ return LLHost();
+ }
+}
+
+void LLMessageSystem::setMaxMessageTime(const F32 seconds)
+{
+ mMaxMessageTime = F32Seconds(seconds);
+}
+
+void LLMessageSystem::setMaxMessageCounts(const S32 num)
+{
+ mMaxMessageCounts = num;
+}
+
+
+std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg)
+{
+ U32 i;
+ if (msg.mbError)
+ {
+ s << "Message system not correctly initialized";
+ }
+ else
+ {
+ s << "Message system open on port " << msg.mPort << " and socket " << msg.mSocket << "\n";
+// s << "Message template file " << msg.mName << " loaded\n";
+
+ s << "\nHigh frequency messages:\n";
+
+ for (i = 1; msg.mMessageNumbers[i] && (i < 255); i++)
+ {
+ s << *(msg.mMessageNumbers[i]);
+ }
+
+ s << "\nMedium frequency messages:\n";
+
+ for (i = (255 << 8) + 1; msg.mMessageNumbers[i] && (i < (255 << 8) + 255); i++)
+ {
+ s << *msg.mMessageNumbers[i];
+ }
+
+ s << "\nLow frequency messages:\n";
+
+ for (i = (0xFFFF0000) + 1; msg.mMessageNumbers[i] && (i < 0xFFFFFFFF); i++)
+ {
+ s << *msg.mMessageNumbers[i];
+ }
+ }
+ return s;
+}
+
+// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.)
+// callback registrations for when gMessageSystem is first assigned
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
+
+// update appropriate ping info
+void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U8 ping_id;
+ msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
+
+ LLCircuitData *cdp;
+ cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
+
+ // stop the appropriate timer
+ if (cdp)
+ {
+ cdp->pingTimerStop(ping_id);
+ }
+}
+
+void process_start_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U8 ping_id;
+ msgsystem->getU8Fast(_PREHASH_PingID, _PREHASH_PingID, ping_id);
+
+ LLCircuitData *cdp;
+ cdp = msgsystem->mCircuitInfo.findCircuit(msgsystem->getSender());
+ if (cdp)
+ {
+ // Grab the packet id of the oldest unacked packet
+ U32 packet_id;
+ msgsystem->getU32Fast(_PREHASH_PingID, _PREHASH_OldestUnacked, packet_id);
+ cdp->clearDuplicateList(packet_id);
+ }
+
+ // Send off the response
+ msgsystem->newMessageFast(_PREHASH_CompletePingCheck);
+ msgsystem->nextBlockFast(_PREHASH_PingID);
+ msgsystem->addU8(_PREHASH_PingID, ping_id);
+ msgsystem->sendMessage(msgsystem->getSender());
+}
+
+
+
+// Note: this is currently unused. --mark
+void open_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ U32 ip;
+ U16 port;
+
+ msgsystem->getIPAddrFast(_PREHASH_CircuitInfo, _PREHASH_IP, ip);
+ msgsystem->getIPPortFast(_PREHASH_CircuitInfo, _PREHASH_Port, port);
+
+ // By default, OpenCircuit's are untrusted
+ msgsystem->enableCircuit(LLHost(ip, port), false);
+}
+
+void close_circuit(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ msgsystem->disableCircuit(msgsystem->getSender());
+}
+
+// static
+/*
+void LLMessageSystem::processAssignCircuitCode(LLMessageSystem* msg, void**)
+{
+ // if we already have a circuit code, we can bail
+ if(msg->mOurCircuitCode) return;
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ if(session_id != msg->getMySessionID())
+ {
+ LL_WARNS("Messaging") << "AssignCircuitCode, bad session id. Expecting "
+ << msg->getMySessionID() << " but got " << session_id
+ << LL_ENDL;
+ return;
+ }
+ U32 code;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
+ if (!code)
+ {
+ LL_ERRS("Messaging") << "Assigning circuit code of zero!" << LL_ENDL;
+ }
+
+ msg->mOurCircuitCode = code;
+ LL_INFOS("Messaging") << "Circuit code " << code << " assigned." << LL_ENDL;
+}
+*/
+
+// static
+void LLMessageSystem::processAddCircuitCode(LLMessageSystem* msg, void**)
+{
+ U32 code;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, code);
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ (void)msg->addCircuitCode(code, session_id);
+
+ // Send the ack back
+ //msg->newMessageFast(_PREHASH_AckAddCircuitCode);
+ //msg->nextBlockFast(_PREHASH_CircuitCode);
+ //msg->addU32Fast(_PREHASH_Code, code);
+ //msg->sendMessage(msg->getSender());
+}
+
+bool LLMessageSystem::addCircuitCode(U32 code, const LLUUID& session_id)
+{
+ if(!code)
+ {
+ LL_WARNS("Messaging") << "addCircuitCode: zero circuit code" << LL_ENDL;
+ return false;
+ }
+ code_session_map_t::iterator it = mCircuitCodes.find(code);
+ if(it == mCircuitCodes.end())
+ {
+ LL_INFOS("Messaging") << "New circuit code " << code << " added" << LL_ENDL;
+ //msg->mCircuitCodes[circuit_code] = circuit_code;
+
+ mCircuitCodes.insert(code_session_map_t::value_type(code, session_id));
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "Duplicate circuit code " << code << " added" << LL_ENDL;
+ }
+ return true;
+}
+
+//void ack_add_circuit_code(LLMessageSystem *msgsystem, void** /*user_data*/)
+//{
+ // By default, we do nothing. This particular message is only handled by the spaceserver
+//}
+
+// static
+void LLMessageSystem::processUseCircuitCode(LLMessageSystem* msg,
+ void** user)
+{
+ U32 circuit_code_in;
+ msg->getU32Fast(_PREHASH_CircuitCode, _PREHASH_Code, circuit_code_in);
+
+ U32 ip = msg->getSenderIP();
+ U32 port = msg->getSenderPort();
+
+ U64 ip64 = ip;
+ U64 port64 = port;
+ U64 ip_port_in = (ip64 << 32) | port64;
+
+ if (circuit_code_in)
+ {
+ //if (!msg->mCircuitCodes.checkKey(circuit_code_in))
+ code_session_map_t::iterator it;
+ it = msg->mCircuitCodes.find(circuit_code_in);
+ if(it == msg->mCircuitCodes.end())
+ {
+ // Whoah, abort! We don't know anything about this circuit code.
+ LL_WARNS("Messaging") << "UseCircuitCode for " << circuit_code_in
+ << " received without AddCircuitCode message - aborting"
+ << LL_ENDL;
+ return;
+ }
+
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_ID, id);
+ LLUUID session_id;
+ msg->getUUIDFast(_PREHASH_CircuitCode, _PREHASH_SessionID, session_id);
+ if(session_id != (*it).second)
+ {
+ LL_WARNS("Messaging") << "UseCircuitCode unmatched session id. Got "
+ << session_id << " but expected " << (*it).second
+ << LL_ENDL;
+ return;
+ }
+
+ // Clean up previous references to this ip/port or circuit
+ U64 ip_port_old = get_if_there(msg->mCircuitCodeToIPPort, circuit_code_in, U64(0));
+ U32 circuit_code_old = get_if_there(msg->mIPPortToCircuitCode, ip_port_in, U32(0));
+
+ if (ip_port_old)
+ {
+ if ((ip_port_old == ip_port_in) && (circuit_code_old == circuit_code_in))
+ {
+ // Current information is the same as incoming info, ignore
+ LL_INFOS("Messaging") << "Got duplicate UseCircuitCode for circuit " << circuit_code_in << " to " << msg->getSender() << LL_ENDL;
+ return;
+ }
+
+ // Hmm, got a different IP and port for the same circuit code.
+ U32 circut_code_old_ip_port = get_if_there(msg->mIPPortToCircuitCode, ip_port_old, U32(0));
+ msg->mCircuitCodeToIPPort.erase(circut_code_old_ip_port);
+ msg->mIPPortToCircuitCode.erase(ip_port_old);
+ U32 old_port = (U32)(ip_port_old & (U64)0xFFFFFFFF);
+ U32 old_ip = (U32)(ip_port_old >> 32);
+ LL_INFOS("Messaging") << "Removing derelict lookup entry for circuit " << circuit_code_old << " to " << LLHost(old_ip, old_port) << LL_ENDL;
+ }
+
+ if (circuit_code_old)
+ {
+ LLHost cur_host(ip, port);
+
+ LL_WARNS("Messaging") << "Disabling existing circuit for " << cur_host << LL_ENDL;
+ msg->disableCircuit(cur_host);
+ if (circuit_code_old == circuit_code_in)
+ {
+ LL_WARNS("Messaging") << "Asymmetrical circuit to ip/port lookup!" << LL_ENDL;
+ LL_WARNS("Messaging") << "Multiple circuit codes for " << cur_host << " probably!" << LL_ENDL;
+ LL_WARNS("Messaging") << "Permanently disabling circuit" << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Circuit code changed for " << msg->getSender()
+ << " from " << circuit_code_old << " to "
+ << circuit_code_in << LL_ENDL;
+ }
+ }
+
+ // Since this comes from the viewer, it's untrusted, but it
+ // passed the circuit code and session id check, so we will go
+ // ahead and persist the ID associated.
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ bool had_circuit_already = cdp != nullptr;
+
+ msg->enableCircuit(msg->getSender(), false);
+ cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if(cdp)
+ {
+ cdp->setRemoteID(id);
+ cdp->setRemoteSessionID(session_id);
+ }
+
+ if (!had_circuit_already)
+ {
+ //
+ // HACK HACK HACK HACK HACK!
+ //
+ // This would NORMALLY happen inside logValidMsg, but at the point that this happens
+ // inside logValidMsg, there's no circuit for this message yet. So the awful thing that
+ // we do here is do it inside this message handler immediately AFTER the message is
+ // handled.
+ //
+ // We COULD not do this, but then what happens is that some of the circuit bookkeeping
+ // gets broken, especially the packets in count. That causes some later packets to flush
+ // the RecentlyReceivedReliable list, resulting in an error in which UseCircuitCode
+ // doesn't get properly duplicate suppressed. Not a BIG deal, but it's somewhat confusing
+ // (and bad from a state point of view). DJS 9/23/04
+ //
+ cdp->checkPacketInID(gMessageSystem->mCurrentRecvPacketID, false ); // Since this is the first message on the circuit, by definition it's not resent.
+ }
+
+ msg->mIPPortToCircuitCode[ip_port_in] = circuit_code_in;
+ msg->mCircuitCodeToIPPort[circuit_code_in] = ip_port_in;
+
+ LL_INFOS("Messaging") << "Circuit code " << circuit_code_in << " from "
+ << msg->getSender() << " for agent " << id << " in session "
+ << session_id << LL_ENDL;
+
+ const LLUseCircuitCodeResponder* responder =
+ (const LLUseCircuitCodeResponder*) user;
+ if(responder)
+ {
+ responder->complete(msg->getSender(), id);
+ }
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Got zero circuit code in use_circuit_code" << LL_ENDL;
+ }
+}
+
+// static
+void LLMessageSystem::processError(LLMessageSystem* msg, void**)
+{
+ S32 error_code = 0;
+ msg->getS32("Data", "Code", error_code);
+ std::string error_token;
+ msg->getString("Data", "Token", error_token);
+
+ LLUUID error_id;
+ msg->getUUID("Data", "ID", error_id);
+ std::string error_system;
+ msg->getString("Data", "System", error_system);
+
+ std::string error_message;
+ msg->getString("Data", "Message", error_message);
+
+ LL_WARNS("Messaging") << "Message error from " << msg->getSender() << " - "
+ << error_code << " " << error_token << " " << error_id << " \""
+ << error_system << "\" \"" << error_message << "\"" << LL_ENDL;
+}
+
+
+static LLHTTPNode& messageRootNode()
+{
+ static LLHTTPNode root_node;
+ static bool initialized = false;
+ if (!initialized) {
+ initialized = true;
+ LLHTTPRegistrar::buildAllServices(root_node);
+ }
+
+ return root_node;
+}
+
+//static
+void LLMessageSystem::dispatch(
+ const std::string& msg_name,
+ const LLSD& message)
+{
+ LLPointer<LLSimpleResponse> responsep = LLSimpleResponse::create();
+ dispatch(msg_name, message, responsep);
+}
+
+//static
+void LLMessageSystem::dispatch(
+ const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
+{
+ if ((gMessageSystem->mMessageTemplates.find
+ (LLMessageStringTable::getInstance()->getString(msg_name.c_str())) ==
+ gMessageSystem->mMessageTemplates.end()) &&
+ !LLMessageConfig::isValidMessage(msg_name))
+ {
+ LL_WARNS("Messaging") << "Ignoring unknown message " << msg_name << LL_ENDL;
+ responsep->notFound("Invalid message name");
+ return;
+ }
+
+ std::string path = "/message/" + msg_name;
+ LLSD context;
+ const LLHTTPNode* handler = messageRootNode().traverse(path, context);
+ if (!handler)
+ {
+ LL_WARNS("Messaging") << "LLMessageService::dispatch > no handler for "
+ << path << LL_ENDL;
+ return;
+ }
+ // enable this for output of message names
+ LL_DEBUGS("Messaging") << "< \"" << msg_name << "\"" << LL_ENDL;
+ LL_DEBUGS("Messaging") << "context: " << context << LL_ENDL;
+ LL_DEBUGS("Messaging") << "message: " << message << LL_ENDL;
+
+ handler->post(responsep, context, message);
+}
+
+//static
+void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
+{
+ LLTemplateMessageDispatcher dispatcher(*(gMessageSystem->mTemplateMessageReader));
+ dispatcher.dispatch(msg_name, message, responsep);
+}
+
+static void check_for_unrecognized_messages(
+ const char* type,
+ const LLSD& map,
+ LLMessageSystem::message_template_name_map_t& templates)
+{
+ for (LLSD::map_const_iterator iter = map.beginMap(),
+ end = map.endMap();
+ iter != end; ++iter)
+ {
+ const char* name = LLMessageStringTable::getInstance()->getString(iter->first.c_str());
+
+ if (templates.find(name) == templates.end())
+ {
+ LL_INFOS("AppInit") << " " << type
+ << " ban list contains unrecognized message "
+ << name << LL_ENDL;
+ }
+ }
+}
+
+void LLMessageSystem::setMessageBans(
+ const LLSD& trusted, const LLSD& untrusted)
+{
+ LL_DEBUGS("AppInit") << "LLMessageSystem::setMessageBans:" << LL_ENDL;
+ bool any_set = false;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; ++iter)
+ {
+ LLMessageTemplate* mt = iter->second;
+
+ std::string name(mt->mName);
+ bool ban_from_trusted
+ = trusted.has(name) && trusted.get(name).asBoolean();
+ bool ban_from_untrusted
+ = untrusted.has(name) && untrusted.get(name).asBoolean();
+
+ mt->mBanFromTrusted = ban_from_trusted;
+ mt->mBanFromUntrusted = ban_from_untrusted;
+
+ if (ban_from_trusted || ban_from_untrusted)
+ {
+ LL_INFOS("AppInit") << " " << name << " banned from "
+ << (ban_from_trusted ? "TRUSTED " : " ")
+ << (ban_from_untrusted ? "UNTRUSTED " : " ")
+ << LL_ENDL;
+ any_set = true;
+ }
+ }
+
+ if (!any_set)
+ {
+ LL_DEBUGS("AppInit") << " no messages banned" << LL_ENDL;
+ }
+
+ check_for_unrecognized_messages("trusted", trusted, mMessageTemplates);
+ check_for_unrecognized_messages("untrusted", untrusted, mMessageTemplates);
+}
+
+S32 LLMessageSystem::sendError(
+ const LLHost& host,
+ const LLUUID& agent_id,
+ S32 code,
+ const std::string& token,
+ const LLUUID& id,
+ const std::string& system,
+ const std::string& message,
+ const LLSD& data)
+{
+ newMessage("Error");
+ nextBlockFast(_PREHASH_AgentData);
+ addUUIDFast(_PREHASH_AgentID, agent_id);
+ nextBlockFast(_PREHASH_Data);
+ addS32("Code", code);
+ addString("Token", token);
+ addUUID("ID", id);
+ addString("System", system);
+ std::string temp;
+ temp = message;
+ if(temp.size() > (size_t)MTUBYTES) temp.resize((size_t)MTUBYTES);
+ addString("Message", message);
+ LLPointer<LLSDBinaryFormatter> formatter = new LLSDBinaryFormatter;
+ std::ostringstream ostr;
+ formatter->format(data, ostr);
+ temp = ostr.str();
+ bool pack_data = true;
+ static const std::string ERROR_MESSAGE_NAME("Error");
+ if (LLMessageConfig::getMessageFlavor(ERROR_MESSAGE_NAME) ==
+ LLMessageConfig::TEMPLATE_FLAVOR)
+ {
+ S32 msg_size = temp.size() + mMessageBuilder->getMessageSize();
+ if(msg_size >= ETHERNET_MTU_BYTES)
+ {
+ pack_data = false;
+ }
+ }
+ if(pack_data)
+ {
+ addBinaryData("Data", (void*)temp.c_str(), temp.size());
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Data and message were too large -- data removed."
+ << LL_ENDL;
+ addBinaryData("Data", NULL, 0);
+ }
+ return sendReliable(host);
+}
+
+void process_packet_ack(LLMessageSystem *msgsystem, void** /*user_data*/)
+{
+ TPACKETID packet_id;
+
+ LLHost host = msgsystem->getSender();
+ LLCircuitData *cdp = msgsystem->mCircuitInfo.findCircuit(host);
+ if (cdp)
+ {
+
+ S32 ack_count = msgsystem->getNumberOfBlocksFast(_PREHASH_Packets);
+
+ for (S32 i = 0; i < ack_count; i++)
+ {
+ msgsystem->getU32Fast(_PREHASH_Packets, _PREHASH_ID, packet_id, i);
+// LL_DEBUGS("Messaging") << "ack recvd' from " << host << " for packet " << (TPACKETID)packet_id << LL_ENDL;
+ cdp->ackReliablePacket(packet_id);
+ }
+ if (!cdp->getUnackedPacketCount())
+ {
+ // Remove this circuit from the list of circuits with unacked packets
+ gMessageSystem->mCircuitInfo.mUnackedCircuitMap.erase(host);
+ }
+ }
+}
+
+
+/*
+void process_log_messages(LLMessageSystem* msg, void**)
+{
+ U8 log_message;
+
+ msg->getU8Fast(_PREHASH_Options, _PREHASH_Enable, log_message);
+
+ if (log_message)
+ {
+ LL_INFOS("Messaging") << "Starting logging via message" << LL_ENDL;
+ msg->startLogging();
+ }
+ else
+ {
+ LL_INFOS("Messaging") << "Stopping logging via message" << LL_ENDL;
+ msg->stopLogging();
+ }
+}*/
+
+// Make circuit trusted if the MD5 Digest matches, otherwise
+// notify remote end that they are not trusted.
+void process_create_trusted_circuit(LLMessageSystem *msg, void **)
+{
+ // don't try to create trust on machines with no shared secret
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+
+ LLUUID remote_id;
+ msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
+
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if (!cdp)
+ {
+ LL_WARNS("Messaging") << "Attempt to create trusted circuit without circuit data: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+
+ LLUUID local_id;
+ local_id = cdp->getLocalEndPointID();
+ if (remote_id == local_id)
+ {
+ // Don't respond to requests that use the same end point ID
+ return;
+ }
+
+ U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
+ U32 last_interface = msg->getReceivingInterface().getAddress();
+ if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
+ {
+ if( msg->getBlockUntrustedInterface() )
+ {
+ LL_WARNS("Messaging") << "Ignoring CreateTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Processing CreateTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ }
+ }
+
+ char their_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ S32 size = msg->getSizeFast(_PREHASH_DataBlock, _PREHASH_Digest);
+ if(size != MD5HEX_STR_BYTES)
+ {
+ // ignore requests which pack the wrong amount of data.
+ return;
+ }
+ msg->getBinaryDataFast(_PREHASH_DataBlock, _PREHASH_Digest, their_digest, MD5HEX_STR_BYTES);
+ their_digest[MD5HEX_STR_SIZE - 1] = '\0';
+ if(msg->isMatchingDigestForWindowAndUUIDs(their_digest, TRUST_TIME_WINDOW, local_id, remote_id))
+ {
+ cdp->setTrusted(true);
+ LL_INFOS("Messaging") << "Trusted digest from " << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else if (cdp->getTrusted())
+ {
+ // The digest is bad, but this circuit is already trusted.
+ // This means that this could just be the result of a stale deny sent from a while back, and
+ // the message system is being slow. Don't bother sending the deny, as it may continually
+ // ping-pong back and forth on a very hosed circuit.
+ LL_WARNS("Messaging") << "Ignoring bad digest from known trusted circuit: " << their_digest
+ << " host: " << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Bad digest from known circuit: " << their_digest
+ << " host: " << msg->getSender() << LL_ENDL;
+ msg->sendDenyTrustedCircuit(msg->getSender());
+ return;
+ }
+}
+
+void process_deny_trusted_circuit(LLMessageSystem *msg, void **)
+{
+ // don't try to create trust on machines with no shared secret
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+
+ LLUUID remote_id;
+ msg->getUUIDFast(_PREHASH_DataBlock, _PREHASH_EndPointID, remote_id);
+
+ LLCircuitData *cdp = msg->mCircuitInfo.findCircuit(msg->getSender());
+ if (!cdp)
+ {
+ return;
+ }
+
+ LLUUID local_id;
+ local_id = cdp->getLocalEndPointID();
+ if (remote_id == local_id)
+ {
+ // Don't respond to requests that use the same end point ID
+ return;
+ }
+
+ U32 untrusted_interface = msg->getUntrustedInterface().getAddress();
+ U32 last_interface = msg->getReceivingInterface().getAddress();
+ if ( ( untrusted_interface != INVALID_HOST_IP_ADDRESS ) && ( untrusted_interface == last_interface ) )
+ {
+ if( msg->getBlockUntrustedInterface() )
+ {
+ LL_WARNS("Messaging") << "Ignoring DenyTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ return;
+ }
+ else
+ {
+ LL_WARNS("Messaging") << "Processing DenyTrustedCircuit on public interface from host: "
+ << msg->getSender() << LL_ENDL;
+ }
+ }
+
+
+ // Assume that we require trust to proceed, so resend.
+ // This catches the case where a circuit that was trusted
+ // times out, and allows us to re-establish it, but does
+ // mean that if our shared_secret or clock is wrong, we'll
+ // spin.
+ // *TODO: probably should keep a count of number of resends
+ // per circuit, and stop resending after a while.
+ LL_INFOS("Messaging") << "Got DenyTrustedCircuit. Sending CreateTrustedCircuit to "
+ << msg->getSender() << LL_ENDL;
+ msg->sendCreateTrustedCircuit(msg->getSender(), local_id, remote_id);
+}
+
+
+void dump_prehash_files()
+{
+ U32 i;
+ std::string filename("../../indra/llmessage/message_prehash.h");
+ LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ fprintf(
+ fp,
+ "/**\n"
+ " * @file message_prehash.h\n"
+ " * @brief header file of externs of prehashed variables plus defines.\n"
+ " *\n"
+ " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
+ " * $/LicenseInfo$"
+ " */\n\n"
+ "#ifndef LL_MESSAGE_PREHASH_H\n#define LL_MESSAGE_PREHASH_H\n\n");
+ fprintf(
+ fp,
+ "/**\n"
+ " * Generated from message template version number %.3f\n"
+ " */\n",
+ gMessageSystem->mMessageFileVersionNumber);
+ fprintf(fp, "\n\nextern F32 const gPrehashVersionNumber;\n\n");
+ for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
+ {
+ fprintf(fp, "extern char const* const _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]);
+ }
+ }
+ fprintf(fp, "\n\n#endif\n");
+ fclose(fp);
+ }
+ filename = std::string("../../indra/llmessage/message_prehash.cpp");
+ fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ fprintf(
+ fp,
+ "/**\n"
+ " * @file message_prehash.cpp\n"
+ " * @brief file of prehashed variables\n"
+ " *\n"
+ " * $LicenseInfo:firstyear=2003&license=viewerlgpl$"
+ " * $/LicenseInfo$"
+ " */\n\n"
+ "/**\n"
+ " * Generated from message template version number %.3f\n"
+ " */\n",
+ gMessageSystem->mMessageFileVersionNumber);
+ fprintf(fp, "#include \"linden_common.h\"\n");
+ fprintf(fp, "#include \"message.h\"\n\n");
+ fprintf(fp, "\n\nF32 const gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber);
+ for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.')
+ {
+ fprintf(fp, "char const* const _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]);
+ }
+ }
+ fclose(fp);
+ }
+}
+
+bool start_messaging_system(
+ const std::string& template_name,
+ U32 port,
+ S32 version_major,
+ S32 version_minor,
+ S32 version_patch,
+ bool b_dump_prehash_file,
+ const std::string& secret,
+ const LLUseCircuitCodeResponder* responder,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval,
+ const F32 circuit_timeout)
+{
+ gMessageSystem = new LLMessageSystem(
+ template_name,
+ port,
+ version_major,
+ version_minor,
+ version_patch,
+ failure_is_fatal,
+ circuit_heartbeat_interval,
+ circuit_timeout);
+ g_shared_secret.assign(secret);
+
+ if (!gMessageSystem)
+ {
+ LL_ERRS("AppInit") << "Messaging system initialization failed." << LL_ENDL;
+ return false;
+ }
+
+ // bail if system encountered an error.
+ if(!gMessageSystem->isOK())
+ {
+ return false;
+ }
+
+ if (b_dump_prehash_file)
+ {
+ dump_prehash_files();
+ exit(0);
+ }
+ else
+ {
+ if (gMessageSystem->mMessageFileVersionNumber != gPrehashVersionNumber)
+ {
+ LL_INFOS("AppInit") << "Message template version does not match prehash version number" << LL_ENDL;
+ LL_INFOS("AppInit") << "Run simulator with -prehash command line option to rebuild prehash data" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("AppInit") << "Message template version matches prehash version number" << LL_ENDL;
+ }
+ }
+
+ gMessageSystem->setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_OpenCircuit, open_circuit, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CloseCircuit, close_circuit, NULL);
+
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_AssignCircuitCode, LLMessageSystem::processAssignCircuitCode);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_AddCircuitCode, LLMessageSystem::processAddCircuitCode);
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_AckAddCircuitCode, ack_add_circuit_code, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_UseCircuitCode, LLMessageSystem::processUseCircuitCode, (void**)responder);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_PacketAck, process_packet_ack, NULL);
+ //gMessageSystem->setHandlerFuncFast(_PREHASH_LogMessages, process_log_messages, NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_CreateTrustedCircuit,
+ process_create_trusted_circuit,
+ NULL);
+ gMessageSystem->setHandlerFuncFast(_PREHASH_DenyTrustedCircuit,
+ process_deny_trusted_circuit,
+ NULL);
+ gMessageSystem->setHandlerFunc("Error", LLMessageSystem::processError);
+
+ // We can hand this to the null_message_callback since it is a
+ // trusted message, so it will automatically be denied if it isn't
+ // trusted and ignored if it is -- exactly what we want.
+ gMessageSystem->setHandlerFunc(
+ "RequestTrustedCircuit",
+ null_message_callback,
+ NULL);
+
+ // Initialize the transfer manager
+ gTransferManager.init();
+
+ return true;
+}
+
+void LLMessageSystem::startLogging()
+{
+ mVerboseLog = true;
+ std::ostringstream str;
+ str << "START MESSAGE LOG" << std::endl;
+ str << "Legend:" << std::endl;
+ str << "\t<-\tincoming message" <<std::endl;
+ str << "\t->\toutgoing message" << std::endl;
+ str << " <> host size zero id name";
+ LL_INFOS("Messaging") << str.str() << LL_ENDL;
+}
+
+void LLMessageSystem::stopLogging()
+{
+ if(mVerboseLog)
+ {
+ mVerboseLog = false;
+ LL_INFOS("Messaging") << "END MESSAGE LOG" << LL_ENDL;
+ }
+}
+
+void LLMessageSystem::summarizeLogs(std::ostream& str)
+{
+ std::string buffer;
+ std::string tmp_str;
+ F32 run_time = mMessageSystemTimer.getElapsedTimeF32();
+ str << "START MESSAGE LOG SUMMARY" << std::endl;
+ buffer = llformat( "Run time: %12.3f seconds", run_time);
+
+ // Incoming
+ str << buffer << std::endl << "Incoming:" << std::endl;
+ tmp_str = U64_to_str(mTotalBytesIn);
+ buffer = llformat( "Total bytes received: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesIn * 0.008f) / run_time);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mPacketsIn);
+ buffer = llformat( "Total packets received: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32) mPacketsIn / run_time));
+ str << buffer << std::endl;
+ buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesIn / (F32)mPacketsIn);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mReliablePacketsIn);
+ buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsIn)/((F32) mPacketsIn + 1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mCompressedPacketsIn);
+ buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsIn)/((F32) mPacketsIn + 1));
+ str << buffer << std::endl;
+ S64 savings = mUncompressedBytesIn - mCompressedBytesIn;
+ tmp_str = U64_to_str(savings);
+ buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mCompressedPacketsIn +1));
+ buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesIn)/((F32) mCompressedBytesIn+1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mPacketsIn+1));
+ buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesIn + (F32) savings)/((F32) mTotalBytesIn + 1.f));
+
+ // Outgoing
+ str << buffer << std::endl << std::endl << "Outgoing:" << std::endl;
+ tmp_str = U64_to_str(mTotalBytesOut);
+ buffer = llformat( "Total bytes sent: %20s (%5.2f kbits per second)", tmp_str.c_str(), ((F32)mTotalBytesOut * 0.008f) / run_time );
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mPacketsOut);
+ buffer = llformat( "Total packets sent: %20s (%5.2f packets per second)", tmp_str.c_str(), ((F32)mPacketsOut / run_time));
+ str << buffer << std::endl;
+ buffer = llformat( "Average packet size: %20.0f bytes", (F32)mTotalBytesOut / (F32)mPacketsOut);
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mReliablePacketsOut);
+ buffer = llformat( "Total reliable packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mReliablePacketsOut)/((F32) mPacketsOut + 1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(mCompressedPacketsOut);
+ buffer = llformat( "Total compressed packets: %20s (%5.2f%%)", tmp_str.c_str(), 100.f * ((F32) mCompressedPacketsOut)/((F32) mPacketsOut + 1));
+ str << buffer << std::endl;
+ savings = mUncompressedBytesOut - mCompressedBytesOut;
+ tmp_str = U64_to_str(savings);
+ buffer = llformat( "Total compression savings: %20s bytes", tmp_str.c_str());
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mCompressedPacketsOut +1));
+ buffer = llformat( "Avg comp packet savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mUncompressedBytesOut)/((F32) mCompressedBytesOut+1));
+ str << buffer << std::endl;
+ tmp_str = U64_to_str(savings/(mPacketsOut+1));
+ buffer = llformat( "Avg overall comp savings: %20s (%5.2f : 1)", tmp_str.c_str(), ((F32) mTotalBytesOut + (F32) savings)/((F32) mTotalBytesOut + 1.f));
+ str << buffer << std::endl << std::endl;
+ buffer = llformat( "SendPacket failures: %20d", mSendPacketFailureCount);
+ str << buffer << std::endl;
+ buffer = llformat( "Dropped packets: %20d", mDroppedPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Resent packets: %20d", mResentPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Failed reliable resends: %20d", mFailedResendPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "Off-circuit rejected packets: %17d", mOffCircuitPackets);
+ str << buffer << std::endl;
+ buffer = llformat( "On-circuit invalid packets: %17d", mInvalidOnCircuitPackets);
+ str << buffer << std::endl << std::endl;
+
+ str << "Decoding: " << std::endl;
+ buffer = llformat( "%35s%10s%10s%10s%10s", "Message", "Count", "Time", "Max", "Avg");
+ str << buffer << std:: endl;
+ F32 avg;
+ for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ const LLMessageTemplate* mt = iter->second;
+ if(mt->mTotalDecoded > 0)
+ {
+ avg = mt->mTotalDecodeTime / (F32)mt->mTotalDecoded;
+ buffer = llformat( "%35s%10u%10f%10f%10f", mt->mName, mt->mTotalDecoded, mt->mTotalDecodeTime, mt->mMaxDecodeTimePerMsg, avg);
+ str << buffer << std::endl;
+ }
+ }
+ str << "END MESSAGE LOG SUMMARY" << std::endl;
+}
+
+void end_messaging_system(bool print_summary)
+{
+ gTransferManager.cleanup();
+ LLTransferTargetVFile::updateQueue(true); // shutdown LLTransferTargetVFile
+ if (gMessageSystem)
+ {
+ gMessageSystem->stopLogging();
+
+ if (print_summary)
+ {
+ std::ostringstream str;
+ gMessageSystem->summarizeLogs(str);
+ LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL;
+ }
+
+ delete static_cast<LLMessageSystem*>(gMessageSystem);
+ gMessageSystem = NULL;
+ }
+}
+
+void LLMessageSystem::resetReceiveCounts()
+{
+ mNumMessageCounts = 0;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ LLMessageTemplate* mt = iter->second;
+ mt->mDecodeTimeThisFrame = 0.f;
+ }
+}
+
+
+void LLMessageSystem::dumpReceiveCounts()
+{
+ LLMessageTemplate *mt;
+
+ for (message_template_name_map_t::iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ LLMessageTemplate* mt = iter->second;
+ mt->mReceiveCount = 0;
+ mt->mReceiveBytes = 0;
+ mt->mReceiveInvalid = 0;
+ }
+
+ S32 i;
+ for (i = 0; i < mNumMessageCounts; i++)
+ {
+ mt = get_ptr_in_map(mMessageNumbers,mMessageCountList[i].mMessageNum);
+ if (mt)
+ {
+ mt->mReceiveCount++;
+ mt->mReceiveBytes += mMessageCountList[i].mMessageBytes;
+ if (mMessageCountList[i].mInvalid)
+ {
+ mt->mReceiveInvalid++;
+ }
+ }
+ }
+
+ if(mNumMessageCounts > 0)
+ {
+ LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL;
+ for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(),
+ end = mMessageTemplates.end();
+ iter != end; iter++)
+ {
+ const LLMessageTemplate* mt = iter->second;
+ if (mt->mReceiveCount > 0)
+ {
+ LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes
+ << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL;
+ }
+ }
+ }
+}
+
+
+
+bool LLMessageSystem::isClear() const
+{
+ return mMessageBuilder->isClear();
+}
+
+
+S32 LLMessageSystem::flush(const LLHost &host)
+{
+ if (mMessageBuilder->getMessageSize())
+ {
+ S32 sentbytes = sendMessage(host);
+ clearMessage();
+ return sentbytes;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+U32 LLMessageSystem::getListenPort( void ) const
+{
+ return mPort;
+}
+
+// TODO: babbage: remove this horror!
+S32 LLMessageSystem::zeroCodeAdjustCurrentSendTotal()
+{
+ if(mMessageBuilder == mLLSDMessageBuilder)
+ {
+ // babbage: don't compress LLSD messages, so delta is 0
+ return 0;
+ }
+
+ if (! mMessageBuilder->isBuilt())
+ {
+ mSendSize = mMessageBuilder->buildMessage(
+ mSendBuffer,
+ MAX_BUFFER_SIZE,
+ 0);
+ }
+ // TODO: babbage: remove this horror
+ mMessageBuilder->setBuilt(false);
+
+ S32 count = mSendSize;
+
+ S32 net_gain = 0;
+ U8 num_zeroes = 0;
+
+ U8 *inptr = (U8 *)mSendBuffer;
+
+// skip the packet id field
+
+ for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
+ {
+ count--;
+ inptr++;
+ }
+
+// don't actually build, just test
+
+// sequential zero bytes are encoded as 0 [U8 count]
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+ while (count--)
+ {
+ if (!(*inptr)) // in a zero count
+ {
+ if (num_zeroes)
+ {
+ if (++num_zeroes > 254)
+ {
+ num_zeroes = 0;
+ }
+ net_gain--; // subseqent zeroes save one
+ }
+ else
+ {
+ net_gain++; // starting a zero count adds one
+ num_zeroes = 1;
+ }
+ inptr++;
+ }
+ else
+ {
+ if (num_zeroes)
+ {
+ num_zeroes = 0;
+ }
+ inptr++;
+ }
+ }
+ if (net_gain < 0)
+ {
+ return net_gain;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
+S32 LLMessageSystem::zeroCodeExpand(U8** data, S32* data_size)
+{
+ if ((*data_size ) < LL_MINIMUM_VALID_PACKET_SIZE)
+ {
+ LL_WARNS("Messaging") << "zeroCodeExpand() called with data_size of " << *data_size
+ << LL_ENDL;
+ }
+
+ mTotalBytesIn += *data_size;
+
+ // if we're not zero-coded, simply return.
+ if (!(*data[0] & LL_ZERO_CODE_FLAG))
+ {
+ return 0;
+ }
+
+ S32 in_size = *data_size;
+ mCompressedPacketsIn++;
+ mCompressedBytesIn += *data_size;
+
+ *data[0] &= (~LL_ZERO_CODE_FLAG);
+
+ S32 count = (*data_size);
+
+ U8 *inptr = (U8 *)*data;
+ U8 *outptr = (U8 *)mEncodedRecvBuffer;
+
+// skip the packet id field
+
+ for (U32 ii = 0; ii < LL_PACKET_ID_SIZE; ++ii)
+ {
+ count--;
+ *outptr++ = *inptr++;
+ }
+
+// reconstruct encoded packet, keeping track of net size gain
+
+// sequential zero bytes are encoded as 0 [U8 count]
+// with 0 0 [count] representing wrap (>256 zeroes)
+
+ while (count--)
+ {
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-1]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 1" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ break;
+ }
+ if (!((*outptr++ = *inptr++)))
+ {
+ while (((count--)) && (!(*inptr)))
+ {
+ *outptr++ = *inptr++;
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-256]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 2" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ count = -1;
+ break;
+ }
+ memset(outptr,0,255);
+ outptr += 255;
+ }
+
+ if (count < 0)
+ {
+ break;
+ }
+
+ else
+ {
+ if (outptr > (&mEncodedRecvBuffer[MAX_BUFFER_SIZE-(*inptr)]))
+ {
+ LL_WARNS("Messaging") << "attempt to write past reasonable encoded buffer size 3" << LL_ENDL;
+ callExceptionFunc(MX_WROTE_PAST_BUFFER_SIZE);
+ outptr = mEncodedRecvBuffer;
+ }
+ memset(outptr,0,(*inptr) - 1);
+ outptr += ((*inptr) - 1);
+ inptr++;
+ }
+ }
+ }
+
+ *data = mEncodedRecvBuffer;
+ *data_size = (S32)(outptr - mEncodedRecvBuffer);
+ mUncompressedBytesIn += *data_size;
+
+ return(in_size);
+}
+
+
+void LLMessageSystem::addTemplate(LLMessageTemplate *templatep)
+{
+ if (mMessageTemplates.count(templatep->mName) > 0)
+ {
+ LL_ERRS("Messaging") << templatep->mName << " already used as a template name!"
+ << LL_ENDL;
+ }
+ mMessageTemplates[templatep->mName] = templatep;
+ mMessageNumbers[templatep->mMessageNumber] = templatep;
+}
+
+
+void LLMessageSystem::setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data)
+{
+ LLMessageTemplate* msgtemplate = get_ptr_in_map(mMessageTemplates, name);
+ if (msgtemplate)
+ {
+ msgtemplate->setHandlerFunc(handler_func, user_data);
+ }
+ else
+ {
+ LL_ERRS("Messaging") << name << " is not a known message name!" << LL_ENDL;
+ }
+}
+
+bool LLMessageSystem::callHandler(const char *name,
+ bool trustedSource, LLMessageSystem* msg)
+{
+ name = LLMessageStringTable::getInstance()->getString(name);
+ message_template_name_map_t::const_iterator iter;
+ iter = mMessageTemplates.find(name);
+ if(iter == mMessageTemplates.end())
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callHandler: unknown message "
+ << name << LL_ENDL;
+ return false;
+ }
+
+ const LLMessageTemplate* msg_template = iter->second;
+ if (msg_template->isBanned(trustedSource))
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callHandler: banned message "
+ << name
+ << " from "
+ << (trustedSource ? "trusted " : "untrusted ")
+ << "source" << LL_ENDL;
+ return false;
+ }
+
+ return msg_template->callHandlerFunc(msg);
+}
+
+
+void LLMessageSystem::setExceptionFunc(EMessageException e,
+ msg_exception_callback func,
+ void* data)
+{
+ callbacks_t::iterator it = mExceptionCallbacks.find(e);
+ if(it != mExceptionCallbacks.end())
+ {
+ mExceptionCallbacks.erase(it);
+ }
+ if(func)
+ {
+ mExceptionCallbacks.insert(callbacks_t::value_type(e, exception_t(func, data)));
+ }
+}
+
+bool LLMessageSystem::callExceptionFunc(EMessageException exception)
+{
+ callbacks_t::iterator it = mExceptionCallbacks.find(exception);
+ if(it == mExceptionCallbacks.end())
+ {
+ return false;
+ }
+
+ exception_t& ex = it->second;
+ msg_exception_callback ex_cb = ex.first;
+
+ if (!ex_cb)
+ {
+ LL_WARNS("Messaging") << "LLMessageSystem::callExceptionFunc: bad message exception callback." << LL_ENDL;
+ return false;
+ }
+
+ (ex_cb)(this, ex.second, exception);
+
+ return true;
+}
+
+void LLMessageSystem::setTimingFunc(msg_timing_callback func, void* data)
+{
+ mTimingCallback = func;
+ mTimingCallbackData = data;
+}
+
+bool LLMessageSystem::isCircuitCodeKnown(U32 code) const
+{
+ if(mCircuitCodes.find(code) == mCircuitCodes.end())
+ return false;
+ return true;
+}
+
+bool LLMessageSystem::isMessageFast(const char *msg)
+{
+ return msg == mMessageReader->getMessageName();
+}
+
+
+char* LLMessageSystem::getMessageName()
+{
+ return const_cast<char*>(mMessageReader->getMessageName());
+}
+
+const LLUUID& LLMessageSystem::getSenderID() const
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
+ if (cdp)
+ {
+ return (cdp->mRemoteID);
+ }
+
+ return LLUUID::null;
+}
+
+const LLUUID& LLMessageSystem::getSenderSessionID() const
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(mLastSender);
+ if (cdp)
+ {
+ return (cdp->mRemoteSessionID);
+ }
+ return LLUUID::null;
+}
+
+bool LLMessageSystem::generateDigestForNumberAndUUIDs(
+ char* digest,
+ const U32 number,
+ const LLUUID& id1,
+ const LLUUID& id2) const
+{
+ // *NOTE: This method is needlessly inefficient. Instead of
+ // calling LLUUID::asString, it should just call
+ // LLUUID::toString().
+
+ const char *colon = ":";
+ char tbuf[16]; /* Flawfinder: ignore */
+ LLMD5 d;
+ std::string id1string = id1.asString();
+ std::string id2string = id2.asString();
+ std::string shared_secret = get_shared_secret();
+ unsigned char * secret = (unsigned char*)shared_secret.c_str();
+ unsigned char * id1str = (unsigned char*)id1string.c_str();
+ unsigned char * id2str = (unsigned char*)id2string.c_str();
+
+ memset(digest, 0, MD5HEX_STR_SIZE);
+
+ if( secret != NULL)
+ {
+ d.update(secret, (U32)strlen((char *) secret)); /* Flawfinder: ignore */
+ }
+
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+
+ snprintf(tbuf, sizeof(tbuf),"%i", number); /* Flawfinder: ignore */
+ d.update((unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
+
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+ if( (char*) id1str != NULL)
+ {
+ d.update(id1str, (U32)strlen((char *) id1str)); /* Flawfinder: ignore */
+ }
+ d.update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
+
+ if( (char*) id2str != NULL)
+ {
+ d.update(id2str, (U32)strlen((char *) id2str)); /* Flawfinder: ignore */
+ }
+
+ d.finalize();
+ d.hex_digest(digest);
+ digest[MD5HEX_STR_SIZE - 1] = '\0';
+
+ return true;
+}
+
+bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
+{
+ if(0 == window) return false;
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ bool result = generateDigestForNumberAndUUIDs(digest, now, id1, id2);
+
+ return result;
+}
+
+bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to compare complex digests on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ // Check 1 window ago, now, and one window from now to catch edge
+ // conditions. Process them as current window, one window ago, and
+ // one window in the future to catch the edges.
+ const S32 WINDOW_BIN_COUNT = 3;
+ U32 window_bin[WINDOW_BIN_COUNT];
+ window_bin[0] = now;
+ window_bin[1] = now - 1;
+ window_bin[2] = now + 1;
+ for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
+ {
+ generateDigestForNumberAndUUIDs(our_digest, window_bin[i], id2, id1);
+ if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LLMessageSystem::generateDigestForNumber(char* digest, const U32 number) const
+{
+ memset(digest, 0, MD5HEX_STR_SIZE);
+
+ LLMD5 d;
+ std::string shared_secret = get_shared_secret();
+ d = LLMD5((const unsigned char *)shared_secret.c_str(), number);
+ d.hex_digest(digest);
+ digest[MD5HEX_STR_SIZE - 1] = '\0';
+
+ return true;
+}
+
+bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ U32 now = (U32)time(NULL);
+
+ now /= window;
+
+ bool result = generateDigestForNumber(digest, now);
+
+ return result;
+}
+
+bool LLMessageSystem::isMatchingDigestForWindow(const char* digest, S32 const window) const
+{
+ if(0 == window) return false;
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to compare simple digests on a machine without a shared secret!" << LL_ENDL;
+ }
+
+ char our_digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ U32 now = (S32)time(NULL);
+
+ now /= window;
+
+ // Check 1 window ago, now, and one window from now to catch edge
+ // conditions. Process them as current window, one window ago, and
+ // one window in the future to catch the edges.
+ const S32 WINDOW_BIN_COUNT = 3;
+ U32 window_bin[WINDOW_BIN_COUNT];
+ window_bin[0] = now;
+ window_bin[1] = now - 1;
+ window_bin[2] = now + 1;
+ for(S32 i = 0; i < WINDOW_BIN_COUNT; ++i)
+ {
+ generateDigestForNumber(our_digest, window_bin[i]);
+ if(0 == strncmp(digest, our_digest, MD5HEX_STR_BYTES))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLMessageSystem::sendCreateTrustedCircuit(const LLHost &host, const LLUUID & id1, const LLUUID & id2)
+{
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty()) return;
+ char digest[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
+ if (id1.isNull())
+ {
+ LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the local end point ID" << LL_ENDL;
+ return;
+ }
+ if (id2.isNull())
+ {
+ LL_WARNS("Messaging") << "Can't send CreateTrustedCircuit to " << host << " because we don't have the remote end point ID" << LL_ENDL;
+ return;
+ }
+ generateDigestForWindowAndUUIDs(digest, TRUST_TIME_WINDOW, id1, id2);
+ newMessageFast(_PREHASH_CreateTrustedCircuit);
+ nextBlockFast(_PREHASH_DataBlock);
+ addUUIDFast(_PREHASH_EndPointID, id1);
+ addBinaryDataFast(_PREHASH_Digest, digest, MD5HEX_STR_BYTES);
+ LL_INFOS("Messaging") << "xmitting digest: " << digest << " Host: " << host << LL_ENDL;
+ sendMessage(host);
+}
+
+void LLMessageSystem::sendDenyTrustedCircuit(const LLHost &host)
+{
+ mDenyTrustedCircuitSet.insert(host);
+}
+
+void LLMessageSystem::reallySendDenyTrustedCircuit(const LLHost &host)
+{
+ LLCircuitData *cdp = mCircuitInfo.findCircuit(host);
+ if (!cdp)
+ {
+ LL_WARNS("Messaging") << "Not sending DenyTrustedCircuit to host without a circuit." << LL_ENDL;
+ return;
+ }
+ LL_INFOS("Messaging") << "Sending DenyTrustedCircuit to " << host << LL_ENDL;
+ newMessageFast(_PREHASH_DenyTrustedCircuit);
+ nextBlockFast(_PREHASH_DataBlock);
+ addUUIDFast(_PREHASH_EndPointID, cdp->getLocalEndPointID());
+ sendMessage(host);
+}
+
+void null_message_callback(LLMessageSystem *msg, void **data)
+{
+ // Nothing should ever go here, but we use this to register messages
+ // that we are expecting to see (and spinning on) at startup.
+ return;
+}
+
+// Try to establish a bidirectional trust metric by pinging a host until it's
+// up, and then sending auth messages.
+void LLMessageSystem::establishBidirectionalTrust(const LLHost &host, S64 frame_count )
+{
+ LockMessageChecker lmc(this);
+
+ std::string shared_secret = get_shared_secret();
+ if(shared_secret.empty())
+ {
+ LL_ERRS("Messaging") << "Trying to establish bidirectional trust on a machine without a shared secret!" << LL_ENDL;
+ }
+ LLTimer timeout;
+
+ timeout.setTimerExpirySec(20.0);
+ setHandlerFuncFast(_PREHASH_StartPingCheck, null_message_callback, NULL);
+ setHandlerFuncFast(_PREHASH_CompletePingCheck, null_message_callback,
+ NULL);
+
+ while (! timeout.hasExpired())
+ {
+ newMessageFast(_PREHASH_StartPingCheck);
+ nextBlockFast(_PREHASH_PingID);
+ addU8Fast(_PREHASH_PingID, 0);
+ addU32Fast(_PREHASH_OldestUnacked, 0);
+ sendMessage(host);
+ if (lmc.checkMessages( frame_count ))
+ {
+ if (isMessageFast(_PREHASH_CompletePingCheck) &&
+ (getSender() == host))
+ {
+ break;
+ }
+ }
+ lmc.processAcks();
+ ms_sleep(1);
+ }
+
+ // Send a request, a deny, and give the host 2 seconds to complete
+ // the trust handshake.
+ newMessage("RequestTrustedCircuit");
+ sendMessage(host);
+ reallySendDenyTrustedCircuit(host);
+ setHandlerFuncFast(_PREHASH_StartPingCheck, process_start_ping_check, NULL);
+ setHandlerFuncFast(_PREHASH_CompletePingCheck, process_complete_ping_check, NULL);
+
+ timeout.setTimerExpirySec(2.0);
+ LLCircuitData* cdp = NULL;
+ while(!timeout.hasExpired())
+ {
+ cdp = mCircuitInfo.findCircuit(host);
+ if(!cdp) break; // no circuit anymore, no point continuing.
+ if(cdp->getTrusted()) break; // circuit is trusted.
+ lmc.checkMessages(frame_count);
+ lmc.processAcks();
+ ms_sleep(1);
+ }
+}
+
+
+void LLMessageSystem::dumpPacketToLog()
+{
+ LL_WARNS("Messaging") << "Packet Dump from:" << mPacketRing.getLastSender() << LL_ENDL;
+ LL_WARNS("Messaging") << "Packet Size:" << mTrueReceiveSize << LL_ENDL;
+ char line_buffer[256]; /* Flawfinder: ignore */
+ S32 i;
+ S32 cur_line_pos = 0;
+ S32 cur_line = 0;
+
+ for (i = 0; i < mTrueReceiveSize; i++)
+ {
+ S32 offset = cur_line_pos * 3;
+ snprintf(line_buffer + offset, sizeof(line_buffer) - offset,
+ "%02x ", mTrueReceiveBuffer[i]); /* Flawfinder: ignore */
+ cur_line_pos++;
+ if (cur_line_pos >= 16)
+ {
+ cur_line_pos = 0;
+ LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
+ cur_line++;
+ }
+ }
+ if (cur_line_pos)
+ {
+ LL_WARNS("Messaging") << "PD:" << cur_line << "PD:" << line_buffer << LL_ENDL;
+ }
+}
+
+
+//static
+U64Microseconds LLMessageSystem::getMessageTimeUsecs(const bool update)
+{
+ if (gMessageSystem)
+ {
+ if (update)
+ {
+ gMessageSystem->mCurrentMessageTime = totalTime();
+ }
+ return gMessageSystem->mCurrentMessageTime;
+ }
+ else
+ {
+ return totalTime();
+ }
+}
+
+//static
+F64Seconds LLMessageSystem::getMessageTimeSeconds(const bool update)
+{
+ if (gMessageSystem)
+ {
+ if (update)
+ {
+ gMessageSystem->mCurrentMessageTime = totalTime();
+ }
+ return gMessageSystem->mCurrentMessageTime;
+ }
+ else
+ {
+ return F64Seconds(totalTime());
+ }
+}
+
+std::string get_shared_secret()
+{
+ static const std::string SHARED_SECRET_KEY("shared_secret");
+ if(g_shared_secret.empty())
+ {
+ LLApp* app = LLApp::instance();
+ if(app) return app->getOption(SHARED_SECRET_KEY);
+ }
+ return g_shared_secret;
+}
+
+typedef std::map<const char*, LLMessageBuilder*> BuilderMap;
+
+void LLMessageSystem::newMessageFast(const char *name)
+{
+ //LL_DEBUGS("Messaging") << "creating new message: " << name << LL_ENDL;
+ LLMessageConfig::Flavor message_flavor =
+ LLMessageConfig::getMessageFlavor(name);
+ LLMessageConfig::Flavor server_flavor =
+ LLMessageConfig::getServerDefaultFlavor();
+
+ if(message_flavor == LLMessageConfig::TEMPLATE_FLAVOR)
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ else if (message_flavor == LLMessageConfig::LLSD_FLAVOR)
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ // NO_FLAVOR
+ else
+ {
+ if (server_flavor == LLMessageConfig::LLSD_FLAVOR)
+ {
+ mMessageBuilder = mLLSDMessageBuilder;
+ }
+ // TEMPLATE_FLAVOR or NO_FLAVOR
+ else
+ {
+ mMessageBuilder = mTemplateMessageBuilder;
+ }
+ }
+ mSendReliable = false;
+ mMessageBuilder->newMessage(name);
+}
+
+void LLMessageSystem::newMessage(const char *name)
+{
+ newMessageFast(LLMessageStringTable::getInstance()->getString(name));
+}
+
+void LLMessageSystem::addBinaryDataFast(const char *varname, const void *data, S32 size)
+{
+ mMessageBuilder->addBinaryData(varname, data, size);
+}
+
+void LLMessageSystem::addBinaryData(const char *varname, const void *data, S32 size)
+{
+ mMessageBuilder->addBinaryData(LLMessageStringTable::getInstance()->getString(varname),data, size);
+}
+
+void LLMessageSystem::addS8Fast(const char *varname, S8 v)
+{
+ mMessageBuilder->addS8(varname, v);
+}
+
+void LLMessageSystem::addS8(const char *varname, S8 v)
+{
+ mMessageBuilder->addS8(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU8Fast(const char *varname, U8 v)
+{
+ mMessageBuilder->addU8(varname, v);
+}
+
+void LLMessageSystem::addU8(const char *varname, U8 v)
+{
+ mMessageBuilder->addU8(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addS16Fast(const char *varname, S16 v)
+{
+ mMessageBuilder->addS16(varname, v);
+}
+
+void LLMessageSystem::addS16(const char *varname, S16 v)
+{
+ mMessageBuilder->addS16(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU16Fast(const char *varname, U16 v)
+{
+ mMessageBuilder->addU16(varname, v);
+}
+
+void LLMessageSystem::addU16(const char *varname, U16 v)
+{
+ mMessageBuilder->addU16(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addF32Fast(const char *varname, F32 v)
+{
+ mMessageBuilder->addF32(varname, v);
+}
+
+void LLMessageSystem::addF32(const char *varname, F32 v)
+{
+ mMessageBuilder->addF32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addS32Fast(const char *varname, S32 v)
+{
+ mMessageBuilder->addS32(varname, v);
+}
+
+void LLMessageSystem::addS32(const char *varname, S32 v)
+{
+ mMessageBuilder->addS32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU32Fast(const char *varname, U32 v)
+{
+ mMessageBuilder->addU32(varname, v);
+}
+
+void LLMessageSystem::addU32(const char *varname, U32 v)
+{
+ mMessageBuilder->addU32(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addU64Fast(const char *varname, U64 v)
+{
+ mMessageBuilder->addU64(varname, v);
+}
+
+void LLMessageSystem::addU64(const char *varname, U64 v)
+{
+ mMessageBuilder->addU64(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addF64Fast(const char *varname, F64 v)
+{
+ mMessageBuilder->addF64(varname, v);
+}
+
+void LLMessageSystem::addF64(const char *varname, F64 v)
+{
+ mMessageBuilder->addF64(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addIPAddrFast(const char *varname, U32 v)
+{
+ mMessageBuilder->addIPAddr(varname, v);
+}
+
+void LLMessageSystem::addIPAddr(const char *varname, U32 v)
+{
+ mMessageBuilder->addIPAddr(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addIPPortFast(const char *varname, U16 v)
+{
+ mMessageBuilder->addIPPort(varname, v);
+}
+
+void LLMessageSystem::addIPPort(const char *varname, U16 v)
+{
+ mMessageBuilder->addIPPort(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addBOOLFast(const char* varname, bool v)
+{
+ mMessageBuilder->addBOOL(varname, v);
+}
+
+void LLMessageSystem::addBOOL(const char* varname, bool v)
+{
+ mMessageBuilder->addBOOL(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const char* v)
+{
+ mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const char* v)
+{
+ mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addStringFast(const char* varname, const std::string& v)
+{
+ mMessageBuilder->addString(varname, v);
+}
+
+void LLMessageSystem::addString(const char* varname, const std::string& v)
+{
+ mMessageBuilder->addString(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector3Fast(const char *varname, const LLVector3& v)
+{
+ mMessageBuilder->addVector3(varname, v);
+}
+
+void LLMessageSystem::addVector3(const char *varname, const LLVector3& v)
+{
+ mMessageBuilder->addVector3(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector4Fast(const char *varname, const LLVector4& v)
+{
+ mMessageBuilder->addVector4(varname, v);
+}
+
+void LLMessageSystem::addVector4(const char *varname, const LLVector4& v)
+{
+ mMessageBuilder->addVector4(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addVector3dFast(const char *varname, const LLVector3d& v)
+{
+ mMessageBuilder->addVector3d(varname, v);
+}
+
+void LLMessageSystem::addVector3d(const char *varname, const LLVector3d& v)
+{
+ mMessageBuilder->addVector3d(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+void LLMessageSystem::addQuatFast(const char *varname, const LLQuaternion& v)
+{
+ mMessageBuilder->addQuat(varname, v);
+}
+
+void LLMessageSystem::addQuat(const char *varname, const LLQuaternion& v)
+{
+ mMessageBuilder->addQuat(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+
+void LLMessageSystem::addUUIDFast(const char *varname, const LLUUID& v)
+{
+ mMessageBuilder->addUUID(varname, v);
+}
+
+void LLMessageSystem::addUUID(const char *varname, const LLUUID& v)
+{
+ mMessageBuilder->addUUID(LLMessageStringTable::getInstance()->getString(varname), v);
+}
+
+S32 LLMessageSystem::getCurrentSendTotal() const
+{
+ return mMessageBuilder->getMessageSize();
+}
+
+void LLMessageSystem::getS8Fast(const char *block, const char *var, S8 &u,
+ S32 blocknum)
+{
+ mMessageReader->getS8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getS8(const char *block, const char *var, S8 &u,
+ S32 blocknum)
+{
+ getS8Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getU8Fast(const char *block, const char *var, U8 &u,
+ S32 blocknum)
+{
+ mMessageReader->getU8(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getU8(const char *block, const char *var, U8 &u,
+ S32 blocknum)
+{
+ getU8Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getBOOLFast(const char *block, const char *var, bool &b,
+ S32 blocknum)
+{
+ mMessageReader->getBOOL(block, var, b, blocknum);
+}
+
+void LLMessageSystem::getBOOL(const char *block, const char *var, bool &b,
+ S32 blocknum)
+{
+ getBOOLFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), b, blocknum);
+}
+
+void LLMessageSystem::getS16Fast(const char *block, const char *var, S16 &d,
+ S32 blocknum)
+{
+ mMessageReader->getS16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS16(const char *block, const char *var, S16 &d,
+ S32 blocknum)
+{
+ getS16Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU16Fast(const char *block, const char *var, U16 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU16(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU16(const char *block, const char *var, U16 &d,
+ S32 blocknum)
+{
+ getU16Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getS32Fast(const char *block, const char *var, S32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getS32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getS32(const char *block, const char *var, S32 &d,
+ S32 blocknum)
+{
+ getS32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU32Fast(const char *block, const char *var, U32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU32(const char *block, const char *var, U32 &d,
+ S32 blocknum)
+{
+ getU32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getU64Fast(const char *block, const char *var, U64 &d,
+ S32 blocknum)
+{
+ mMessageReader->getU64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getU64(const char *block, const char *var, U64 &d,
+ S32 blocknum)
+{
+
+ getU64Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getBinaryDataFast(const char *blockname,
+ const char *varname,
+ void *datap, S32 size,
+ S32 blocknum, S32 max_size)
+{
+ mMessageReader->getBinaryData(blockname, varname, datap, size, blocknum,
+ max_size);
+}
+
+void LLMessageSystem::getBinaryData(const char *blockname,
+ const char *varname,
+ void *datap, S32 size,
+ S32 blocknum, S32 max_size)
+{
+ getBinaryDataFast(LLMessageStringTable::getInstance()->getString(blockname),
+ LLMessageStringTable::getInstance()->getString(varname),
+ datap, size, blocknum, max_size);
+}
+
+void LLMessageSystem::getF32Fast(const char *block, const char *var, F32 &d,
+ S32 blocknum)
+{
+ mMessageReader->getF32(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF32(const char *block, const char *var, F32 &d,
+ S32 blocknum)
+{
+ getF32Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+void LLMessageSystem::getF64Fast(const char *block, const char *var, F64 &d,
+ S32 blocknum)
+{
+ mMessageReader->getF64(block, var, d, blocknum);
+}
+
+void LLMessageSystem::getF64(const char *block, const char *var, F64 &d,
+ S32 blocknum)
+{
+ getF64Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), d, blocknum);
+}
+
+
+void LLMessageSystem::getVector3Fast(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ mMessageReader->getVector3(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3(const char *block, const char *var,
+ LLVector3 &v, S32 blocknum )
+{
+ getVector3Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector4Fast(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum )
+{
+ mMessageReader->getVector4(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector4(const char *block, const char *var,
+ LLVector4 &v, S32 blocknum )
+{
+ getVector4Fast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getVector3dFast(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ mMessageReader->getVector3d(block, var, v, blocknum);
+}
+
+void LLMessageSystem::getVector3d(const char *block, const char *var,
+ LLVector3d &v, S32 blocknum )
+{
+ getVector3dFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), v, blocknum);
+}
+
+void LLMessageSystem::getQuatFast(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum )
+{
+ mMessageReader->getQuat(block, var, q, blocknum);
+}
+
+void LLMessageSystem::getQuat(const char *block, const char *var,
+ LLQuaternion &q, S32 blocknum)
+{
+ getQuatFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), q, blocknum);
+}
+
+void LLMessageSystem::getUUIDFast(const char *block, const char *var,
+ LLUUID &u, S32 blocknum )
+{
+ mMessageReader->getUUID(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getUUID(const char *block, const char *var, LLUUID &u,
+ S32 blocknum )
+{
+ getUUIDFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPAddrFast(const char *block, const char *var,
+ U32 &u, S32 blocknum)
+{
+ mMessageReader->getIPAddr(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPAddr(const char *block, const char *var, U32 &u,
+ S32 blocknum)
+{
+ getIPAddrFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u, blocknum);
+}
+
+void LLMessageSystem::getIPPortFast(const char *block, const char *var,
+ U16 &u, S32 blocknum)
+{
+ mMessageReader->getIPPort(block, var, u, blocknum);
+}
+
+void LLMessageSystem::getIPPort(const char *block, const char *var, U16 &u,
+ S32 blocknum)
+{
+ getIPPortFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), u,
+ blocknum);
+}
+
+
+void LLMessageSystem::getStringFast(const char *block, const char *var,
+ S32 buffer_size, char *s, S32 blocknum)
+{
+ if(buffer_size <= 0)
+ {
+ LL_WARNS("Messaging") << "buffer_size <= 0" << LL_ENDL;
+ }
+ mMessageReader->getString(block, var, buffer_size, s, blocknum);
+}
+
+void LLMessageSystem::getString(const char *block, const char *var,
+ S32 buffer_size, char *s, S32 blocknum )
+{
+ getStringFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), buffer_size, s,
+ blocknum);
+}
+
+void LLMessageSystem::getStringFast(const char *block, const char *var,
+ std::string& outstr, S32 blocknum)
+{
+ mMessageReader->getString(block, var, outstr, blocknum);
+}
+
+void LLMessageSystem::getString(const char *block, const char *var,
+ std::string& outstr, S32 blocknum )
+{
+ getStringFast(LLMessageStringTable::getInstance()->getString(block),
+ LLMessageStringTable::getInstance()->getString(var), outstr,
+ blocknum);
+}
+
+bool LLMessageSystem::has(const char *blockname) const
+{
+ return getNumberOfBlocks(blockname) > 0;
+}
+
+S32 LLMessageSystem::getNumberOfBlocksFast(const char *blockname) const
+{
+ return mMessageReader->getNumberOfBlocks(blockname);
+}
+
+S32 LLMessageSystem::getNumberOfBlocks(const char *blockname) const
+{
+ return getNumberOfBlocksFast(LLMessageStringTable::getInstance()->getString(blockname));
+}
+
+S32 LLMessageSystem::getSizeFast(const char *blockname, const char *varname) const
+{
+ return mMessageReader->getSize(blockname, varname);
+}
+
+S32 LLMessageSystem::getSize(const char *blockname, const char *varname) const
+{
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname),
+ LLMessageStringTable::getInstance()->getString(varname));
+}
+
+// size in bytes of variable length data
+S32 LLMessageSystem::getSizeFast(const char *blockname, S32 blocknum,
+ const char *varname) const
+{
+ return mMessageReader->getSize(blockname, blocknum, varname);
+}
+
+S32 LLMessageSystem::getSize(const char *blockname, S32 blocknum,
+ const char *varname) const
+{
+ return getSizeFast(LLMessageStringTable::getInstance()->getString(blockname), blocknum,
+ LLMessageStringTable::getInstance()->getString(varname));
+}
+
+S32 LLMessageSystem::getReceiveSize() const
+{
+ return mMessageReader->getMessageSize();
+}
+
+//static
+void LLMessageSystem::setTimeDecodes( bool b )
+{
+ LLMessageReader::setTimeDecodes(b);
+}
+
+//static
+void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
+{
+ LLMessageReader::setTimeDecodesSpamThreshold(seconds);
+}
+
+LockMessageChecker::LockMessageChecker(LLMessageSystem* msgsystem):
+ // for the lifespan of this LockMessageChecker instance, use
+ // LLTemplateMessageReader as msgsystem's mMessageReader
+ LockMessageReader(msgsystem->mMessageReader, msgsystem->mTemplateMessageReader),
+ mMessageSystem(msgsystem)
+{}
+
+// HACK! babbage: return true if message rxed via either UDP or HTTP
+// TODO: babbage: move gServicePump in to LLMessageSystem?
+bool LLMessageSystem::checkAllMessages(LockMessageChecker& lmc, S64 frame_count, LLPumpIO* http_pump)
+{
+ if(lmc.checkMessages(frame_count))
+ {
+ return true;
+ }
+ U32 packetsIn = mPacketsIn;
+ http_pump->pump();
+ http_pump->callback();
+ return (mPacketsIn - packetsIn) > 0;
+}
+
+void LLMessageSystem::banUdpMessage(const std::string& name)
+{
+ message_template_name_map_t::iterator itt = mMessageTemplates.find(
+ LLMessageStringTable::getInstance()->getString(name.c_str())
+ );
+ if(itt != mMessageTemplates.end())
+ {
+ itt->second->banUdp();
+ }
+ else
+ {
+ LL_WARNS() << "Attempted to ban an unknown message: " << name << "." << LL_ENDL;
+ }
+}
+const LLHost& LLMessageSystem::getSender() const
+{
+ return mLastSender;
+}
+
+void LLMessageSystem::sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback)
+{
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("untrustedSimulatorMessage", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+ LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
+
+
+ if (url.empty())
+ {
+ LL_WARNS() << "sendUntrustedSimulatorMessageCoro called with empty capability!" << LL_ENDL;
+ return;
+ }
+
+ LL_INFOS() << "sendUntrustedSimulatorMessageCoro: message " << message << " to cap " << url << LL_ENDL;
+ LLSD postData;
+ postData["message"] = message;
+ postData["body"] = body;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData, httpOpts);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if ((callback) && (!callback.empty()))
+ callback((status) ? LL_ERR_NOERR : LL_ERR_TCP_TIMEOUT);
+}
+
+
+LLHTTPRegistration<LLHTTPNodeAdapter<LLTrustedMessageService> >
+ gHTTPRegistrationTrustedMessageWildcard("/trusted-message/<message-name>");
+
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 65c1e07a68..8f15bc266d 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -1,1171 +1,1171 @@
-/**
- * @file message.h
- * @brief LLMessageSystem class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_MESSAGE_H
-#define LL_MESSAGE_H
-
-#include <cstring>
-#include <set>
-
-#if LL_LINUX
-#include <endian.h>
-#include <netinet/in.h>
-#endif
-
-#if LL_WINDOWS
-#include "winsock2.h" // htons etc.
-#endif
-
-#include "llerror.h"
-#include "net.h"
-#include "llstringtable.h"
-#include "llcircuit.h"
-#include "lltimer.h"
-#include "llpacketring.h"
-#include "llhost.h"
-#include "llhttpnode.h"
-//#include "llpacketack.h"
-#include "llsingleton.h"
-#include "message_prehash.h"
-#include "llstl.h"
-#include "llmsgvariabletype.h"
-#include "llmessagesenderinterface.h"
-
-#include "llstoredmessage.h"
-#include "boost/function.hpp"
-#include "llpounceable.h"
-#include "llcoros.h"
-#include LLCOROS_MUTEX_HEADER
-
-const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
-const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
-
-const S32 MESSAGE_MAX_PER_FRAME = 400;
-
-class LLMessageStringTable : public LLSingleton<LLMessageStringTable>
-{
- LLSINGLETON(LLMessageStringTable);
- ~LLMessageStringTable();
-
-public:
- char *getString(const char *str);
-
- U32 mUsed;
- bool mEmpty[MESSAGE_NUMBER_OF_HASH_BUCKETS];
- char mString[MESSAGE_NUMBER_OF_HASH_BUCKETS][MESSAGE_MAX_STRINGS_LENGTH]; /* Flawfinder: ignore */
-};
-
-
-// Individual Messages are described with the following format
-// Note that to ease parsing, keywords are used
-//
-// // Comment (Comment like a C++ single line comment)
-// Comments can only be placed between Messages
-// {
-// MessageName (same naming restrictions as C variable)
-// Frequency ("High", "Medium", or "Low" - determines whether message ID is 8, 16, or 32-bits --
-// there can 254 messages in the first 2 groups, 32K in the last group)
-// (A message can be made up only of the Name if it is only a signal)
-// Trust ("Trusted", "NotTrusted" - determines if a message will be accepted
-// on a circuit. "Trusted" messages are not accepted from NotTrusted circuits
-// while NotTrusted messages are accepted on any circuit. An example of a
-// NotTrusted circuit is any circuit from the viewer.)
-// Encoding ("Zerocoded", "Unencoded" - zerocoded messages attempt to compress sequences of
-// zeros, but if there is no space win, it discards the compression and goes unencoded)
-// {
-// Block Name (same naming restrictions as C variable)
-// Block Type ("Single", "Multiple", or "Variable" - determines if the block is coded once,
-// a known number of times, or has a 8 bit argument encoded to tell the decoder
-// how many times the group is repeated)
-// Block Repeat Number (Optional - used only with the "Multiple" type - tells how many times the field is repeated
-// {
-// Variable 1 Name (same naming restrictions as C variable)
-// Variable Type ("Fixed" or "Variable" - determines if the variable is of fixed size or needs to
-// encode an argument describing the size in bytes)
-// Variable Size (In bytes, either of the "Fixed" variable itself or of the size argument)
-//
-// repeat variables
-//
-// }
-//
-// Repeat for number of variables in block
-// }
-//
-// Repeat for number of blocks in message
-// }
-// Repeat for number of messages in file
-//
-
-// Constants
-const S32 MAX_MESSAGE_INTERNAL_NAME_SIZE = 255;
-const S32 MAX_BUFFER_SIZE = NET_BUFFER_SIZE;
-const S32 MAX_BLOCKS = 255;
-
-const U8 LL_ZERO_CODE_FLAG = 0x80;
-const U8 LL_RELIABLE_FLAG = 0x40;
-const U8 LL_RESENT_FLAG = 0x20;
-const U8 LL_ACK_FLAG = 0x10;
-
-// 1 byte flags, 4 bytes sequence, 1 byte offset + 1 byte message name (high)
-const S32 LL_MINIMUM_VALID_PACKET_SIZE = LL_PACKET_ID_SIZE + 1;
-enum EPacketHeaderLayout
-{
- PHL_FLAGS = 0,
- PHL_PACKET_ID = 1,
- PHL_OFFSET = 5,
- PHL_NAME = 6
-};
-
-
-const S32 LL_DEFAULT_RELIABLE_RETRIES = 3;
-const F32Seconds LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS(1.f);
-const F32Seconds LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS(1.f);
-const F32Seconds LL_PING_BASED_TIMEOUT_DUMMY(0.0f);
-
-const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping
-const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping
-const F32 LL_LOST_TIMEOUT_FACTOR = 16.f; // averaged ping for marking packets "Lost"
-const F32Seconds LL_MAX_LOST_TIMEOUT(5.f); // Maximum amount of time before considering something "lost"
-
-const S32 MAX_MESSAGE_COUNT_NUM = 1024;
-
-// Forward declarations
-class LLVector3;
-class LLVector4;
-class LLVector3d;
-class LLQuaternion;
-class LLSD;
-class LLUUID;
-class LLMessageSystem;
-class LLPumpIO;
-
-// message system exceptional condition handlers.
-enum EMessageException
-{
- MX_UNREGISTERED_MESSAGE, // message number not part of template
- MX_PACKET_TOO_SHORT, // invalid packet, shorter than minimum packet size
- MX_RAN_OFF_END_OF_PACKET, // ran off the end of the packet during decode
- MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
-};
-typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
-
-
-// message data pieces are used to collect the data called for by the message template
-class LLMsgData;
-class LLMsgBlkData;
-class LLMessageTemplate;
-
-class LLMessagePollInfo;
-class LLMessageBuilder;
-class LLTemplateMessageBuilder;
-class LLSDMessageBuilder;
-class LLMessageReader;
-class LLTemplateMessageReader;
-class LLSDMessageReader;
-
-
-
-class LLUseCircuitCodeResponder
-{
- LOG_CLASS(LLMessageSystem);
-
-public:
- virtual ~LLUseCircuitCodeResponder();
- virtual void complete(const LLHost& host, const LLUUID& agent) const = 0;
-};
-
-/**
- * SL-12204: We've observed crashes when consumer code sets
- * LLMessageSystem::mMessageReader, assuming that all subsequent processing of
- * the current message will use the same mMessageReader value -- only to have
- * a different coroutine sneak in and replace mMessageReader before
- * completion. This is a limitation of sharing a stateful global resource for
- * message parsing; instead code receiving a new message should instantiate a
- * (trivially constructed) local message parser and use that.
- *
- * Until then, when one coroutine sets a particular LLMessageReader subclass
- * as the current message reader, ensure that no other coroutine can replace
- * it until the first coroutine has finished with its message.
- *
- * This is achieved with two helper classes. LLMessageSystem::mMessageReader
- * is now an LLMessageReaderPointer instance, which can efficiently compare or
- * dereference its contained LLMessageReader* but which cannot be directly
- * assigned. To change the value of LLMessageReaderPointer, you must
- * instantiate LockMessageReader with the LLMessageReader* you wish to make
- * current. mMessageReader will have that value for the lifetime of the
- * LockMessageReader instance, then revert to nullptr. Moreover, as its name
- * implies, LockMessageReader locks the mutex in LLMessageReaderPointer so
- * that any other coroutine instantiating LockMessageReader will block until
- * the first coroutine has destroyed its instance.
- */
-class LLMessageReaderPointer
-{
-public:
- LLMessageReaderPointer(): mPtr(nullptr) {}
- // It is essential that comparison and dereferencing must be fast, which
- // is why we don't check for nullptr when dereferencing.
- LLMessageReader* operator->() const { return mPtr; }
- bool operator==(const LLMessageReader* other) const { return mPtr == other; }
- bool operator!=(const LLMessageReader* other) const { return ! (*this == other); }
-private:
- // Only LockMessageReader can set mPtr.
- friend class LockMessageReader;
- LLMessageReader* mPtr;
- LLCoros::Mutex mMutex;
-};
-
-/**
- * To set mMessageReader to nullptr:
- *
- * @code
- * // use an anonymous instance that is destroyed immediately
- * LockMessageReader(gMessageSystem->mMessageReader, nullptr);
- * @endcode
- *
- * Why do we still require going through LockMessageReader at all? Because it
- * would be Bad if any coroutine set mMessageReader to nullptr while another
- * coroutine was still parsing a message.
- */
-class LockMessageReader
-{
-public:
- LockMessageReader(LLMessageReaderPointer& var, LLMessageReader* instance):
- mVar(var.mPtr),
- mLock(var.mMutex)
- {
- mVar = instance;
- }
- // Some compilers reportedly fail to suppress generating implicit copy
- // operations even though we have a move-only LockType data member.
- LockMessageReader(const LockMessageReader&) = delete;
- LockMessageReader& operator=(const LockMessageReader&) = delete;
- ~LockMessageReader()
- {
- mVar = nullptr;
- }
-private:
- // capture a reference to LLMessageReaderPointer::mPtr
- decltype(LLMessageReaderPointer::mPtr)& mVar;
- // while holding a lock on LLMessageReaderPointer::mMutex
- LLCoros::LockType mLock;
-};
-
-/**
- * LockMessageReader is great as long as you only need mMessageReader locked
- * during a single LLMessageSystem function call. However, empirically the
- * sequence from checkAllMessages() through processAcks() need mMessageReader
- * locked to LLTemplateMessageReader. Enforce that by making them require an
- * instance of LockMessageChecker.
- */
-class LockMessageChecker;
-
-class LLMessageSystem : public LLMessageSenderInterface
-{
- private:
- U8 mSendBuffer[MAX_BUFFER_SIZE];
- S32 mSendSize;
-
- bool mBlockUntrustedInterface;
- LLHost mUntrustedInterface;
-
- public:
- LLPacketRing mPacketRing;
- LLReliablePacketParams mReliablePacketParams;
-
- // Set this flag to true when you want *very* verbose logs.
- bool mVerboseLog;
-
- F32 mMessageFileVersionNumber;
-
- typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t;
- typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
-
-private:
- message_template_name_map_t mMessageTemplates;
- message_template_number_map_t mMessageNumbers;
-
-public:
- S32 mSystemVersionMajor;
- S32 mSystemVersionMinor;
- S32 mSystemVersionPatch;
- S32 mSystemVersionServer;
- U32 mVersionFlags;
-
- bool mbProtected;
-
- U32 mNumberHighFreqMessages;
- U32 mNumberMediumFreqMessages;
- U32 mNumberLowFreqMessages;
- S32 mPort;
- S32 mSocket;
-
- U32 mPacketsIn; // total packets in, including compressed and uncompressed
- U32 mPacketsOut; // total packets out, including compressed and uncompressed
-
- U64 mBytesIn; // total bytes in, including compressed and uncompressed
- U64 mBytesOut; // total bytes out, including compressed and uncompressed
-
- U32 mCompressedPacketsIn; // total compressed packets in
- U32 mCompressedPacketsOut; // total compressed packets out
-
- U32 mReliablePacketsIn; // total reliable packets in
- U32 mReliablePacketsOut; // total reliable packets out
-
- U32 mDroppedPackets; // total dropped packets in
- U32 mResentPackets; // total resent packets out
- U32 mFailedResendPackets; // total resend failure packets out
- U32 mOffCircuitPackets; // total # of off-circuit packets rejected
- U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected
-
- S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in
- S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out
- S64 mCompressedBytesIn; // total compressed size of compressed packets in
- S64 mCompressedBytesOut; // total compressed size of compressed packets out
- S64 mTotalBytesIn; // total size of all uncompressed packets in
- S64 mTotalBytesOut; // total size of all uncompressed packets out
-
- bool mSendReliable; // does the outgoing message require a pos ack?
-
- LLCircuit mCircuitInfo;
- F64Seconds mCircuitPrintTime; // used to print circuit debug info every couple minutes
- F32Seconds mCircuitPrintFreq;
-
- std::map<U64, U32> mIPPortToCircuitCode;
- std::map<U32, U64> mCircuitCodeToIPPort;
- U32 mOurCircuitCode;
- S32 mSendPacketFailureCount;
- S32 mUnackedListDepth;
- S32 mUnackedListSize;
- S32 mDSMaxListDepth;
-
-public:
- // Read file and build message templates
- LLMessageSystem(const std::string& filename, U32 port, S32 version_major,
- S32 version_minor, S32 version_patch,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
-
- ~LLMessageSystem();
-
- bool isOK() const { return !mbError; }
- S32 getErrorCode() const { return mErrorCode; }
-
- // Read file and build message templates filename must point to a
- // valid string which specifies the path of a valid linden
- // template.
- void loadTemplateFile(const std::string& filename, bool failure_is_fatal);
-
-
- // methods for building, sending, receiving, and handling messages
- void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
- void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
- {
- setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
- }
-
- // Set a callback function for a message system exception.
- void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
- // Call the specified exception func, and return true if a
- // function was found and called. Otherwise return false.
- bool callExceptionFunc(EMessageException exception);
-
- // Set a function that will be called once per packet processed with the
- // hashed message name and the time spent in the processing handler function
- // measured in seconds. JC
- typedef void (*msg_timing_callback)(const char* hashed_name, F32 time, void* data);
- void setTimingFunc(msg_timing_callback func, void* data = NULL);
- msg_timing_callback getTimingCallback()
- {
- return mTimingCallback;
- }
- void* getTimingCallbackData()
- {
- return mTimingCallbackData;
- }
-
- // This method returns true if the code is in the circuit codes map.
- bool isCircuitCodeKnown(U32 code) const;
-
- // usually called in response to an AddCircuitCode message, but
- // may also be called by the login process.
- bool addCircuitCode(U32 code, const LLUUID& session_id);
-
- bool poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received
- bool checkMessages(LockMessageChecker&, S64 frame_count = 0 );
- void processAcks(LockMessageChecker&, F32 collect_time = 0.f);
-
- bool isMessageFast(const char *msg);
- bool isMessage(const char *msg)
- {
- return isMessageFast(LLMessageStringTable::getInstance()->getString(msg));
- }
-
- void dumpPacketToLog();
-
- char *getMessageName();
-
- const LLHost& getSender() const;
- U32 getSenderIP() const; // getSender() is preferred
- U32 getSenderPort() const; // getSender() is preferred
-
- const LLHost& getReceivingInterface() const;
-
- // This method returns the uuid associated with the sender. The
- // UUID will be null if it is not yet known or is a server
- // circuit.
- const LLUUID& getSenderID() const;
-
- // This method returns the session id associated with the last
- // sender.
- const LLUUID& getSenderSessionID() const;
-
- // set & get the session id (useful for viewers for now.)
- void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; }
- const LLUUID& getMySessionID() { return mSessionID; }
-
- void newMessageFast(const char *name);
- void newMessage(const char *name);
-
-
-public:
- LLStoredMessagePtr getReceivedMessage() const;
- LLStoredMessagePtr getBuiltMessage() const;
- S32 sendMessage(const LLHost &host, LLStoredMessagePtr message);
-
-private:
- LLSD getReceivedMessageLLSD() const;
- LLSD getBuiltMessageLLSD() const;
-
- // NOTE: babbage: Only use to support legacy misuse of the
- // LLMessageSystem API where values are dangerously written
- // as one type and read as another. LLSD does not support
- // dangerous conversions and so converting the message to an
- // LLSD would result in the reads failing. All code which
- // misuses the message system in this way should be made safe
- // but while the unsafe code is run in old processes, this
- // method should be used to forward unsafe messages.
- LLSD wrapReceivedTemplateData() const;
- LLSD wrapBuiltTemplateData() const;
-
-public:
-
- void copyMessageReceivedToSend();
- void clearMessage();
-
- void nextBlockFast(const char *blockname);
- void nextBlock(const char *blockname);
-
-public:
- void addBinaryDataFast(const char *varname, const void *data, S32 size);
- void addBinaryData(const char *varname, const void *data, S32 size);
-
- void addBOOLFast( const char* varname, bool b); // typed, checks storage space
- void addBOOL( const char* varname, bool b); // typed, checks storage space
- void addS8Fast( const char *varname, S8 s); // typed, checks storage space
- void addS8( const char *varname, S8 s); // typed, checks storage space
- void addU8Fast( const char *varname, U8 u); // typed, checks storage space
- void addU8( const char *varname, U8 u); // typed, checks storage space
- void addS16Fast( const char *varname, S16 i); // typed, checks storage space
- void addS16( const char *varname, S16 i); // typed, checks storage space
- void addU16Fast( const char *varname, U16 i); // typed, checks storage space
- void addU16( const char *varname, U16 i); // typed, checks storage space
- void addF32Fast( const char *varname, F32 f); // typed, checks storage space
- void addF32( const char *varname, F32 f); // typed, checks storage space
- void addS32Fast( const char *varname, S32 s); // typed, checks storage space
- void addS32( const char *varname, S32 s); // typed, checks storage space
- void addU32Fast( const char *varname, U32 u); // typed, checks storage space
- void addU32( const char *varname, U32 u); // typed, checks storage space
- void addU64Fast( const char *varname, U64 lu); // typed, checks storage space
- void addU64( const char *varname, U64 lu); // typed, checks storage space
- void addF64Fast( const char *varname, F64 d); // typed, checks storage space
- void addF64( const char *varname, F64 d); // typed, checks storage space
- void addVector3Fast( const char *varname, const LLVector3& vec); // typed, checks storage space
- void addVector3( const char *varname, const LLVector3& vec); // typed, checks storage space
- void addVector4Fast( const char *varname, const LLVector4& vec); // typed, checks storage space
- void addVector4( const char *varname, const LLVector4& vec); // typed, checks storage space
- void addVector3dFast( const char *varname, const LLVector3d& vec); // typed, checks storage space
- void addVector3d( const char *varname, const LLVector3d& vec); // typed, checks storage space
- void addQuatFast( const char *varname, const LLQuaternion& quat); // typed, checks storage space
- void addQuat( const char *varname, const LLQuaternion& quat); // typed, checks storage space
- void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space
- void addUUID( const char *varname, const LLUUID& uuid); // typed, checks storage space
- void addIPAddrFast( const char *varname, const U32 ip); // typed, checks storage space
- void addIPAddr( const char *varname, const U32 ip); // typed, checks storage space
- void addIPPortFast( const char *varname, const U16 port); // typed, checks storage space
- void addIPPort( const char *varname, const U16 port); // typed, checks storage space
- void addStringFast( const char* varname, const char* s); // typed, checks storage space
- void addString( const char* varname, const char* s); // typed, checks storage space
- void addStringFast( const char* varname, const std::string& s); // typed, checks storage space
- void addString( const char* varname, const std::string& s); // typed, checks storage space
-
- S32 getCurrentSendTotal() const;
- TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; }
-
- // This method checks for current send total and returns true if
- // you need to go to the next block type or need to start a new
- // message. Specify the current blockname to check block counts,
- // otherwise the method only checks against MTU.
- bool isSendFull(const char* blockname = NULL);
- bool isSendFullFast(const char* blockname = NULL);
-
- bool removeLastBlock();
-
- //void buildMessage();
-
- S32 zeroCode(U8 **data, S32 *data_size);
- S32 zeroCodeExpand(U8 **data, S32 *data_size);
- S32 zeroCodeAdjustCurrentSendTotal();
-
- // Uses ping-based retry
- S32 sendReliable(const LLHost &host);
-
- // Uses ping-based retry
- S32 sendReliable(const U32 circuit) { return sendReliable(findHost(circuit)); }
-
- // Use this one if you DON'T want automatic ping-based retry.
- S32 sendReliable( const LLHost &host,
- S32 retries,
- bool ping_based_retries,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data);
-
- S32 sendSemiReliable( const LLHost &host,
- void (*callback)(void **,S32), void ** callback_data);
-
- // flush sends a message only if data's been pushed on it.
- S32 flushSemiReliable( const LLHost &host,
- void (*callback)(void **,S32), void ** callback_data);
-
- S32 flushReliable( const LLHost &host );
-
- void forwardMessage(const LLHost &host);
- void forwardReliable(const LLHost &host);
- void forwardReliable(const U32 circuit_code);
- S32 forwardReliable(
- const LLHost &host,
- S32 retries,
- bool ping_based_timeout,
- F32Seconds timeout,
- void (*callback)(void **,S32),
- void ** callback_data);
-
- S32 sendMessage(const LLHost &host);
- S32 sendMessage(const U32 circuit);
-private:
- S32 sendMessage(const LLHost &host, const char* name,
- const LLSD& message);
-public:
- // bool decodeData(const U8 *buffer, const LLHost &host);
-
- /**
- gets binary data from the current message.
-
- @param blockname the name of the block in the message (from the message template)
-
- @param varname
-
- @param datap
-
- @param size expected size - set to zero to get any amount of data up to max_size.
- Make sure max_size is set in that case!
-
- @param blocknum
-
- @param max_size the max number of bytes to read
- */
- void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
- void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
- void getBOOLFast( const char *block, const char *var, bool &data, S32 blocknum = 0);
- void getBOOL( const char *block, const char *var, bool &data, S32 blocknum = 0);
- void getS8Fast( const char *block, const char *var, S8 &data, S32 blocknum = 0);
- void getS8( const char *block, const char *var, S8 &data, S32 blocknum = 0);
- void getU8Fast( const char *block, const char *var, U8 &data, S32 blocknum = 0);
- void getU8( const char *block, const char *var, U8 &data, S32 blocknum = 0);
- void getS16Fast( const char *block, const char *var, S16 &data, S32 blocknum = 0);
- void getS16( const char *block, const char *var, S16 &data, S32 blocknum = 0);
- void getU16Fast( const char *block, const char *var, U16 &data, S32 blocknum = 0);
- void getU16( const char *block, const char *var, U16 &data, S32 blocknum = 0);
- void getS32Fast( const char *block, const char *var, S32 &data, S32 blocknum = 0);
- void getS32( const char *block, const char *var, S32 &data, S32 blocknum = 0);
- void getF32Fast( const char *block, const char *var, F32 &data, S32 blocknum = 0);
- void getF32( const char *block, const char *var, F32 &data, S32 blocknum = 0);
- void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0);
- void getU32( const char *block, const char *var, U32 &data, S32 blocknum = 0);
- void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0);
- void getU64( const char *block, const char *var, U64 &data, S32 blocknum = 0);
- void getF64Fast( const char *block, const char *var, F64 &data, S32 blocknum = 0);
- void getF64( const char *block, const char *var, F64 &data, S32 blocknum = 0);
- void getVector3Fast( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
- void getVector3( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
- void getVector4Fast( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
- void getVector4( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
- void getVector3dFast(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
- void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
- void getQuatFast( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
- void getQuat( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
- void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
- void getUUID( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
- void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
- void getIPAddr( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
- void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0);
- void getIPPort( const char *block, const char *var, U16 &port, S32 blocknum = 0);
- void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
- void getString( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
- void getStringFast( const char *block, const char *var, std::string& outstr, S32 blocknum = 0);
- void getString( const char *block, const char *var, std::string& outstr, S32 blocknum = 0);
-
-
- // Utility functions to generate a replay-resistant digest check
- // against the shared secret. The window specifies how much of a
- // time window is allowed - 1 second is good for tight
- // connections, but multi-process windows might want to be upwards
- // of 5 seconds. For generateDigest, you want to pass in a
- // character array of at least MD5HEX_STR_SIZE so that the hex
- // digest and null termination will fit.
- bool generateDigestForNumberAndUUIDs(char* digest, const U32 number, const LLUUID &id1, const LLUUID &id2) const;
- bool generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
- bool isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
-
- bool generateDigestForNumber(char* digest, const U32 number) const;
- bool generateDigestForWindow(char* digest, const S32 window) const;
- bool isMatchingDigestForWindow(const char* digest, const S32 window) const;
-
- void showCircuitInfo();
- void getCircuitInfo(LLSD& info) const;
-
- U32 getOurCircuitCode();
-
- void enableCircuit(const LLHost &host, bool trusted);
- void disableCircuit(const LLHost &host);
-
- // Use this to establish trust on startup and in response to
- // DenyTrustedCircuit.
- void sendCreateTrustedCircuit(const LLHost& host, const LLUUID & id1, const LLUUID & id2);
-
- // Use this to inform a peer that they aren't currently trusted...
- // This now enqueues the request so that we can ensure that we only send
- // one deny per circuit per message loop so that this doesn't become a DoS.
- // The actual sending is done by reallySendDenyTrustedCircuit()
- void sendDenyTrustedCircuit(const LLHost &host);
-
- /** Return false if host is unknown or untrusted */
- // Note:DaveH/Babbage some trusted messages can be received without a circuit
- bool isTrustedSender(const LLHost& host) const;
-
- /** Return true if current message is from trusted source */
- bool isTrustedSender() const;
-
- /** Return false true if name is unknown or untrusted */
- bool isTrustedMessage(const std::string& name) const;
-
- /** Return false true if name is unknown or trusted */
- bool isUntrustedMessage(const std::string& name) const;
-
- // Mark an interface ineligible for trust
- void setUntrustedInterface( const LLHost host ) { mUntrustedInterface = host; }
- LLHost getUntrustedInterface() const { return mUntrustedInterface; }
- void setBlockUntrustedInterface( bool block ) { mBlockUntrustedInterface = block; } // Throw a switch to allow, sending warnings only
- bool getBlockUntrustedInterface() const { return mBlockUntrustedInterface; }
-
- // Change this message to be UDP black listed.
- void banUdpMessage(const std::string& name);
-
-
-private:
- // A list of the circuits that need to be sent DenyTrustedCircuit messages.
- typedef std::set<LLHost> host_set_t;
- host_set_t mDenyTrustedCircuitSet;
-
- // Really sends the DenyTrustedCircuit message to a given host
- // related to sendDenyTrustedCircuit()
- void reallySendDenyTrustedCircuit(const LLHost &host);
-
-public:
- // Use this to establish trust to and from a host. This blocks
- // until trust has been established, and probably should only be
- // used on startup.
- void establishBidirectionalTrust(const LLHost &host, S64 frame_count = 0);
-
- // returns whether the given host is on a trusted circuit
- // Note:DaveH/Babbage some trusted messages can be received without a circuit
- bool getCircuitTrust(const LLHost &host);
-
- void setCircuitAllowTimeout(const LLHost &host, bool allow);
- void setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
-
- bool checkCircuitBlocked(const U32 circuit);
- bool checkCircuitAlive(const U32 circuit);
- bool checkCircuitAlive(const LLHost &host);
- void setCircuitProtection(bool b_protect);
- U32 findCircuitCode(const LLHost &host);
- LLHost findHost(const U32 circuit_code);
- void sanityCheck();
-
- bool has(const char *blockname) const;
- S32 getNumberOfBlocksFast(const char *blockname) const;
- S32 getNumberOfBlocks(const char *blockname) const;
- S32 getSizeFast(const char *blockname, const char *varname) const;
- S32 getSize(const char *blockname, const char *varname) const;
- S32 getSizeFast(const char *blockname, S32 blocknum,
- const char *varname) const; // size in bytes of data
- S32 getSize(const char *blockname, S32 blocknum, const char *varname) const;
-
- void resetReceiveCounts(); // resets receive counts for all message types to 0
- void dumpReceiveCounts(); // dumps receive count for each message type to LL_INFOS()
- void dumpCircuitInfo(); // Circuit information to LL_INFOS()
-
- bool isClear() const; // returns mbSClear;
- S32 flush(const LLHost &host);
-
- U32 getListenPort( void ) const;
-
- void startLogging(); // start verbose logging
- void stopLogging(); // flush and close file
- void summarizeLogs(std::ostream& str); // log statistics
-
- S32 getReceiveSize() const;
- S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; }
- S32 getReceiveBytes() const;
-
- S32 getUnackedListSize() const { return mUnackedListSize; }
-
- //const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
- //const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
-
- // friends
- friend std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg);
-
- void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable)
- void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable)
-
- static U64Microseconds getMessageTimeUsecs(const bool update = false); // Get the current message system time in microseconds
- static F64Seconds getMessageTimeSeconds(const bool update = false); // Get the current message system time in seconds
-
- static void setTimeDecodes(bool b);
- static void setTimeDecodesSpamThreshold(F32 seconds);
-
- // message handlers internal to the message systesm
- //static void processAssignCircuitCode(LLMessageSystem* msg, void**);
- static void processAddCircuitCode(LLMessageSystem* msg, void**);
- static void processUseCircuitCode(LLMessageSystem* msg, void**);
- static void processError(LLMessageSystem* msg, void**);
-
- // dispatch llsd message to http node tree
- static void dispatch(const std::string& msg_name,
- const LLSD& message);
- static void dispatch(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep);
-
- // this is added to support specific legacy messages and is
- // ***not intended for general use*** Si, Gabriel, 2009
- static void dispatchTemplate(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep);
-
- void setMessageBans(const LLSD& trusted, const LLSD& untrusted);
-
- /**
- * @brief send an error message to the host. This is a helper method.
- *
- * @param host Destination host.
- * @param agent_id Destination agent id (may be null)
- * @param code An HTTP status compatible error code.
- * @param token A specific short string based message
- * @param id The transactionid/uniqueid/sessionid whatever.
- * @param system The hierarchical path to the system (255 bytes)
- * @param message Human readable message (1200 bytes)
- * @param data Extra info.
- * @return Returns value returned from sendReliable().
- */
- S32 sendError(
- const LLHost& host,
- const LLUUID& agent_id,
- S32 code,
- const std::string& token,
- const LLUUID& id,
- const std::string& system,
- const std::string& message,
- const LLSD& data);
-
- // Check UDP messages and pump http_pump to receive HTTP messages.
- bool checkAllMessages(LockMessageChecker&, S64 frame_count, LLPumpIO* http_pump);
-
- // Moved to allow access from LLTemplateMessageDispatcher
- void clearReceiveState();
-
- // This will cause all trust queries to return true until the next message
- // is read: use with caution!
- void receivedMessageFromTrustedSender();
-
-private:
- typedef boost::function<void(S32)> UntrustedCallback_t;
- void sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback);
-
-
- bool mLastMessageFromTrustedMessageService;
-
- // The mCircuitCodes is a map from circuit codes to session
- // ids. This allows us to verify sessions on connect.
- typedef std::map<U32, LLUUID> code_session_map_t;
- code_session_map_t mCircuitCodes;
-
- // Viewers need to track a process session in order to make sure
- // that no one gives them a bad circuit code.
- LLUUID mSessionID;
-
- void addTemplate(LLMessageTemplate *templatep);
- bool decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
-
- void logMsgFromInvalidCircuit( const LLHost& sender, bool recv_reliable );
- void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
- void logValidMsg(LLCircuitData *cdp, const LLHost& sender, bool recv_reliable, bool recv_resent, bool recv_acks );
- void logRanOffEndOfPacket( const LLHost& sender );
-
- class LLMessageCountInfo
- {
- public:
- U32 mMessageNum;
- U32 mMessageBytes;
- bool mInvalid;
- };
-
- LLMessagePollInfo *mPollInfop;
-
- U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE];
- U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE];
- S32 mTrueReceiveSize;
-
- // Must be valid during decode
-
- bool mbError;
- S32 mErrorCode;
-
- F64Seconds mResendDumpTime; // The last time we dumped resends
-
- LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM];
- S32 mNumMessageCounts;
- F32Seconds mReceiveTime;
- F32Seconds mMaxMessageTime; // Max number of seconds for processing messages
- S32 mMaxMessageCounts; // Max number of messages to process before dumping.
- F64Seconds mMessageCountTime;
-
- F64Seconds mCurrentMessageTime; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount
-
- // message system exceptions
- typedef std::pair<msg_exception_callback, void*> exception_t;
- typedef std::map<EMessageException, exception_t> callbacks_t;
- callbacks_t mExceptionCallbacks;
-
- // stuff for logging
- LLTimer mMessageSystemTimer;
-
- static F32 mTimeDecodesSpamThreshold; // If mTimeDecodes is on, all this many seconds for each msg decode before spamming
- static bool mTimeDecodes; // Measure time for all message decodes if true;
-
- msg_timing_callback mTimingCallback;
- void* mTimingCallbackData;
-
- void init(); // ctor shared initialisation.
-
- LLHost mLastSender;
- LLHost mLastReceivingIF;
- S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.)
- TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting)
-
- LLMessageBuilder* mMessageBuilder;
- LLTemplateMessageBuilder* mTemplateMessageBuilder;
- LLSDMessageBuilder* mLLSDMessageBuilder;
- LLMessageReaderPointer mMessageReader;
- LLTemplateMessageReader* mTemplateMessageReader;
- LLSDMessageReader* mLLSDMessageReader;
-
- friend class LLMessageHandlerBridge;
- friend class LockMessageChecker;
-
- bool callHandler(const char *name, bool trustedSource,
- LLMessageSystem* msg);
-
-
- /** Find, create or revive circuit for host as needed */
- LLCircuitData* findCircuit(const LLHost& host, bool resetPacketId);
-};
-
-
-// external hook into messaging system
-extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
-
-// Implementation of LockMessageChecker depends on definition of
-// LLMessageSystem, hence must follow it.
-class LockMessageChecker: public LockMessageReader
-{
-public:
- LockMessageChecker(LLMessageSystem* msgsystem);
-
- // For convenience, provide forwarding wrappers so you can call (e.g.)
- // checkAllMessages() on your LockMessageChecker instance instead of
- // passing the instance to LLMessageSystem::checkAllMessages(). Use
- // perfect forwarding to avoid having to maintain these wrappers in sync
- // with the target methods.
- template <typename... ARGS>
- bool checkAllMessages(ARGS&&... args)
- {
- return mMessageSystem->checkAllMessages(*this, std::forward<ARGS>(args)...);
- }
-
- template <typename... ARGS>
- bool checkMessages(ARGS&&... args)
- {
- return mMessageSystem->checkMessages(*this, std::forward<ARGS>(args)...);
- }
-
- template <typename... ARGS>
- void processAcks(ARGS&&... args)
- {
- return mMessageSystem->processAcks(*this, std::forward<ARGS>(args)...);
- }
-
-private:
- LLMessageSystem* mMessageSystem;
-};
-
-// Must specific overall system version, which is used to determine
-// if a patch is available in the message template checksum verification.
-// Return true if able to initialize system.
-bool start_messaging_system(
- const std::string& template_name,
- U32 port,
- S32 version_major,
- S32 version_minor,
- S32 version_patch,
- bool b_dump_prehash_file,
- const std::string& secret,
- const LLUseCircuitCodeResponder* responder,
- bool failure_is_fatal,
- const F32 circuit_heartbeat_interval,
- const F32 circuit_timeout);
-
-void end_messaging_system(bool print_summary = true);
-
-void null_message_callback(LLMessageSystem *msg, void **data);
-
-//
-// Inlines
-//
-
-#if !defined( LL_BIG_ENDIAN ) && !defined( LL_LITTLE_ENDIAN )
-#error Unknown endianness for htolememcpy. Did you miss a common include?
-#endif
-
-static inline void *htolememcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
-{
- char *s = (char *)vs;
- const char *ct = (const char *)vct;
-#ifdef LL_BIG_ENDIAN
- S32 i, length;
-#endif
- switch(type)
- {
- case MVT_FIXED:
- case MVT_VARIABLE:
- case MVT_U8:
- case MVT_S8:
- case MVT_BOOL:
- case MVT_LLUUID:
- case MVT_IP_ADDR: // these two are swizzled in the getters and setters
- case MVT_IP_PORT: // these two are swizzled in the getters and setters
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-
- case MVT_U16:
- case MVT_S16:
- if (n != 2)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- *(s + 1) = *(ct);
- *(s) = *(ct + 1);
- return(vs);
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_U32:
- case MVT_S32:
- case MVT_F32:
- if (n != 4)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- *(s + 3) = *(ct);
- *(s + 2) = *(ct + 1);
- *(s + 1) = *(ct + 2);
- *(s) = *(ct + 3);
- return(vs);
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_U64:
- case MVT_S64:
- case MVT_F64:
- if (n != 8)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- *(s + 7) = *(ct);
- *(s + 6) = *(ct + 1);
- *(s + 5) = *(ct + 2);
- *(s + 4) = *(ct + 3);
- *(s + 3) = *(ct + 4);
- *(s + 2) = *(ct + 5);
- *(s + 1) = *(ct + 6);
- *(s) = *(ct + 7);
- return(vs);
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_LLVector3:
- case MVT_LLQuaternion: // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0)
- if (n != 12)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- htolememcpy(s + 8, ct + 8, MVT_F32, 4);
- htolememcpy(s + 4, ct + 4, MVT_F32, 4);
- return(htolememcpy(s, ct, MVT_F32, 4));
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_LLVector3d:
- if (n != 24)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- htolememcpy(s + 16, ct + 16, MVT_F64, 8);
- htolememcpy(s + 8, ct + 8, MVT_F64, 8);
- return(htolememcpy(s, ct, MVT_F64, 8));
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_LLVector4:
- if (n != 16)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- htolememcpy(s + 12, ct + 12, MVT_F32, 4);
- htolememcpy(s + 8, ct + 8, MVT_F32, 4);
- htolememcpy(s + 4, ct + 4, MVT_F32, 4);
- return(htolememcpy(s, ct, MVT_F32, 4));
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_U16Vec3:
- if (n != 6)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- htolememcpy(s + 4, ct + 4, MVT_U16, 2);
- htolememcpy(s + 2, ct + 2, MVT_U16, 2);
- return(htolememcpy(s, ct, MVT_U16, 2));
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_U16Quat:
- if (n != 8)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- htolememcpy(s + 6, ct + 6, MVT_U16, 2);
- htolememcpy(s + 4, ct + 4, MVT_U16, 2);
- htolememcpy(s + 2, ct + 2, MVT_U16, 2);
- return(htolememcpy(s, ct, MVT_U16, 2));
-#else
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
-#endif
-
- case MVT_S16Array:
- if (n % 2)
- {
- LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
- }
-#ifdef LL_BIG_ENDIAN
- length = n % 2;
- for (i = 1; i < length; i++)
- {
- htolememcpy(s + i*2, ct + i*2, MVT_S16, 2);
- }
- return(htolememcpy(s, ct, MVT_S16, 2));
-#else
- return(memcpy(s,ct,n));
-#endif
-
- default:
- return(memcpy(s,ct,n)); /* Flawfinder: ignore */
- }
-}
-
-inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n)
-{
- return(htolememcpy(s,ct,type, n));
-}
-
-inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}
-
-inline U32 LLMessageSystem::getSenderIP() const
-{
- return mLastSender.getAddress();
-}
-
-inline U32 LLMessageSystem::getSenderPort() const
-{
- return mLastSender.getPort();
-}
-
-
-//-----------------------------------------------------------------------------
-// Transmission aliases
-//-----------------------------------------------------------------------------
-
-inline S32 LLMessageSystem::sendMessage(const U32 circuit)
-{
- return sendMessage(findHost(circuit));
-}
-
-#endif
+/**
+ * @file message.h
+ * @brief LLMessageSystem class header file
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_MESSAGE_H
+#define LL_MESSAGE_H
+
+#include <cstring>
+#include <set>
+
+#if LL_LINUX
+#include <endian.h>
+#include <netinet/in.h>
+#endif
+
+#if LL_WINDOWS
+#include "winsock2.h" // htons etc.
+#endif
+
+#include "llerror.h"
+#include "net.h"
+#include "llstringtable.h"
+#include "llcircuit.h"
+#include "lltimer.h"
+#include "llpacketring.h"
+#include "llhost.h"
+#include "llhttpnode.h"
+//#include "llpacketack.h"
+#include "llsingleton.h"
+#include "message_prehash.h"
+#include "llstl.h"
+#include "llmsgvariabletype.h"
+#include "llmessagesenderinterface.h"
+
+#include "llstoredmessage.h"
+#include "boost/function.hpp"
+#include "llpounceable.h"
+#include "llcoros.h"
+#include LLCOROS_MUTEX_HEADER
+
+const U32 MESSAGE_MAX_STRINGS_LENGTH = 64;
+const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192;
+
+const S32 MESSAGE_MAX_PER_FRAME = 400;
+
+class LLMessageStringTable : public LLSingleton<LLMessageStringTable>
+{
+ LLSINGLETON(LLMessageStringTable);
+ ~LLMessageStringTable();
+
+public:
+ char *getString(const char *str);
+
+ U32 mUsed;
+ bool mEmpty[MESSAGE_NUMBER_OF_HASH_BUCKETS];
+ char mString[MESSAGE_NUMBER_OF_HASH_BUCKETS][MESSAGE_MAX_STRINGS_LENGTH]; /* Flawfinder: ignore */
+};
+
+
+// Individual Messages are described with the following format
+// Note that to ease parsing, keywords are used
+//
+// // Comment (Comment like a C++ single line comment)
+// Comments can only be placed between Messages
+// {
+// MessageName (same naming restrictions as C variable)
+// Frequency ("High", "Medium", or "Low" - determines whether message ID is 8, 16, or 32-bits --
+// there can 254 messages in the first 2 groups, 32K in the last group)
+// (A message can be made up only of the Name if it is only a signal)
+// Trust ("Trusted", "NotTrusted" - determines if a message will be accepted
+// on a circuit. "Trusted" messages are not accepted from NotTrusted circuits
+// while NotTrusted messages are accepted on any circuit. An example of a
+// NotTrusted circuit is any circuit from the viewer.)
+// Encoding ("Zerocoded", "Unencoded" - zerocoded messages attempt to compress sequences of
+// zeros, but if there is no space win, it discards the compression and goes unencoded)
+// {
+// Block Name (same naming restrictions as C variable)
+// Block Type ("Single", "Multiple", or "Variable" - determines if the block is coded once,
+// a known number of times, or has a 8 bit argument encoded to tell the decoder
+// how many times the group is repeated)
+// Block Repeat Number (Optional - used only with the "Multiple" type - tells how many times the field is repeated
+// {
+// Variable 1 Name (same naming restrictions as C variable)
+// Variable Type ("Fixed" or "Variable" - determines if the variable is of fixed size or needs to
+// encode an argument describing the size in bytes)
+// Variable Size (In bytes, either of the "Fixed" variable itself or of the size argument)
+//
+// repeat variables
+//
+// }
+//
+// Repeat for number of variables in block
+// }
+//
+// Repeat for number of blocks in message
+// }
+// Repeat for number of messages in file
+//
+
+// Constants
+const S32 MAX_MESSAGE_INTERNAL_NAME_SIZE = 255;
+const S32 MAX_BUFFER_SIZE = NET_BUFFER_SIZE;
+const S32 MAX_BLOCKS = 255;
+
+const U8 LL_ZERO_CODE_FLAG = 0x80;
+const U8 LL_RELIABLE_FLAG = 0x40;
+const U8 LL_RESENT_FLAG = 0x20;
+const U8 LL_ACK_FLAG = 0x10;
+
+// 1 byte flags, 4 bytes sequence, 1 byte offset + 1 byte message name (high)
+const S32 LL_MINIMUM_VALID_PACKET_SIZE = LL_PACKET_ID_SIZE + 1;
+enum EPacketHeaderLayout
+{
+ PHL_FLAGS = 0,
+ PHL_PACKET_ID = 1,
+ PHL_OFFSET = 5,
+ PHL_NAME = 6
+};
+
+
+const S32 LL_DEFAULT_RELIABLE_RETRIES = 3;
+const F32Seconds LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS(1.f);
+const F32Seconds LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS(1.f);
+const F32Seconds LL_PING_BASED_TIMEOUT_DUMMY(0.0f);
+
+const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping
+const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping
+const F32 LL_LOST_TIMEOUT_FACTOR = 16.f; // averaged ping for marking packets "Lost"
+const F32Seconds LL_MAX_LOST_TIMEOUT(5.f); // Maximum amount of time before considering something "lost"
+
+const S32 MAX_MESSAGE_COUNT_NUM = 1024;
+
+// Forward declarations
+class LLVector3;
+class LLVector4;
+class LLVector3d;
+class LLQuaternion;
+class LLSD;
+class LLUUID;
+class LLMessageSystem;
+class LLPumpIO;
+
+// message system exceptional condition handlers.
+enum EMessageException
+{
+ MX_UNREGISTERED_MESSAGE, // message number not part of template
+ MX_PACKET_TOO_SHORT, // invalid packet, shorter than minimum packet size
+ MX_RAN_OFF_END_OF_PACKET, // ran off the end of the packet during decode
+ MX_WROTE_PAST_BUFFER_SIZE // wrote past buffer size in zero code expand
+};
+typedef void (*msg_exception_callback)(LLMessageSystem*,void*,EMessageException);
+
+
+// message data pieces are used to collect the data called for by the message template
+class LLMsgData;
+class LLMsgBlkData;
+class LLMessageTemplate;
+
+class LLMessagePollInfo;
+class LLMessageBuilder;
+class LLTemplateMessageBuilder;
+class LLSDMessageBuilder;
+class LLMessageReader;
+class LLTemplateMessageReader;
+class LLSDMessageReader;
+
+
+
+class LLUseCircuitCodeResponder
+{
+ LOG_CLASS(LLMessageSystem);
+
+public:
+ virtual ~LLUseCircuitCodeResponder();
+ virtual void complete(const LLHost& host, const LLUUID& agent) const = 0;
+};
+
+/**
+ * SL-12204: We've observed crashes when consumer code sets
+ * LLMessageSystem::mMessageReader, assuming that all subsequent processing of
+ * the current message will use the same mMessageReader value -- only to have
+ * a different coroutine sneak in and replace mMessageReader before
+ * completion. This is a limitation of sharing a stateful global resource for
+ * message parsing; instead code receiving a new message should instantiate a
+ * (trivially constructed) local message parser and use that.
+ *
+ * Until then, when one coroutine sets a particular LLMessageReader subclass
+ * as the current message reader, ensure that no other coroutine can replace
+ * it until the first coroutine has finished with its message.
+ *
+ * This is achieved with two helper classes. LLMessageSystem::mMessageReader
+ * is now an LLMessageReaderPointer instance, which can efficiently compare or
+ * dereference its contained LLMessageReader* but which cannot be directly
+ * assigned. To change the value of LLMessageReaderPointer, you must
+ * instantiate LockMessageReader with the LLMessageReader* you wish to make
+ * current. mMessageReader will have that value for the lifetime of the
+ * LockMessageReader instance, then revert to nullptr. Moreover, as its name
+ * implies, LockMessageReader locks the mutex in LLMessageReaderPointer so
+ * that any other coroutine instantiating LockMessageReader will block until
+ * the first coroutine has destroyed its instance.
+ */
+class LLMessageReaderPointer
+{
+public:
+ LLMessageReaderPointer(): mPtr(nullptr) {}
+ // It is essential that comparison and dereferencing must be fast, which
+ // is why we don't check for nullptr when dereferencing.
+ LLMessageReader* operator->() const { return mPtr; }
+ bool operator==(const LLMessageReader* other) const { return mPtr == other; }
+ bool operator!=(const LLMessageReader* other) const { return ! (*this == other); }
+private:
+ // Only LockMessageReader can set mPtr.
+ friend class LockMessageReader;
+ LLMessageReader* mPtr;
+ LLCoros::Mutex mMutex;
+};
+
+/**
+ * To set mMessageReader to nullptr:
+ *
+ * @code
+ * // use an anonymous instance that is destroyed immediately
+ * LockMessageReader(gMessageSystem->mMessageReader, nullptr);
+ * @endcode
+ *
+ * Why do we still require going through LockMessageReader at all? Because it
+ * would be Bad if any coroutine set mMessageReader to nullptr while another
+ * coroutine was still parsing a message.
+ */
+class LockMessageReader
+{
+public:
+ LockMessageReader(LLMessageReaderPointer& var, LLMessageReader* instance):
+ mVar(var.mPtr),
+ mLock(var.mMutex)
+ {
+ mVar = instance;
+ }
+ // Some compilers reportedly fail to suppress generating implicit copy
+ // operations even though we have a move-only LockType data member.
+ LockMessageReader(const LockMessageReader&) = delete;
+ LockMessageReader& operator=(const LockMessageReader&) = delete;
+ ~LockMessageReader()
+ {
+ mVar = nullptr;
+ }
+private:
+ // capture a reference to LLMessageReaderPointer::mPtr
+ decltype(LLMessageReaderPointer::mPtr)& mVar;
+ // while holding a lock on LLMessageReaderPointer::mMutex
+ LLCoros::LockType mLock;
+};
+
+/**
+ * LockMessageReader is great as long as you only need mMessageReader locked
+ * during a single LLMessageSystem function call. However, empirically the
+ * sequence from checkAllMessages() through processAcks() need mMessageReader
+ * locked to LLTemplateMessageReader. Enforce that by making them require an
+ * instance of LockMessageChecker.
+ */
+class LockMessageChecker;
+
+class LLMessageSystem : public LLMessageSenderInterface
+{
+ private:
+ U8 mSendBuffer[MAX_BUFFER_SIZE];
+ S32 mSendSize;
+
+ bool mBlockUntrustedInterface;
+ LLHost mUntrustedInterface;
+
+ public:
+ LLPacketRing mPacketRing;
+ LLReliablePacketParams mReliablePacketParams;
+
+ // Set this flag to true when you want *very* verbose logs.
+ bool mVerboseLog;
+
+ F32 mMessageFileVersionNumber;
+
+ typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t;
+ typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t;
+
+private:
+ message_template_name_map_t mMessageTemplates;
+ message_template_number_map_t mMessageNumbers;
+
+public:
+ S32 mSystemVersionMajor;
+ S32 mSystemVersionMinor;
+ S32 mSystemVersionPatch;
+ S32 mSystemVersionServer;
+ U32 mVersionFlags;
+
+ bool mbProtected;
+
+ U32 mNumberHighFreqMessages;
+ U32 mNumberMediumFreqMessages;
+ U32 mNumberLowFreqMessages;
+ S32 mPort;
+ S32 mSocket;
+
+ U32 mPacketsIn; // total packets in, including compressed and uncompressed
+ U32 mPacketsOut; // total packets out, including compressed and uncompressed
+
+ U64 mBytesIn; // total bytes in, including compressed and uncompressed
+ U64 mBytesOut; // total bytes out, including compressed and uncompressed
+
+ U32 mCompressedPacketsIn; // total compressed packets in
+ U32 mCompressedPacketsOut; // total compressed packets out
+
+ U32 mReliablePacketsIn; // total reliable packets in
+ U32 mReliablePacketsOut; // total reliable packets out
+
+ U32 mDroppedPackets; // total dropped packets in
+ U32 mResentPackets; // total resent packets out
+ U32 mFailedResendPackets; // total resend failure packets out
+ U32 mOffCircuitPackets; // total # of off-circuit packets rejected
+ U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected
+
+ S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in
+ S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out
+ S64 mCompressedBytesIn; // total compressed size of compressed packets in
+ S64 mCompressedBytesOut; // total compressed size of compressed packets out
+ S64 mTotalBytesIn; // total size of all uncompressed packets in
+ S64 mTotalBytesOut; // total size of all uncompressed packets out
+
+ bool mSendReliable; // does the outgoing message require a pos ack?
+
+ LLCircuit mCircuitInfo;
+ F64Seconds mCircuitPrintTime; // used to print circuit debug info every couple minutes
+ F32Seconds mCircuitPrintFreq;
+
+ std::map<U64, U32> mIPPortToCircuitCode;
+ std::map<U32, U64> mCircuitCodeToIPPort;
+ U32 mOurCircuitCode;
+ S32 mSendPacketFailureCount;
+ S32 mUnackedListDepth;
+ S32 mUnackedListSize;
+ S32 mDSMaxListDepth;
+
+public:
+ // Read file and build message templates
+ LLMessageSystem(const std::string& filename, U32 port, S32 version_major,
+ S32 version_minor, S32 version_patch,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
+
+ ~LLMessageSystem();
+
+ bool isOK() const { return !mbError; }
+ S32 getErrorCode() const { return mErrorCode; }
+
+ // Read file and build message templates filename must point to a
+ // valid string which specifies the path of a valid linden
+ // template.
+ void loadTemplateFile(const std::string& filename, bool failure_is_fatal);
+
+
+ // methods for building, sending, receiving, and handling messages
+ void setHandlerFuncFast(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL);
+ void setHandlerFunc(const char *name, void (*handler_func)(LLMessageSystem *msgsystem, void **user_data), void **user_data = NULL)
+ {
+ setHandlerFuncFast(LLMessageStringTable::getInstance()->getString(name), handler_func, user_data);
+ }
+
+ // Set a callback function for a message system exception.
+ void setExceptionFunc(EMessageException exception, msg_exception_callback func, void* data = NULL);
+ // Call the specified exception func, and return true if a
+ // function was found and called. Otherwise return false.
+ bool callExceptionFunc(EMessageException exception);
+
+ // Set a function that will be called once per packet processed with the
+ // hashed message name and the time spent in the processing handler function
+ // measured in seconds. JC
+ typedef void (*msg_timing_callback)(const char* hashed_name, F32 time, void* data);
+ void setTimingFunc(msg_timing_callback func, void* data = NULL);
+ msg_timing_callback getTimingCallback()
+ {
+ return mTimingCallback;
+ }
+ void* getTimingCallbackData()
+ {
+ return mTimingCallbackData;
+ }
+
+ // This method returns true if the code is in the circuit codes map.
+ bool isCircuitCodeKnown(U32 code) const;
+
+ // usually called in response to an AddCircuitCode message, but
+ // may also be called by the login process.
+ bool addCircuitCode(U32 code, const LLUUID& session_id);
+
+ bool poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received
+ bool checkMessages(LockMessageChecker&, S64 frame_count = 0 );
+ void processAcks(LockMessageChecker&, F32 collect_time = 0.f);
+
+ bool isMessageFast(const char *msg);
+ bool isMessage(const char *msg)
+ {
+ return isMessageFast(LLMessageStringTable::getInstance()->getString(msg));
+ }
+
+ void dumpPacketToLog();
+
+ char *getMessageName();
+
+ const LLHost& getSender() const;
+ U32 getSenderIP() const; // getSender() is preferred
+ U32 getSenderPort() const; // getSender() is preferred
+
+ const LLHost& getReceivingInterface() const;
+
+ // This method returns the uuid associated with the sender. The
+ // UUID will be null if it is not yet known or is a server
+ // circuit.
+ const LLUUID& getSenderID() const;
+
+ // This method returns the session id associated with the last
+ // sender.
+ const LLUUID& getSenderSessionID() const;
+
+ // set & get the session id (useful for viewers for now.)
+ void setMySessionID(const LLUUID& session_id) { mSessionID = session_id; }
+ const LLUUID& getMySessionID() { return mSessionID; }
+
+ void newMessageFast(const char *name);
+ void newMessage(const char *name);
+
+
+public:
+ LLStoredMessagePtr getReceivedMessage() const;
+ LLStoredMessagePtr getBuiltMessage() const;
+ S32 sendMessage(const LLHost &host, LLStoredMessagePtr message);
+
+private:
+ LLSD getReceivedMessageLLSD() const;
+ LLSD getBuiltMessageLLSD() const;
+
+ // NOTE: babbage: Only use to support legacy misuse of the
+ // LLMessageSystem API where values are dangerously written
+ // as one type and read as another. LLSD does not support
+ // dangerous conversions and so converting the message to an
+ // LLSD would result in the reads failing. All code which
+ // misuses the message system in this way should be made safe
+ // but while the unsafe code is run in old processes, this
+ // method should be used to forward unsafe messages.
+ LLSD wrapReceivedTemplateData() const;
+ LLSD wrapBuiltTemplateData() const;
+
+public:
+
+ void copyMessageReceivedToSend();
+ void clearMessage();
+
+ void nextBlockFast(const char *blockname);
+ void nextBlock(const char *blockname);
+
+public:
+ void addBinaryDataFast(const char *varname, const void *data, S32 size);
+ void addBinaryData(const char *varname, const void *data, S32 size);
+
+ void addBOOLFast( const char* varname, bool b); // typed, checks storage space
+ void addBOOL( const char* varname, bool b); // typed, checks storage space
+ void addS8Fast( const char *varname, S8 s); // typed, checks storage space
+ void addS8( const char *varname, S8 s); // typed, checks storage space
+ void addU8Fast( const char *varname, U8 u); // typed, checks storage space
+ void addU8( const char *varname, U8 u); // typed, checks storage space
+ void addS16Fast( const char *varname, S16 i); // typed, checks storage space
+ void addS16( const char *varname, S16 i); // typed, checks storage space
+ void addU16Fast( const char *varname, U16 i); // typed, checks storage space
+ void addU16( const char *varname, U16 i); // typed, checks storage space
+ void addF32Fast( const char *varname, F32 f); // typed, checks storage space
+ void addF32( const char *varname, F32 f); // typed, checks storage space
+ void addS32Fast( const char *varname, S32 s); // typed, checks storage space
+ void addS32( const char *varname, S32 s); // typed, checks storage space
+ void addU32Fast( const char *varname, U32 u); // typed, checks storage space
+ void addU32( const char *varname, U32 u); // typed, checks storage space
+ void addU64Fast( const char *varname, U64 lu); // typed, checks storage space
+ void addU64( const char *varname, U64 lu); // typed, checks storage space
+ void addF64Fast( const char *varname, F64 d); // typed, checks storage space
+ void addF64( const char *varname, F64 d); // typed, checks storage space
+ void addVector3Fast( const char *varname, const LLVector3& vec); // typed, checks storage space
+ void addVector3( const char *varname, const LLVector3& vec); // typed, checks storage space
+ void addVector4Fast( const char *varname, const LLVector4& vec); // typed, checks storage space
+ void addVector4( const char *varname, const LLVector4& vec); // typed, checks storage space
+ void addVector3dFast( const char *varname, const LLVector3d& vec); // typed, checks storage space
+ void addVector3d( const char *varname, const LLVector3d& vec); // typed, checks storage space
+ void addQuatFast( const char *varname, const LLQuaternion& quat); // typed, checks storage space
+ void addQuat( const char *varname, const LLQuaternion& quat); // typed, checks storage space
+ void addUUIDFast( const char *varname, const LLUUID& uuid); // typed, checks storage space
+ void addUUID( const char *varname, const LLUUID& uuid); // typed, checks storage space
+ void addIPAddrFast( const char *varname, const U32 ip); // typed, checks storage space
+ void addIPAddr( const char *varname, const U32 ip); // typed, checks storage space
+ void addIPPortFast( const char *varname, const U16 port); // typed, checks storage space
+ void addIPPort( const char *varname, const U16 port); // typed, checks storage space
+ void addStringFast( const char* varname, const char* s); // typed, checks storage space
+ void addString( const char* varname, const char* s); // typed, checks storage space
+ void addStringFast( const char* varname, const std::string& s); // typed, checks storage space
+ void addString( const char* varname, const std::string& s); // typed, checks storage space
+
+ S32 getCurrentSendTotal() const;
+ TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; }
+
+ // This method checks for current send total and returns true if
+ // you need to go to the next block type or need to start a new
+ // message. Specify the current blockname to check block counts,
+ // otherwise the method only checks against MTU.
+ bool isSendFull(const char* blockname = NULL);
+ bool isSendFullFast(const char* blockname = NULL);
+
+ bool removeLastBlock();
+
+ //void buildMessage();
+
+ S32 zeroCode(U8 **data, S32 *data_size);
+ S32 zeroCodeExpand(U8 **data, S32 *data_size);
+ S32 zeroCodeAdjustCurrentSendTotal();
+
+ // Uses ping-based retry
+ S32 sendReliable(const LLHost &host);
+
+ // Uses ping-based retry
+ S32 sendReliable(const U32 circuit) { return sendReliable(findHost(circuit)); }
+
+ // Use this one if you DON'T want automatic ping-based retry.
+ S32 sendReliable( const LLHost &host,
+ S32 retries,
+ bool ping_based_retries,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data);
+
+ S32 sendSemiReliable( const LLHost &host,
+ void (*callback)(void **,S32), void ** callback_data);
+
+ // flush sends a message only if data's been pushed on it.
+ S32 flushSemiReliable( const LLHost &host,
+ void (*callback)(void **,S32), void ** callback_data);
+
+ S32 flushReliable( const LLHost &host );
+
+ void forwardMessage(const LLHost &host);
+ void forwardReliable(const LLHost &host);
+ void forwardReliable(const U32 circuit_code);
+ S32 forwardReliable(
+ const LLHost &host,
+ S32 retries,
+ bool ping_based_timeout,
+ F32Seconds timeout,
+ void (*callback)(void **,S32),
+ void ** callback_data);
+
+ S32 sendMessage(const LLHost &host);
+ S32 sendMessage(const U32 circuit);
+private:
+ S32 sendMessage(const LLHost &host, const char* name,
+ const LLSD& message);
+public:
+ // bool decodeData(const U8 *buffer, const LLHost &host);
+
+ /**
+ gets binary data from the current message.
+
+ @param blockname the name of the block in the message (from the message template)
+
+ @param varname
+
+ @param datap
+
+ @param size expected size - set to zero to get any amount of data up to max_size.
+ Make sure max_size is set in that case!
+
+ @param blocknum
+
+ @param max_size the max number of bytes to read
+ */
+ void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
+ void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
+ void getBOOLFast( const char *block, const char *var, bool &data, S32 blocknum = 0);
+ void getBOOL( const char *block, const char *var, bool &data, S32 blocknum = 0);
+ void getS8Fast( const char *block, const char *var, S8 &data, S32 blocknum = 0);
+ void getS8( const char *block, const char *var, S8 &data, S32 blocknum = 0);
+ void getU8Fast( const char *block, const char *var, U8 &data, S32 blocknum = 0);
+ void getU8( const char *block, const char *var, U8 &data, S32 blocknum = 0);
+ void getS16Fast( const char *block, const char *var, S16 &data, S32 blocknum = 0);
+ void getS16( const char *block, const char *var, S16 &data, S32 blocknum = 0);
+ void getU16Fast( const char *block, const char *var, U16 &data, S32 blocknum = 0);
+ void getU16( const char *block, const char *var, U16 &data, S32 blocknum = 0);
+ void getS32Fast( const char *block, const char *var, S32 &data, S32 blocknum = 0);
+ void getS32( const char *block, const char *var, S32 &data, S32 blocknum = 0);
+ void getF32Fast( const char *block, const char *var, F32 &data, S32 blocknum = 0);
+ void getF32( const char *block, const char *var, F32 &data, S32 blocknum = 0);
+ void getU32Fast( const char *block, const char *var, U32 &data, S32 blocknum = 0);
+ void getU32( const char *block, const char *var, U32 &data, S32 blocknum = 0);
+ void getU64Fast( const char *block, const char *var, U64 &data, S32 blocknum = 0);
+ void getU64( const char *block, const char *var, U64 &data, S32 blocknum = 0);
+ void getF64Fast( const char *block, const char *var, F64 &data, S32 blocknum = 0);
+ void getF64( const char *block, const char *var, F64 &data, S32 blocknum = 0);
+ void getVector3Fast( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
+ void getVector3( const char *block, const char *var, LLVector3 &vec, S32 blocknum = 0);
+ void getVector4Fast( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
+ void getVector4( const char *block, const char *var, LLVector4 &vec, S32 blocknum = 0);
+ void getVector3dFast(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
+ void getVector3d(const char *block, const char *var, LLVector3d &vec, S32 blocknum = 0);
+ void getQuatFast( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
+ void getQuat( const char *block, const char *var, LLQuaternion &q, S32 blocknum = 0);
+ void getUUIDFast( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
+ void getUUID( const char *block, const char *var, LLUUID &uuid, S32 blocknum = 0);
+ void getIPAddrFast( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
+ void getIPAddr( const char *block, const char *var, U32 &ip, S32 blocknum = 0);
+ void getIPPortFast( const char *block, const char *var, U16 &port, S32 blocknum = 0);
+ void getIPPort( const char *block, const char *var, U16 &port, S32 blocknum = 0);
+ void getStringFast( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
+ void getString( const char *block, const char *var, S32 buffer_size, char *buffer, S32 blocknum = 0);
+ void getStringFast( const char *block, const char *var, std::string& outstr, S32 blocknum = 0);
+ void getString( const char *block, const char *var, std::string& outstr, S32 blocknum = 0);
+
+
+ // Utility functions to generate a replay-resistant digest check
+ // against the shared secret. The window specifies how much of a
+ // time window is allowed - 1 second is good for tight
+ // connections, but multi-process windows might want to be upwards
+ // of 5 seconds. For generateDigest, you want to pass in a
+ // character array of at least MD5HEX_STR_SIZE so that the hex
+ // digest and null termination will fit.
+ bool generateDigestForNumberAndUUIDs(char* digest, const U32 number, const LLUUID &id1, const LLUUID &id2) const;
+ bool generateDigestForWindowAndUUIDs(char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
+ bool isMatchingDigestForWindowAndUUIDs(const char* digest, const S32 window, const LLUUID &id1, const LLUUID &id2) const;
+
+ bool generateDigestForNumber(char* digest, const U32 number) const;
+ bool generateDigestForWindow(char* digest, const S32 window) const;
+ bool isMatchingDigestForWindow(const char* digest, const S32 window) const;
+
+ void showCircuitInfo();
+ void getCircuitInfo(LLSD& info) const;
+
+ U32 getOurCircuitCode();
+
+ void enableCircuit(const LLHost &host, bool trusted);
+ void disableCircuit(const LLHost &host);
+
+ // Use this to establish trust on startup and in response to
+ // DenyTrustedCircuit.
+ void sendCreateTrustedCircuit(const LLHost& host, const LLUUID & id1, const LLUUID & id2);
+
+ // Use this to inform a peer that they aren't currently trusted...
+ // This now enqueues the request so that we can ensure that we only send
+ // one deny per circuit per message loop so that this doesn't become a DoS.
+ // The actual sending is done by reallySendDenyTrustedCircuit()
+ void sendDenyTrustedCircuit(const LLHost &host);
+
+ /** Return false if host is unknown or untrusted */
+ // Note:DaveH/Babbage some trusted messages can be received without a circuit
+ bool isTrustedSender(const LLHost& host) const;
+
+ /** Return true if current message is from trusted source */
+ bool isTrustedSender() const;
+
+ /** Return false true if name is unknown or untrusted */
+ bool isTrustedMessage(const std::string& name) const;
+
+ /** Return false true if name is unknown or trusted */
+ bool isUntrustedMessage(const std::string& name) const;
+
+ // Mark an interface ineligible for trust
+ void setUntrustedInterface( const LLHost host ) { mUntrustedInterface = host; }
+ LLHost getUntrustedInterface() const { return mUntrustedInterface; }
+ void setBlockUntrustedInterface( bool block ) { mBlockUntrustedInterface = block; } // Throw a switch to allow, sending warnings only
+ bool getBlockUntrustedInterface() const { return mBlockUntrustedInterface; }
+
+ // Change this message to be UDP black listed.
+ void banUdpMessage(const std::string& name);
+
+
+private:
+ // A list of the circuits that need to be sent DenyTrustedCircuit messages.
+ typedef std::set<LLHost> host_set_t;
+ host_set_t mDenyTrustedCircuitSet;
+
+ // Really sends the DenyTrustedCircuit message to a given host
+ // related to sendDenyTrustedCircuit()
+ void reallySendDenyTrustedCircuit(const LLHost &host);
+
+public:
+ // Use this to establish trust to and from a host. This blocks
+ // until trust has been established, and probably should only be
+ // used on startup.
+ void establishBidirectionalTrust(const LLHost &host, S64 frame_count = 0);
+
+ // returns whether the given host is on a trusted circuit
+ // Note:DaveH/Babbage some trusted messages can be received without a circuit
+ bool getCircuitTrust(const LLHost &host);
+
+ void setCircuitAllowTimeout(const LLHost &host, bool allow);
+ void setCircuitTimeoutCallback(const LLHost &host, void (*callback_func)(const LLHost &host, void *user_data), void *user_data);
+
+ bool checkCircuitBlocked(const U32 circuit);
+ bool checkCircuitAlive(const U32 circuit);
+ bool checkCircuitAlive(const LLHost &host);
+ void setCircuitProtection(bool b_protect);
+ U32 findCircuitCode(const LLHost &host);
+ LLHost findHost(const U32 circuit_code);
+ void sanityCheck();
+
+ bool has(const char *blockname) const;
+ S32 getNumberOfBlocksFast(const char *blockname) const;
+ S32 getNumberOfBlocks(const char *blockname) const;
+ S32 getSizeFast(const char *blockname, const char *varname) const;
+ S32 getSize(const char *blockname, const char *varname) const;
+ S32 getSizeFast(const char *blockname, S32 blocknum,
+ const char *varname) const; // size in bytes of data
+ S32 getSize(const char *blockname, S32 blocknum, const char *varname) const;
+
+ void resetReceiveCounts(); // resets receive counts for all message types to 0
+ void dumpReceiveCounts(); // dumps receive count for each message type to LL_INFOS()
+ void dumpCircuitInfo(); // Circuit information to LL_INFOS()
+
+ bool isClear() const; // returns mbSClear;
+ S32 flush(const LLHost &host);
+
+ U32 getListenPort( void ) const;
+
+ void startLogging(); // start verbose logging
+ void stopLogging(); // flush and close file
+ void summarizeLogs(std::ostream& str); // log statistics
+
+ S32 getReceiveSize() const;
+ S32 getReceiveCompressedSize() const { return mIncomingCompressedSize; }
+ S32 getReceiveBytes() const;
+
+ S32 getUnackedListSize() const { return mUnackedListSize; }
+
+ //const char* getCurrentSMessageName() const { return mCurrentSMessageName; }
+ //const char* getCurrentSBlockName() const { return mCurrentSBlockName; }
+
+ // friends
+ friend std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg);
+
+ void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable)
+ void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable)
+
+ static U64Microseconds getMessageTimeUsecs(const bool update = false); // Get the current message system time in microseconds
+ static F64Seconds getMessageTimeSeconds(const bool update = false); // Get the current message system time in seconds
+
+ static void setTimeDecodes(bool b);
+ static void setTimeDecodesSpamThreshold(F32 seconds);
+
+ // message handlers internal to the message systesm
+ //static void processAssignCircuitCode(LLMessageSystem* msg, void**);
+ static void processAddCircuitCode(LLMessageSystem* msg, void**);
+ static void processUseCircuitCode(LLMessageSystem* msg, void**);
+ static void processError(LLMessageSystem* msg, void**);
+
+ // dispatch llsd message to http node tree
+ static void dispatch(const std::string& msg_name,
+ const LLSD& message);
+ static void dispatch(const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep);
+
+ // this is added to support specific legacy messages and is
+ // ***not intended for general use*** Si, Gabriel, 2009
+ static void dispatchTemplate(const std::string& msg_name,
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep);
+
+ void setMessageBans(const LLSD& trusted, const LLSD& untrusted);
+
+ /**
+ * @brief send an error message to the host. This is a helper method.
+ *
+ * @param host Destination host.
+ * @param agent_id Destination agent id (may be null)
+ * @param code An HTTP status compatible error code.
+ * @param token A specific short string based message
+ * @param id The transactionid/uniqueid/sessionid whatever.
+ * @param system The hierarchical path to the system (255 bytes)
+ * @param message Human readable message (1200 bytes)
+ * @param data Extra info.
+ * @return Returns value returned from sendReliable().
+ */
+ S32 sendError(
+ const LLHost& host,
+ const LLUUID& agent_id,
+ S32 code,
+ const std::string& token,
+ const LLUUID& id,
+ const std::string& system,
+ const std::string& message,
+ const LLSD& data);
+
+ // Check UDP messages and pump http_pump to receive HTTP messages.
+ bool checkAllMessages(LockMessageChecker&, S64 frame_count, LLPumpIO* http_pump);
+
+ // Moved to allow access from LLTemplateMessageDispatcher
+ void clearReceiveState();
+
+ // This will cause all trust queries to return true until the next message
+ // is read: use with caution!
+ void receivedMessageFromTrustedSender();
+
+private:
+ typedef boost::function<void(S32)> UntrustedCallback_t;
+ void sendUntrustedSimulatorMessageCoro(std::string url, std::string message, LLSD body, UntrustedCallback_t callback);
+
+
+ bool mLastMessageFromTrustedMessageService;
+
+ // The mCircuitCodes is a map from circuit codes to session
+ // ids. This allows us to verify sessions on connect.
+ typedef std::map<U32, LLUUID> code_session_map_t;
+ code_session_map_t mCircuitCodes;
+
+ // Viewers need to track a process session in order to make sure
+ // that no one gives them a bad circuit code.
+ LLUUID mSessionID;
+
+ void addTemplate(LLMessageTemplate *templatep);
+ bool decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template );
+
+ void logMsgFromInvalidCircuit( const LLHost& sender, bool recv_reliable );
+ void logTrustedMsgFromUntrustedCircuit( const LLHost& sender );
+ void logValidMsg(LLCircuitData *cdp, const LLHost& sender, bool recv_reliable, bool recv_resent, bool recv_acks );
+ void logRanOffEndOfPacket( const LLHost& sender );
+
+ class LLMessageCountInfo
+ {
+ public:
+ U32 mMessageNum;
+ U32 mMessageBytes;
+ bool mInvalid;
+ };
+
+ LLMessagePollInfo *mPollInfop;
+
+ U8 mEncodedRecvBuffer[MAX_BUFFER_SIZE];
+ U8 mTrueReceiveBuffer[MAX_BUFFER_SIZE];
+ S32 mTrueReceiveSize;
+
+ // Must be valid during decode
+
+ bool mbError;
+ S32 mErrorCode;
+
+ F64Seconds mResendDumpTime; // The last time we dumped resends
+
+ LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM];
+ S32 mNumMessageCounts;
+ F32Seconds mReceiveTime;
+ F32Seconds mMaxMessageTime; // Max number of seconds for processing messages
+ S32 mMaxMessageCounts; // Max number of messages to process before dumping.
+ F64Seconds mMessageCountTime;
+
+ F64Seconds mCurrentMessageTime; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount
+
+ // message system exceptions
+ typedef std::pair<msg_exception_callback, void*> exception_t;
+ typedef std::map<EMessageException, exception_t> callbacks_t;
+ callbacks_t mExceptionCallbacks;
+
+ // stuff for logging
+ LLTimer mMessageSystemTimer;
+
+ static F32 mTimeDecodesSpamThreshold; // If mTimeDecodes is on, all this many seconds for each msg decode before spamming
+ static bool mTimeDecodes; // Measure time for all message decodes if true;
+
+ msg_timing_callback mTimingCallback;
+ void* mTimingCallbackData;
+
+ void init(); // ctor shared initialisation.
+
+ LLHost mLastSender;
+ LLHost mLastReceivingIF;
+ S32 mIncomingCompressedSize; // original size of compressed msg (0 if uncomp.)
+ TPACKETID mCurrentRecvPacketID; // packet ID of current receive packet (for reporting)
+
+ LLMessageBuilder* mMessageBuilder;
+ LLTemplateMessageBuilder* mTemplateMessageBuilder;
+ LLSDMessageBuilder* mLLSDMessageBuilder;
+ LLMessageReaderPointer mMessageReader;
+ LLTemplateMessageReader* mTemplateMessageReader;
+ LLSDMessageReader* mLLSDMessageReader;
+
+ friend class LLMessageHandlerBridge;
+ friend class LockMessageChecker;
+
+ bool callHandler(const char *name, bool trustedSource,
+ LLMessageSystem* msg);
+
+
+ /** Find, create or revive circuit for host as needed */
+ LLCircuitData* findCircuit(const LLHost& host, bool resetPacketId);
+};
+
+
+// external hook into messaging system
+extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
+
+// Implementation of LockMessageChecker depends on definition of
+// LLMessageSystem, hence must follow it.
+class LockMessageChecker: public LockMessageReader
+{
+public:
+ LockMessageChecker(LLMessageSystem* msgsystem);
+
+ // For convenience, provide forwarding wrappers so you can call (e.g.)
+ // checkAllMessages() on your LockMessageChecker instance instead of
+ // passing the instance to LLMessageSystem::checkAllMessages(). Use
+ // perfect forwarding to avoid having to maintain these wrappers in sync
+ // with the target methods.
+ template <typename... ARGS>
+ bool checkAllMessages(ARGS&&... args)
+ {
+ return mMessageSystem->checkAllMessages(*this, std::forward<ARGS>(args)...);
+ }
+
+ template <typename... ARGS>
+ bool checkMessages(ARGS&&... args)
+ {
+ return mMessageSystem->checkMessages(*this, std::forward<ARGS>(args)...);
+ }
+
+ template <typename... ARGS>
+ void processAcks(ARGS&&... args)
+ {
+ return mMessageSystem->processAcks(*this, std::forward<ARGS>(args)...);
+ }
+
+private:
+ LLMessageSystem* mMessageSystem;
+};
+
+// Must specific overall system version, which is used to determine
+// if a patch is available in the message template checksum verification.
+// Return true if able to initialize system.
+bool start_messaging_system(
+ const std::string& template_name,
+ U32 port,
+ S32 version_major,
+ S32 version_minor,
+ S32 version_patch,
+ bool b_dump_prehash_file,
+ const std::string& secret,
+ const LLUseCircuitCodeResponder* responder,
+ bool failure_is_fatal,
+ const F32 circuit_heartbeat_interval,
+ const F32 circuit_timeout);
+
+void end_messaging_system(bool print_summary = true);
+
+void null_message_callback(LLMessageSystem *msg, void **data);
+
+//
+// Inlines
+//
+
+#if !defined( LL_BIG_ENDIAN ) && !defined( LL_LITTLE_ENDIAN )
+#error Unknown endianness for htolememcpy. Did you miss a common include?
+#endif
+
+static inline void *htolememcpy(void *vs, const void *vct, EMsgVariableType type, size_t n)
+{
+ char *s = (char *)vs;
+ const char *ct = (const char *)vct;
+#ifdef LL_BIG_ENDIAN
+ S32 i, length;
+#endif
+ switch(type)
+ {
+ case MVT_FIXED:
+ case MVT_VARIABLE:
+ case MVT_U8:
+ case MVT_S8:
+ case MVT_BOOL:
+ case MVT_LLUUID:
+ case MVT_IP_ADDR: // these two are swizzled in the getters and setters
+ case MVT_IP_PORT: // these two are swizzled in the getters and setters
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+
+ case MVT_U16:
+ case MVT_S16:
+ if (n != 2)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 1) = *(ct);
+ *(s) = *(ct + 1);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U32:
+ case MVT_S32:
+ case MVT_F32:
+ if (n != 4)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 3) = *(ct);
+ *(s + 2) = *(ct + 1);
+ *(s + 1) = *(ct + 2);
+ *(s) = *(ct + 3);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U64:
+ case MVT_S64:
+ case MVT_F64:
+ if (n != 8)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ *(s + 7) = *(ct);
+ *(s + 6) = *(ct + 1);
+ *(s + 5) = *(ct + 2);
+ *(s + 4) = *(ct + 3);
+ *(s + 3) = *(ct + 4);
+ *(s + 2) = *(ct + 5);
+ *(s + 1) = *(ct + 6);
+ *(s) = *(ct + 7);
+ return(vs);
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector3:
+ case MVT_LLQuaternion: // We only send x, y, z and infer w (we set x, y, z to ensure that w >= 0)
+ if (n != 12)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ htolememcpy(s + 8, ct + 8, MVT_F32, 4);
+ htolememcpy(s + 4, ct + 4, MVT_F32, 4);
+ return(htolememcpy(s, ct, MVT_F32, 4));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector3d:
+ if (n != 24)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ htolememcpy(s + 16, ct + 16, MVT_F64, 8);
+ htolememcpy(s + 8, ct + 8, MVT_F64, 8);
+ return(htolememcpy(s, ct, MVT_F64, 8));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_LLVector4:
+ if (n != 16)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ htolememcpy(s + 12, ct + 12, MVT_F32, 4);
+ htolememcpy(s + 8, ct + 8, MVT_F32, 4);
+ htolememcpy(s + 4, ct + 4, MVT_F32, 4);
+ return(htolememcpy(s, ct, MVT_F32, 4));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U16Vec3:
+ if (n != 6)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ htolememcpy(s + 4, ct + 4, MVT_U16, 2);
+ htolememcpy(s + 2, ct + 2, MVT_U16, 2);
+ return(htolememcpy(s, ct, MVT_U16, 2));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_U16Quat:
+ if (n != 8)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ htolememcpy(s + 6, ct + 6, MVT_U16, 2);
+ htolememcpy(s + 4, ct + 4, MVT_U16, 2);
+ htolememcpy(s + 2, ct + 2, MVT_U16, 2);
+ return(htolememcpy(s, ct, MVT_U16, 2));
+#else
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+#endif
+
+ case MVT_S16Array:
+ if (n % 2)
+ {
+ LL_ERRS() << "Size argument passed to htolememcpy doesn't match swizzle type size" << LL_ENDL;
+ }
+#ifdef LL_BIG_ENDIAN
+ length = n % 2;
+ for (i = 1; i < length; i++)
+ {
+ htolememcpy(s + i*2, ct + i*2, MVT_S16, 2);
+ }
+ return(htolememcpy(s, ct, MVT_S16, 2));
+#else
+ return(memcpy(s,ct,n));
+#endif
+
+ default:
+ return(memcpy(s,ct,n)); /* Flawfinder: ignore */
+ }
+}
+
+inline void *ntohmemcpy(void *s, const void *ct, EMsgVariableType type, size_t n)
+{
+ return(htolememcpy(s,ct,type, n));
+}
+
+inline const LLHost& LLMessageSystem::getReceivingInterface() const {return mLastReceivingIF;}
+
+inline U32 LLMessageSystem::getSenderIP() const
+{
+ return mLastSender.getAddress();
+}
+
+inline U32 LLMessageSystem::getSenderPort() const
+{
+ return mLastSender.getPort();
+}
+
+
+//-----------------------------------------------------------------------------
+// Transmission aliases
+//-----------------------------------------------------------------------------
+
+inline S32 LLMessageSystem::sendMessage(const U32 circuit)
+{
+ return sendMessage(findHost(circuit));
+}
+
+#endif
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index 4dccacb889..c264a9f086 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -412,7 +412,7 @@ char const* const _PREHASH_GlobalX = LLMessageStringTable::getInstance()->getStr
char const* const _PREHASH_GlobalY = LLMessageStringTable::getInstance()->getString("GlobalY");
char const* const _PREHASH_CopyRotates = LLMessageStringTable::getInstance()->getString("CopyRotates");
char const* const _PREHASH_KickUserAck = LLMessageStringTable::getInstance()->getString("KickUserAck");
-char const* const _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); //legacy var need to be deleted -angela
+char const* const _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); //legacy var need to be deleted -angela
char const* const _PREHASH_SessionID = LLMessageStringTable::getInstance()->getString("SessionID");
char const* const _PREHASH_GlobalZ = LLMessageStringTable::getInstance()->getString("GlobalZ");
char const* const _PREHASH_DeclineFriendship = LLMessageStringTable::getInstance()->getString("DeclineFriendship");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index a393bbabb2..1d30b69b67 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/message_string_table.cpp b/indra/llmessage/message_string_table.cpp
index 8bcc452e3f..facc8f6cae 100644
--- a/indra/llmessage/message_string_table.cpp
+++ b/indra/llmessage/message_string_table.cpp
@@ -1,91 +1,91 @@
-/**
- * @file message_string_table.cpp
- * @brief static string table for message template
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llerror.h"
-#include "message.h"
-
-inline U32 message_hash_my_string(const char *str)
-{
- U32 retval = 0;
- while (*str++)
- {
- retval += *str;
- retval <<= 1;
- }
- return (retval % MESSAGE_NUMBER_OF_HASH_BUCKETS);
-}
-
-
-
-LLMessageStringTable::LLMessageStringTable()
-: mUsed(0)
-{
- for (U32 i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- mEmpty[i] = true;
- mString[i][0] = 0;
- }
-}
-
-
-LLMessageStringTable::~LLMessageStringTable()
-{ }
-
-
-char* LLMessageStringTable::getString(const char *str)
-{
- U32 hash_value = message_hash_my_string(str);
- while (!mEmpty[hash_value])
- {
- if (!strncmp(str, mString[hash_value], MESSAGE_MAX_STRINGS_LENGTH))
- {
- return mString[hash_value];
- }
- else
- {
- hash_value++;
- hash_value %= MESSAGE_NUMBER_OF_HASH_BUCKETS;
- }
- }
- // not found, so add!
- strncpy(mString[hash_value], str, MESSAGE_MAX_STRINGS_LENGTH); /* Flawfinder: ignore */
- mString[hash_value][MESSAGE_MAX_STRINGS_LENGTH - 1] = 0;
- mEmpty[hash_value] = false;
- mUsed++;
- if (mUsed >= MESSAGE_NUMBER_OF_HASH_BUCKETS - 1)
- {
- U32 i;
- LL_INFOS() << "Dumping string table before crashing on HashTable full!" << LL_ENDL;
- for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
- {
- LL_INFOS() << "Entry #" << i << ": " << mString[i] << LL_ENDL;
- }
- }
- return mString[hash_value];
-}
-
+/**
+ * @file message_string_table.cpp
+ * @brief static string table for message template
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llerror.h"
+#include "message.h"
+
+inline U32 message_hash_my_string(const char *str)
+{
+ U32 retval = 0;
+ while (*str++)
+ {
+ retval += *str;
+ retval <<= 1;
+ }
+ return (retval % MESSAGE_NUMBER_OF_HASH_BUCKETS);
+}
+
+
+
+LLMessageStringTable::LLMessageStringTable()
+: mUsed(0)
+{
+ for (U32 i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ mEmpty[i] = true;
+ mString[i][0] = 0;
+ }
+}
+
+
+LLMessageStringTable::~LLMessageStringTable()
+{ }
+
+
+char* LLMessageStringTable::getString(const char *str)
+{
+ U32 hash_value = message_hash_my_string(str);
+ while (!mEmpty[hash_value])
+ {
+ if (!strncmp(str, mString[hash_value], MESSAGE_MAX_STRINGS_LENGTH))
+ {
+ return mString[hash_value];
+ }
+ else
+ {
+ hash_value++;
+ hash_value %= MESSAGE_NUMBER_OF_HASH_BUCKETS;
+ }
+ }
+ // not found, so add!
+ strncpy(mString[hash_value], str, MESSAGE_MAX_STRINGS_LENGTH); /* Flawfinder: ignore */
+ mString[hash_value][MESSAGE_MAX_STRINGS_LENGTH - 1] = 0;
+ mEmpty[hash_value] = false;
+ mUsed++;
+ if (mUsed >= MESSAGE_NUMBER_OF_HASH_BUCKETS - 1)
+ {
+ U32 i;
+ LL_INFOS() << "Dumping string table before crashing on HashTable full!" << LL_ENDL;
+ for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++)
+ {
+ LL_INFOS() << "Entry #" << i << ": " << mString[i] << LL_ENDL;
+ }
+ }
+ return mString[hash_value];
+}
+
diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp
index 443303e45a..833380632c 100644
--- a/indra/llmessage/net.cpp
+++ b/indra/llmessage/net.cpp
@@ -1,663 +1,663 @@
-/**
- * @file net.cpp
- * @brief Cross-platform routines for sending and receiving packets.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-//#include "net.h"
-
-// system library includes
-#include <stdexcept>
-
-#if LL_WINDOWS
-#include "llwin32headerslean.h"
-#else
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <fcntl.h>
- #include <errno.h>
-#endif
-
-// linden library includes
-#include "llerror.h"
-#include "llhost.h"
-#include "lltimer.h"
-#include "indra_constants.h"
-
-// Globals
-#if LL_WINDOWS
-
-SOCKADDR_IN stDstAddr;
-SOCKADDR_IN stSrcAddr;
-SOCKADDR_IN stLclAddr;
-static WSADATA stWSAData;
-
-#else
-
-struct sockaddr_in stDstAddr;
-struct sockaddr_in stSrcAddr;
-struct sockaddr_in stLclAddr;
-
-#if LL_DARWIN
-#ifndef _SOCKLEN_T
-#define _SOCKLEN_T
-typedef int socklen_t;
-#endif
-#endif
-
-#endif
-
-static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent
-
-const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
-const char* BROADCAST_ADDRESS_STRING = "255.255.255.255";
-
-#if LL_DARWIN
- // macOS returns an error when trying to set these to 400000. Smaller values succeed.
- const int SEND_BUFFER_SIZE = 200000;
- const int RECEIVE_BUFFER_SIZE = 200000;
-#else // LL_DARWIN
- const int SEND_BUFFER_SIZE = 400000;
- const int RECEIVE_BUFFER_SIZE = 400000;
-#endif // LL_DARWIN
-
-// universal functions (cross-platform)
-
-LLHost get_sender()
-{
- return LLHost(stSrcAddr.sin_addr.s_addr, ntohs(stSrcAddr.sin_port));
-}
-
-U32 get_sender_ip(void)
-{
- return stSrcAddr.sin_addr.s_addr;
-}
-
-U32 get_sender_port()
-{
- return ntohs(stSrcAddr.sin_port);
-}
-
-LLHost get_receiving_interface()
-{
- return LLHost(gsnReceivingIFAddr, INVALID_PORT);
-}
-
-U32 get_receiving_interface_ip(void)
-{
- return gsnReceivingIFAddr;
-}
-
-const char* u32_to_ip_string(U32 ip)
-{
- static char buffer[MAXADDRSTR]; /* Flawfinder: ignore */
-
- // Convert the IP address into a string
- in_addr in;
- in.s_addr = ip;
- char* result = inet_ntoa(in);
-
- // NULL indicates error in conversion
- if (result != NULL)
- {
- strncpy( buffer, result, MAXADDRSTR ); /* Flawfinder: ignore */
- buffer[MAXADDRSTR-1] = '\0';
- return buffer;
- }
- else
- {
- return "(bad IP addr)";
- }
-}
-
-
-// Returns ip_string if successful, NULL if not. Copies into ip_string
-char *u32_to_ip_string(U32 ip, char *ip_string)
-{
- char *result;
- in_addr in;
-
- // Convert the IP address into a string
- in.s_addr = ip;
- result = inet_ntoa(in);
-
- // NULL indicates error in conversion
- if (result != NULL)
- {
- //the function signature needs to change to pass in the lengfth of first and last.
- strcpy(ip_string, result); /*Flawfinder: ignore*/
- return ip_string;
- }
- else
- {
- return NULL;
- }
-}
-
-
-// Wrapper for inet_addr()
-U32 ip_string_to_u32(const char* ip_string)
-{
- // *NOTE: Windows doesn't support inet_aton(), so we are using
- // inet_addr(). Unfortunately, INADDR_NONE == INADDR_BROADCAST, so
- // we have to check whether the input is a broadcast address before
- // deciding that @ip_string is invalid.
- //
- // Also, our definition of INVALID_HOST_IP_ADDRESS doesn't allow us to
- // use wildcard addresses. -Ambroff
- U32 ip = inet_addr(ip_string);
- if (ip == INADDR_NONE
- && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0)
- {
- LL_WARNS() << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << LL_ENDL;
- return INVALID_HOST_IP_ADDRESS;
- }
- return ip;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Windows Versions
-//////////////////////////////////////////////////////////////////////////////////////////
-
-#if LL_WINDOWS
-
-S32 start_net(S32& socket_out, int& nPort)
-{
- // Create socket, make non-blocking
- // Init WinSock
- int nRet;
- int hSocket;
-
- int snd_size = SEND_BUFFER_SIZE;
- int rec_size = RECEIVE_BUFFER_SIZE;
- int buff_size = 4;
-
- // Initialize windows specific stuff
- if (WSAStartup(0x0202, &stWSAData))
- {
- S32 err = WSAGetLastError();
- WSACleanup();
- LL_WARNS("AppInit") << "Windows Sockets initialization failed, err " << err << LL_ENDL;
- return 1;
- }
-
- // Get a datagram socket
- hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
- if (hSocket == INVALID_SOCKET)
- {
- S32 err = WSAGetLastError();
- WSACleanup();
- LL_WARNS("AppInit") << "socket() failed, err " << err << LL_ENDL;
- return 2;
- }
-
- // Name the socket (assign the local port number to receive on)
- stLclAddr.sin_family = AF_INET;
- stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- stLclAddr.sin_port = htons(nPort);
-
- S32 attempt_port = nPort;
- LL_DEBUGS("AppInit") << "attempting to connect on port " << attempt_port << LL_ENDL;
- nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
-
- if (nRet == SOCKET_ERROR)
- {
- // If we got an address in use error...
- if (WSAGetLastError() == WSAEADDRINUSE)
- {
- // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX
- for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
- attempt_port <= PORT_DISCOVERY_RANGE_MAX;
- attempt_port++)
- {
- stLclAddr.sin_port = htons(attempt_port);
- LL_DEBUGS("AppInit") << "trying port " << attempt_port << LL_ENDL;
- nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
-
- if (!(nRet == SOCKET_ERROR &&
- WSAGetLastError() == WSAEADDRINUSE))
- {
- break;
- }
- }
-
- if (nRet == SOCKET_ERROR)
- {
- LL_WARNS("AppInit") << "startNet() : Couldn't find available network port." << LL_ENDL;
- // Fail gracefully here in release
- return 3;
- }
- }
- else
- // Some other socket error
- {
- LL_WARNS("AppInit") << llformat("bind() port: %d failed, Err: %d\n", nPort, WSAGetLastError()) << LL_ENDL;
- // Fail gracefully in release.
- return 4;
- }
- }
-
- sockaddr_in socket_address;
- S32 socket_address_size = sizeof(socket_address);
- getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size);
- attempt_port = ntohs(socket_address.sin_port);
-
- LL_INFOS("AppInit") << "connected on port " << attempt_port << LL_ENDL;
- nPort = attempt_port;
-
- // Set socket to be non-blocking
- unsigned long argp = 1;
- nRet = ioctlsocket (hSocket, FIONBIO, &argp);
- if (nRet == SOCKET_ERROR)
- {
- printf("Failed to set socket non-blocking, Err: %d\n",
- WSAGetLastError());
- }
-
- // set a large receive buffer
- nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
- if (nRet)
- {
- LL_INFOS("AppInit") << "Can't set receive buffer size!" << LL_ENDL;
- }
-
- nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
- if (nRet)
- {
- LL_INFOS("AppInit") << "Can't set send buffer size!" << LL_ENDL;
- }
-
- getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
- getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
-
- LL_DEBUGS("AppInit") << "startNet - receive buffer size : " << rec_size << LL_ENDL;
- LL_DEBUGS("AppInit") << "startNet - send buffer size : " << snd_size << LL_ENDL;
-
- // Setup a destination address
- stDstAddr.sin_family = AF_INET;
- stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS;
- stDstAddr.sin_port = htons(nPort);
-
- socket_out = hSocket;
- return 0;
-}
-
-void end_net(S32& socket_out)
-{
- if (socket_out >= 0)
- {
- shutdown(socket_out, SD_BOTH);
- closesocket(socket_out);
- }
- WSACleanup();
-}
-
-S32 receive_packet(int hSocket, char * receiveBuffer)
-{
- // Receives data asynchronously from the socket set by initNet().
- // Returns the number of bytes received into dataReceived, or zero
- // if there is no data received.
- int nRet;
- int addr_size = sizeof(struct sockaddr_in);
-
- nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size);
- if (nRet == SOCKET_ERROR )
- {
- if (WSAEWOULDBLOCK == WSAGetLastError())
- return 0;
- if (WSAECONNRESET == WSAGetLastError())
- return 0;
- LL_INFOS() << "receivePacket() failed, Error: " << WSAGetLastError() << LL_ENDL;
- }
-
- return nRet;
-}
-
-// Returns true on success.
-bool send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort)
-{
- // Sends a packet to the address set in initNet
- //
- int nRet = 0;
- U32 last_error = 0;
-
- stDstAddr.sin_addr.s_addr = recipient;
- stDstAddr.sin_port = htons(nPort);
- do
- {
- nRet = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
-
- if (nRet == SOCKET_ERROR )
- {
- last_error = WSAGetLastError();
- if (last_error != WSAEWOULDBLOCK)
- {
- // WSAECONNRESET - I think this is caused by an ICMP "connection refused"
- // message being sent back from a Linux box... I'm not finding helpful
- // documentation or web pages on this. The question is whether the packet
- // actually got sent or not. Based on the structure of this code, I would
- // assume it is. JNC 2002.01.18
- if (WSAECONNRESET == WSAGetLastError())
- {
- return true;
- }
- LL_INFOS() << "sendto() failed to " << u32_to_ip_string(recipient) << ":" << nPort
- << ", Error " << last_error << LL_ENDL;
- }
- }
- } while ( (nRet == SOCKET_ERROR)
- &&(last_error == WSAEWOULDBLOCK));
-
- return (nRet != SOCKET_ERROR);
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Linux Versions
-//////////////////////////////////////////////////////////////////////////////////////////
-
-#else
-
-// Create socket, make non-blocking
-S32 start_net(S32& socket_out, int& nPort)
-{
- int hSocket, nRet;
- int snd_size = SEND_BUFFER_SIZE;
- int rec_size = RECEIVE_BUFFER_SIZE;
-
- socklen_t buff_size = 4;
-
- // Create socket
- hSocket = socket(AF_INET, SOCK_DGRAM, 0);
- if (hSocket < 0)
- {
- LL_WARNS() << "socket() failed" << LL_ENDL;
- return 1;
- }
-
- if (NET_USE_OS_ASSIGNED_PORT == nPort)
- {
- // Although bind is not required it will tell us which port we were
- // assigned to.
- stLclAddr.sin_family = AF_INET;
- stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- stLclAddr.sin_port = htons(0);
- LL_INFOS() << "attempting to connect on OS assigned port" << LL_ENDL;
- nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
- if (nRet < 0)
- {
- LL_WARNS() << "Failed to bind on an OS assigned port error: "
- << nRet << LL_ENDL;
- }
- else
- {
- sockaddr_in socket_info;
- socklen_t len = sizeof(sockaddr_in);
- int err = getsockname(hSocket, (sockaddr*)&socket_info, &len);
- LL_INFOS() << "Get socket returned: " << err << " length " << len << LL_ENDL;
- nPort = ntohs(socket_info.sin_port);
- LL_INFOS() << "Assigned port: " << nPort << LL_ENDL;
-
- }
- }
- else
- {
- // Name the socket (assign the local port number to receive on)
- stLclAddr.sin_family = AF_INET;
- stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- stLclAddr.sin_port = htons(nPort);
- U32 attempt_port = nPort;
- LL_INFOS() << "attempting to connect on port " << attempt_port << LL_ENDL;
-
- nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
- if (nRet < 0)
- {
- // If we got an address in use error...
- if (errno == EADDRINUSE)
- {
- // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX
- for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
- attempt_port <= PORT_DISCOVERY_RANGE_MAX;
- attempt_port++)
- {
- stLclAddr.sin_port = htons(attempt_port);
- LL_INFOS() << "trying port " << attempt_port << LL_ENDL;
- nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
- if (!((nRet < 0) && (errno == EADDRINUSE)))
- {
- break;
- }
- }
- if (nRet < 0)
- {
- LL_WARNS() << "startNet() : Couldn't find available network port." << LL_ENDL;
- // Fail gracefully in release.
- return 3;
- }
- }
- // Some other socket error
- else
- {
- LL_WARNS() << llformat ("bind() port: %d failed, Err: %s\n", nPort, strerror(errno)) << LL_ENDL;
- // Fail gracefully in release.
- return 4;
- }
- }
- LL_INFOS() << "connected on port " << attempt_port << LL_ENDL;
- nPort = attempt_port;
- }
- // Set socket to be non-blocking
- fcntl(hSocket, F_SETFL, O_NONBLOCK);
- // set a large receive buffer
- nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
- if (nRet)
- {
- LL_INFOS() << "Can't set receive size!" << LL_ENDL;
- }
- nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
- if (nRet)
- {
- LL_INFOS() << "Can't set send size!" << LL_ENDL;
- }
- getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
- getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
-
- LL_INFOS() << "startNet - receive buffer size : " << rec_size << LL_ENDL;
- LL_INFOS() << "startNet - send buffer size : " << snd_size << LL_ENDL;
-
-#if LL_LINUX
- // Turn on recipient address tracking
- {
- int use_pktinfo = 1;
- if( setsockopt( hSocket, SOL_IP, IP_PKTINFO, &use_pktinfo, sizeof(use_pktinfo) ) == -1 )
- {
- LL_WARNS() << "No IP_PKTINFO available" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "IP_PKKTINFO enabled" << LL_ENDL;
- }
- }
-#endif
-
- // Setup a destination address
- char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */
- stDstAddr.sin_family = AF_INET;
- stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr);
- stDstAddr.sin_port = htons(nPort);
-
- socket_out = hSocket;
- return 0;
-}
-
-void end_net(S32& socket_out)
-{
- if (socket_out >= 0)
- {
- close(socket_out);
- }
-}
-
-#if LL_LINUX
-static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, U32 *dstip )
-{
- int size;
- struct iovec iov[1];
- char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
- struct cmsghdr *cmsgptr;
- struct msghdr msg = {0};
-
- iov[0].iov_base = buf;
- iov[0].iov_len = len;
-
- memset(&msg, 0, sizeof msg);
- msg.msg_name = from;
- msg.msg_namelen = *fromlen;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- msg.msg_control = &cmsg;
- msg.msg_controllen = sizeof(cmsg);
-
- size = recvmsg(socket, &msg, 0);
-
- if (size == -1)
- {
- return -1;
- }
-
- for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr))
- {
- if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO )
- {
- in_pktinfo *pktinfo = (in_pktinfo *)CMSG_DATA(cmsgptr);
- if( pktinfo )
- {
- // Two choices. routed and specified. ipi_addr is routed, ipi_spec_dst is
- // routed. We should stay with specified until we go to multiple
- // interfaces
- *dstip = pktinfo->ipi_spec_dst.s_addr;
- }
- }
- }
-
- return size;
-}
-#endif
-
-int receive_packet(int hSocket, char * receiveBuffer)
-{
- // Receives data asynchronously from the socket set by initNet().
- // Returns the number of bytes received into dataReceived, or zero
- // if there is no data received.
- // or -1 if an error occured!
- int nRet;
- socklen_t addr_size = sizeof(struct sockaddr_in);
-
- gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS;
-
-#if LL_LINUX
- nRet = recvfrom_destip(hSocket, receiveBuffer, NET_BUFFER_SIZE, (struct sockaddr*)&stSrcAddr, &addr_size, &gsnReceivingIFAddr);
-#else
- int recv_flags = 0;
- nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, recv_flags, (struct sockaddr*)&stSrcAddr, &addr_size);
-#endif
-
- if (nRet == -1)
- {
- // To maintain consistency with the Windows implementation, return a zero for size on error.
- return 0;
- }
-
- // Uncomment for testing if/when implementing for Mac or Windows:
- // LL_INFOS() << "Received datagram to in addr " << u32_to_ip_string(get_receiving_interface_ip()) << LL_ENDL;
-
- return nRet;
-}
-
-bool send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient, int nPort)
-{
- int ret;
- bool success;
- bool resend;
- S32 send_attempts = 0;
-
- stDstAddr.sin_addr.s_addr = recipient;
- stDstAddr.sin_port = htons(nPort);
-
- do
- {
- ret = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
- send_attempts++;
-
- if (ret >= 0)
- {
- // successful send
- success = true;
- resend = false;
- }
- else
- {
- // send failed, check to see if we should resend
- success = false;
-
- if (errno == EAGAIN)
- {
- // say nothing, just repeat send
- LL_INFOS() << "sendto() reported buffer full, resending (attempt " << send_attempts << ")" << LL_ENDL;
- LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
- resend = true;
- }
- else if (errno == ECONNREFUSED)
- {
- // response to ICMP connection refused message on earlier send
- LL_INFOS() << "sendto() reported connection refused, resending (attempt " << send_attempts << ")" << LL_ENDL;
- LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
- resend = true;
- }
- else
- {
- // some other error
- LL_INFOS() << "sendto() failed: " << errno << ", " << strerror(errno) << LL_ENDL;
- LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
- resend = false;
- }
- }
- }
- while (resend && send_attempts < 3);
-
- if (send_attempts >= 3)
- {
- LL_INFOS() << "sendPacket() bailed out of send!" << LL_ENDL;
- return false;
- }
-
- return success;
-}
-
-#endif
-
-//EOF
+/**
+ * @file net.cpp
+ * @brief Cross-platform routines for sending and receiving packets.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+//#include "net.h"
+
+// system library includes
+#include <stdexcept>
+
+#if LL_WINDOWS
+#include "llwin32headerslean.h"
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif
+
+// linden library includes
+#include "llerror.h"
+#include "llhost.h"
+#include "lltimer.h"
+#include "indra_constants.h"
+
+// Globals
+#if LL_WINDOWS
+
+SOCKADDR_IN stDstAddr;
+SOCKADDR_IN stSrcAddr;
+SOCKADDR_IN stLclAddr;
+static WSADATA stWSAData;
+
+#else
+
+struct sockaddr_in stDstAddr;
+struct sockaddr_in stSrcAddr;
+struct sockaddr_in stLclAddr;
+
+#if LL_DARWIN
+#ifndef _SOCKLEN_T
+#define _SOCKLEN_T
+typedef int socklen_t;
+#endif
+#endif
+
+#endif
+
+static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent
+
+const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1";
+const char* BROADCAST_ADDRESS_STRING = "255.255.255.255";
+
+#if LL_DARWIN
+ // macOS returns an error when trying to set these to 400000. Smaller values succeed.
+ const int SEND_BUFFER_SIZE = 200000;
+ const int RECEIVE_BUFFER_SIZE = 200000;
+#else // LL_DARWIN
+ const int SEND_BUFFER_SIZE = 400000;
+ const int RECEIVE_BUFFER_SIZE = 400000;
+#endif // LL_DARWIN
+
+// universal functions (cross-platform)
+
+LLHost get_sender()
+{
+ return LLHost(stSrcAddr.sin_addr.s_addr, ntohs(stSrcAddr.sin_port));
+}
+
+U32 get_sender_ip(void)
+{
+ return stSrcAddr.sin_addr.s_addr;
+}
+
+U32 get_sender_port()
+{
+ return ntohs(stSrcAddr.sin_port);
+}
+
+LLHost get_receiving_interface()
+{
+ return LLHost(gsnReceivingIFAddr, INVALID_PORT);
+}
+
+U32 get_receiving_interface_ip(void)
+{
+ return gsnReceivingIFAddr;
+}
+
+const char* u32_to_ip_string(U32 ip)
+{
+ static char buffer[MAXADDRSTR]; /* Flawfinder: ignore */
+
+ // Convert the IP address into a string
+ in_addr in;
+ in.s_addr = ip;
+ char* result = inet_ntoa(in);
+
+ // NULL indicates error in conversion
+ if (result != NULL)
+ {
+ strncpy( buffer, result, MAXADDRSTR ); /* Flawfinder: ignore */
+ buffer[MAXADDRSTR-1] = '\0';
+ return buffer;
+ }
+ else
+ {
+ return "(bad IP addr)";
+ }
+}
+
+
+// Returns ip_string if successful, NULL if not. Copies into ip_string
+char *u32_to_ip_string(U32 ip, char *ip_string)
+{
+ char *result;
+ in_addr in;
+
+ // Convert the IP address into a string
+ in.s_addr = ip;
+ result = inet_ntoa(in);
+
+ // NULL indicates error in conversion
+ if (result != NULL)
+ {
+ //the function signature needs to change to pass in the lengfth of first and last.
+ strcpy(ip_string, result); /*Flawfinder: ignore*/
+ return ip_string;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+// Wrapper for inet_addr()
+U32 ip_string_to_u32(const char* ip_string)
+{
+ // *NOTE: Windows doesn't support inet_aton(), so we are using
+ // inet_addr(). Unfortunately, INADDR_NONE == INADDR_BROADCAST, so
+ // we have to check whether the input is a broadcast address before
+ // deciding that @ip_string is invalid.
+ //
+ // Also, our definition of INVALID_HOST_IP_ADDRESS doesn't allow us to
+ // use wildcard addresses. -Ambroff
+ U32 ip = inet_addr(ip_string);
+ if (ip == INADDR_NONE
+ && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0)
+ {
+ LL_WARNS() << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << LL_ENDL;
+ return INVALID_HOST_IP_ADDRESS;
+ }
+ return ip;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Windows Versions
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#if LL_WINDOWS
+
+S32 start_net(S32& socket_out, int& nPort)
+{
+ // Create socket, make non-blocking
+ // Init WinSock
+ int nRet;
+ int hSocket;
+
+ int snd_size = SEND_BUFFER_SIZE;
+ int rec_size = RECEIVE_BUFFER_SIZE;
+ int buff_size = 4;
+
+ // Initialize windows specific stuff
+ if (WSAStartup(0x0202, &stWSAData))
+ {
+ S32 err = WSAGetLastError();
+ WSACleanup();
+ LL_WARNS("AppInit") << "Windows Sockets initialization failed, err " << err << LL_ENDL;
+ return 1;
+ }
+
+ // Get a datagram socket
+ hSocket = (int)socket(AF_INET, SOCK_DGRAM, 0);
+ if (hSocket == INVALID_SOCKET)
+ {
+ S32 err = WSAGetLastError();
+ WSACleanup();
+ LL_WARNS("AppInit") << "socket() failed, err " << err << LL_ENDL;
+ return 2;
+ }
+
+ // Name the socket (assign the local port number to receive on)
+ stLclAddr.sin_family = AF_INET;
+ stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ stLclAddr.sin_port = htons(nPort);
+
+ S32 attempt_port = nPort;
+ LL_DEBUGS("AppInit") << "attempting to connect on port " << attempt_port << LL_ENDL;
+ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+
+ if (nRet == SOCKET_ERROR)
+ {
+ // If we got an address in use error...
+ if (WSAGetLastError() == WSAEADDRINUSE)
+ {
+ // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX
+ for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
+ attempt_port <= PORT_DISCOVERY_RANGE_MAX;
+ attempt_port++)
+ {
+ stLclAddr.sin_port = htons(attempt_port);
+ LL_DEBUGS("AppInit") << "trying port " << attempt_port << LL_ENDL;
+ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+
+ if (!(nRet == SOCKET_ERROR &&
+ WSAGetLastError() == WSAEADDRINUSE))
+ {
+ break;
+ }
+ }
+
+ if (nRet == SOCKET_ERROR)
+ {
+ LL_WARNS("AppInit") << "startNet() : Couldn't find available network port." << LL_ENDL;
+ // Fail gracefully here in release
+ return 3;
+ }
+ }
+ else
+ // Some other socket error
+ {
+ LL_WARNS("AppInit") << llformat("bind() port: %d failed, Err: %d\n", nPort, WSAGetLastError()) << LL_ENDL;
+ // Fail gracefully in release.
+ return 4;
+ }
+ }
+
+ sockaddr_in socket_address;
+ S32 socket_address_size = sizeof(socket_address);
+ getsockname(hSocket, (SOCKADDR*) &socket_address, &socket_address_size);
+ attempt_port = ntohs(socket_address.sin_port);
+
+ LL_INFOS("AppInit") << "connected on port " << attempt_port << LL_ENDL;
+ nPort = attempt_port;
+
+ // Set socket to be non-blocking
+ unsigned long argp = 1;
+ nRet = ioctlsocket (hSocket, FIONBIO, &argp);
+ if (nRet == SOCKET_ERROR)
+ {
+ printf("Failed to set socket non-blocking, Err: %d\n",
+ WSAGetLastError());
+ }
+
+ // set a large receive buffer
+ nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
+ if (nRet)
+ {
+ LL_INFOS("AppInit") << "Can't set receive buffer size!" << LL_ENDL;
+ }
+
+ nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
+ if (nRet)
+ {
+ LL_INFOS("AppInit") << "Can't set send buffer size!" << LL_ENDL;
+ }
+
+ getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
+ getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
+
+ LL_DEBUGS("AppInit") << "startNet - receive buffer size : " << rec_size << LL_ENDL;
+ LL_DEBUGS("AppInit") << "startNet - send buffer size : " << snd_size << LL_ENDL;
+
+ // Setup a destination address
+ stDstAddr.sin_family = AF_INET;
+ stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS;
+ stDstAddr.sin_port = htons(nPort);
+
+ socket_out = hSocket;
+ return 0;
+}
+
+void end_net(S32& socket_out)
+{
+ if (socket_out >= 0)
+ {
+ shutdown(socket_out, SD_BOTH);
+ closesocket(socket_out);
+ }
+ WSACleanup();
+}
+
+S32 receive_packet(int hSocket, char * receiveBuffer)
+{
+ // Receives data asynchronously from the socket set by initNet().
+ // Returns the number of bytes received into dataReceived, or zero
+ // if there is no data received.
+ int nRet;
+ int addr_size = sizeof(struct sockaddr_in);
+
+ nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, 0, (struct sockaddr*)&stSrcAddr, &addr_size);
+ if (nRet == SOCKET_ERROR )
+ {
+ if (WSAEWOULDBLOCK == WSAGetLastError())
+ return 0;
+ if (WSAECONNRESET == WSAGetLastError())
+ return 0;
+ LL_INFOS() << "receivePacket() failed, Error: " << WSAGetLastError() << LL_ENDL;
+ }
+
+ return nRet;
+}
+
+// Returns true on success.
+bool send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort)
+{
+ // Sends a packet to the address set in initNet
+ //
+ int nRet = 0;
+ U32 last_error = 0;
+
+ stDstAddr.sin_addr.s_addr = recipient;
+ stDstAddr.sin_port = htons(nPort);
+ do
+ {
+ nRet = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
+
+ if (nRet == SOCKET_ERROR )
+ {
+ last_error = WSAGetLastError();
+ if (last_error != WSAEWOULDBLOCK)
+ {
+ // WSAECONNRESET - I think this is caused by an ICMP "connection refused"
+ // message being sent back from a Linux box... I'm not finding helpful
+ // documentation or web pages on this. The question is whether the packet
+ // actually got sent or not. Based on the structure of this code, I would
+ // assume it is. JNC 2002.01.18
+ if (WSAECONNRESET == WSAGetLastError())
+ {
+ return true;
+ }
+ LL_INFOS() << "sendto() failed to " << u32_to_ip_string(recipient) << ":" << nPort
+ << ", Error " << last_error << LL_ENDL;
+ }
+ }
+ } while ( (nRet == SOCKET_ERROR)
+ &&(last_error == WSAEWOULDBLOCK));
+
+ return (nRet != SOCKET_ERROR);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Linux Versions
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#else
+
+// Create socket, make non-blocking
+S32 start_net(S32& socket_out, int& nPort)
+{
+ int hSocket, nRet;
+ int snd_size = SEND_BUFFER_SIZE;
+ int rec_size = RECEIVE_BUFFER_SIZE;
+
+ socklen_t buff_size = 4;
+
+ // Create socket
+ hSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (hSocket < 0)
+ {
+ LL_WARNS() << "socket() failed" << LL_ENDL;
+ return 1;
+ }
+
+ if (NET_USE_OS_ASSIGNED_PORT == nPort)
+ {
+ // Although bind is not required it will tell us which port we were
+ // assigned to.
+ stLclAddr.sin_family = AF_INET;
+ stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ stLclAddr.sin_port = htons(0);
+ LL_INFOS() << "attempting to connect on OS assigned port" << LL_ENDL;
+ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+ if (nRet < 0)
+ {
+ LL_WARNS() << "Failed to bind on an OS assigned port error: "
+ << nRet << LL_ENDL;
+ }
+ else
+ {
+ sockaddr_in socket_info;
+ socklen_t len = sizeof(sockaddr_in);
+ int err = getsockname(hSocket, (sockaddr*)&socket_info, &len);
+ LL_INFOS() << "Get socket returned: " << err << " length " << len << LL_ENDL;
+ nPort = ntohs(socket_info.sin_port);
+ LL_INFOS() << "Assigned port: " << nPort << LL_ENDL;
+
+ }
+ }
+ else
+ {
+ // Name the socket (assign the local port number to receive on)
+ stLclAddr.sin_family = AF_INET;
+ stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ stLclAddr.sin_port = htons(nPort);
+ U32 attempt_port = nPort;
+ LL_INFOS() << "attempting to connect on port " << attempt_port << LL_ENDL;
+
+ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+ if (nRet < 0)
+ {
+ // If we got an address in use error...
+ if (errno == EADDRINUSE)
+ {
+ // Try all ports from PORT_DISCOVERY_RANGE_MIN to PORT_DISCOVERY_RANGE_MAX
+ for(attempt_port = PORT_DISCOVERY_RANGE_MIN;
+ attempt_port <= PORT_DISCOVERY_RANGE_MAX;
+ attempt_port++)
+ {
+ stLclAddr.sin_port = htons(attempt_port);
+ LL_INFOS() << "trying port " << attempt_port << LL_ENDL;
+ nRet = bind(hSocket, (struct sockaddr*) &stLclAddr, sizeof(stLclAddr));
+ if (!((nRet < 0) && (errno == EADDRINUSE)))
+ {
+ break;
+ }
+ }
+ if (nRet < 0)
+ {
+ LL_WARNS() << "startNet() : Couldn't find available network port." << LL_ENDL;
+ // Fail gracefully in release.
+ return 3;
+ }
+ }
+ // Some other socket error
+ else
+ {
+ LL_WARNS() << llformat ("bind() port: %d failed, Err: %s\n", nPort, strerror(errno)) << LL_ENDL;
+ // Fail gracefully in release.
+ return 4;
+ }
+ }
+ LL_INFOS() << "connected on port " << attempt_port << LL_ENDL;
+ nPort = attempt_port;
+ }
+ // Set socket to be non-blocking
+ fcntl(hSocket, F_SETFL, O_NONBLOCK);
+ // set a large receive buffer
+ nRet = setsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, buff_size);
+ if (nRet)
+ {
+ LL_INFOS() << "Can't set receive size!" << LL_ENDL;
+ }
+ nRet = setsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, buff_size);
+ if (nRet)
+ {
+ LL_INFOS() << "Can't set send size!" << LL_ENDL;
+ }
+ getsockopt(hSocket, SOL_SOCKET, SO_RCVBUF, (char *)&rec_size, &buff_size);
+ getsockopt(hSocket, SOL_SOCKET, SO_SNDBUF, (char *)&snd_size, &buff_size);
+
+ LL_INFOS() << "startNet - receive buffer size : " << rec_size << LL_ENDL;
+ LL_INFOS() << "startNet - send buffer size : " << snd_size << LL_ENDL;
+
+#if LL_LINUX
+ // Turn on recipient address tracking
+ {
+ int use_pktinfo = 1;
+ if( setsockopt( hSocket, SOL_IP, IP_PKTINFO, &use_pktinfo, sizeof(use_pktinfo) ) == -1 )
+ {
+ LL_WARNS() << "No IP_PKTINFO available" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "IP_PKKTINFO enabled" << LL_ENDL;
+ }
+ }
+#endif
+
+ // Setup a destination address
+ char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */
+ stDstAddr.sin_family = AF_INET;
+ stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr);
+ stDstAddr.sin_port = htons(nPort);
+
+ socket_out = hSocket;
+ return 0;
+}
+
+void end_net(S32& socket_out)
+{
+ if (socket_out >= 0)
+ {
+ close(socket_out);
+ }
+}
+
+#if LL_LINUX
+static int recvfrom_destip( int socket, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, U32 *dstip )
+{
+ int size;
+ struct iovec iov[1];
+ char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct cmsghdr *cmsgptr;
+ struct msghdr msg = {0};
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = len;
+
+ memset(&msg, 0, sizeof msg);
+ msg.msg_name = from;
+ msg.msg_namelen = *fromlen;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &cmsg;
+ msg.msg_controllen = sizeof(cmsg);
+
+ size = recvmsg(socket, &msg, 0);
+
+ if (size == -1)
+ {
+ return -1;
+ }
+
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR( &msg, cmsgptr))
+ {
+ if( cmsgptr->cmsg_level == SOL_IP && cmsgptr->cmsg_type == IP_PKTINFO )
+ {
+ in_pktinfo *pktinfo = (in_pktinfo *)CMSG_DATA(cmsgptr);
+ if( pktinfo )
+ {
+ // Two choices. routed and specified. ipi_addr is routed, ipi_spec_dst is
+ // routed. We should stay with specified until we go to multiple
+ // interfaces
+ *dstip = pktinfo->ipi_spec_dst.s_addr;
+ }
+ }
+ }
+
+ return size;
+}
+#endif
+
+int receive_packet(int hSocket, char * receiveBuffer)
+{
+ // Receives data asynchronously from the socket set by initNet().
+ // Returns the number of bytes received into dataReceived, or zero
+ // if there is no data received.
+ // or -1 if an error occured!
+ int nRet;
+ socklen_t addr_size = sizeof(struct sockaddr_in);
+
+ gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS;
+
+#if LL_LINUX
+ nRet = recvfrom_destip(hSocket, receiveBuffer, NET_BUFFER_SIZE, (struct sockaddr*)&stSrcAddr, &addr_size, &gsnReceivingIFAddr);
+#else
+ int recv_flags = 0;
+ nRet = recvfrom(hSocket, receiveBuffer, NET_BUFFER_SIZE, recv_flags, (struct sockaddr*)&stSrcAddr, &addr_size);
+#endif
+
+ if (nRet == -1)
+ {
+ // To maintain consistency with the Windows implementation, return a zero for size on error.
+ return 0;
+ }
+
+ // Uncomment for testing if/when implementing for Mac or Windows:
+ // LL_INFOS() << "Received datagram to in addr " << u32_to_ip_string(get_receiving_interface_ip()) << LL_ENDL;
+
+ return nRet;
+}
+
+bool send_packet(int hSocket, const char * sendBuffer, int size, U32 recipient, int nPort)
+{
+ int ret;
+ bool success;
+ bool resend;
+ S32 send_attempts = 0;
+
+ stDstAddr.sin_addr.s_addr = recipient;
+ stDstAddr.sin_port = htons(nPort);
+
+ do
+ {
+ ret = sendto(hSocket, sendBuffer, size, 0, (struct sockaddr*)&stDstAddr, sizeof(stDstAddr));
+ send_attempts++;
+
+ if (ret >= 0)
+ {
+ // successful send
+ success = true;
+ resend = false;
+ }
+ else
+ {
+ // send failed, check to see if we should resend
+ success = false;
+
+ if (errno == EAGAIN)
+ {
+ // say nothing, just repeat send
+ LL_INFOS() << "sendto() reported buffer full, resending (attempt " << send_attempts << ")" << LL_ENDL;
+ LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
+ resend = true;
+ }
+ else if (errno == ECONNREFUSED)
+ {
+ // response to ICMP connection refused message on earlier send
+ LL_INFOS() << "sendto() reported connection refused, resending (attempt " << send_attempts << ")" << LL_ENDL;
+ LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
+ resend = true;
+ }
+ else
+ {
+ // some other error
+ LL_INFOS() << "sendto() failed: " << errno << ", " << strerror(errno) << LL_ENDL;
+ LL_INFOS() << inet_ntoa(stDstAddr.sin_addr) << ":" << nPort << LL_ENDL;
+ resend = false;
+ }
+ }
+ }
+ while (resend && send_attempts < 3);
+
+ if (send_attempts >= 3)
+ {
+ LL_INFOS() << "sendPacket() bailed out of send!" << LL_ENDL;
+ return false;
+ }
+
+ return success;
+}
+
+#endif
+
+//EOF
diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h
index a873026fa4..b6040b0a35 100644
--- a/indra/llmessage/net.h
+++ b/indra/llmessage/net.h
@@ -1,74 +1,74 @@
-/**
- * @file net.h
- * @brief Cross platform UDP network code.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_NET_H
-#define LL_NET_H
-
-class LLTimer;
-class LLHost;
-
-#define NET_BUFFER_SIZE (0x2000)
-
-// Request a free local port from the operating system
-#define NET_USE_OS_ASSIGNED_PORT 0
-
-// Returns 0 on success, non-zero on error.
-// Sets socket handler/descriptor, changes nPort if port requested is unavailable.
-S32 start_net(S32& socket_out, int& nPort);
-void end_net(S32& socket_out);
-
-// returns size of packet or -1 in case of error
-S32 receive_packet(int hSocket, char * receiveBuffer);
-
-bool send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort); // Returns true on success.
-
-//void get_sender(char * tmp);
-LLHost get_sender();
-U32 get_sender_port();
-U32 get_sender_ip(void);
-LLHost get_receiving_interface();
-U32 get_receiving_interface_ip(void);
-
-const char* u32_to_ip_string(U32 ip); // Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls
-char* u32_to_ip_string(U32 ip, char *ip_string); // NULL on failure, ip_string on success, you must allocate at least MAXADDRSTR chars
-U32 ip_string_to_u32(const char* ip_string); // Wrapper for inet_addr()
-
-extern const char* LOOPBACK_ADDRESS_STRING;
-extern const char* BROADCAST_ADDRESS_STRING;
-
-
-// useful MTU consts
-
-const S32 MTUBYTES = 1200; // 1500 = standard Ethernet MTU
-const S32 ETHERNET_MTU_BYTES = 1500;
-const S32 MTUBITS = MTUBYTES*8;
-const S32 MTUU32S = MTUBITS/32;
-
-// For automatic port discovery when running multiple viewers on one host
-const U32 PORT_DISCOVERY_RANGE_MIN = 13000;
-const U32 PORT_DISCOVERY_RANGE_MAX = PORT_DISCOVERY_RANGE_MIN + 50;
-
-#endif
+/**
+ * @file net.h
+ * @brief Cross platform UDP network code.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_NET_H
+#define LL_NET_H
+
+class LLTimer;
+class LLHost;
+
+#define NET_BUFFER_SIZE (0x2000)
+
+// Request a free local port from the operating system
+#define NET_USE_OS_ASSIGNED_PORT 0
+
+// Returns 0 on success, non-zero on error.
+// Sets socket handler/descriptor, changes nPort if port requested is unavailable.
+S32 start_net(S32& socket_out, int& nPort);
+void end_net(S32& socket_out);
+
+// returns size of packet or -1 in case of error
+S32 receive_packet(int hSocket, char * receiveBuffer);
+
+bool send_packet(int hSocket, const char *sendBuffer, int size, U32 recipient, int nPort); // Returns true on success.
+
+//void get_sender(char * tmp);
+LLHost get_sender();
+U32 get_sender_port();
+U32 get_sender_ip(void);
+LLHost get_receiving_interface();
+U32 get_receiving_interface_ip(void);
+
+const char* u32_to_ip_string(U32 ip); // Returns pointer to internal string buffer, "(bad IP addr)" on failure, cannot nest calls
+char* u32_to_ip_string(U32 ip, char *ip_string); // NULL on failure, ip_string on success, you must allocate at least MAXADDRSTR chars
+U32 ip_string_to_u32(const char* ip_string); // Wrapper for inet_addr()
+
+extern const char* LOOPBACK_ADDRESS_STRING;
+extern const char* BROADCAST_ADDRESS_STRING;
+
+
+// useful MTU consts
+
+const S32 MTUBYTES = 1200; // 1500 = standard Ethernet MTU
+const S32 ETHERNET_MTU_BYTES = 1500;
+const S32 MTUBITS = MTUBYTES*8;
+const S32 MTUU32S = MTUBITS/32;
+
+// For automatic port discovery when running multiple viewers on one host
+const U32 PORT_DISCOVERY_RANGE_MIN = 13000;
+const U32 PORT_DISCOVERY_RANGE_MAX = PORT_DISCOVERY_RANGE_MIN + 50;
+
+#endif
diff --git a/indra/llmessage/partsyspacket.cpp b/indra/llmessage/partsyspacket.cpp
index 846b11a5d0..f0af91e7a3 100644
--- a/indra/llmessage/partsyspacket.cpp
+++ b/indra/llmessage/partsyspacket.cpp
@@ -1,1297 +1,1297 @@
-/**
- * @file partsyspacket.cpp
- * @brief Object for packing particle system initialization parameters
- * before sending them over the network.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "partsyspacket.h"
-#include "indra_constants.h"
-
-// this function is global
-void gSetInitDataDefaults(LLPartInitData *setMe)
-{
- U32 i;
-
- //for(i = 0; i < 18; i++)
- //{
- // setMe->k[i] = 0.0f;
- //}
-
- //setMe->kill_p[0] = setMe->kill_p[1] = setMe->kill_p[2] = 0.0f;
- //setMe->kill_p[3] = -0.2f; // time parameter, die when t= 5.0f
- //setMe->kill_p[4] = 1.0f;
- //setMe->kill_p[5] = -0.5f; // or radius == 2 (contracting)
-
- //setMe->bounce_p[0] = setMe->bounce_p[1] =
- // setMe->bounce_p[2] = setMe->bounce_p[3] = 0.0f;
- //setMe->bounce_p[4] = 1.0f;
-
- setMe->bounce_b = 1.0f;
- // i just changed the meaning of bounce_b
- // its now the attenuation from revlecting your velocity across the normal
- // set by bounce_p
-
- //setMe->pos_ranges[0] = setMe->pos_ranges[2] = setMe->pos_ranges[4] = -1.0f;
- //setMe->pos_ranges[1] = setMe->pos_ranges[3] = setMe->pos_ranges[5] = 1.0f;
-
- //setMe->vel_ranges[0] = setMe->vel_ranges[2] = setMe->vel_ranges[4] = -1.0f;
- //setMe->vel_ranges[1] = setMe->vel_ranges[3] = setMe->vel_ranges[5] = 1.0f;
-
- for(i = 0; i < 3; i++)
- {
- setMe->diffEqAlpha[i] = 0.0f;
- setMe->diffEqScale[i] = 0.0f;
- }
-
- setMe->scale_range[0] = 1.00f;
- setMe->scale_range[1] = 5.00f;
- setMe->scale_range[2] = setMe->scale_range[3] = 0.0f;
-
- setMe->alpha_range[0] = setMe->alpha_range[1] = 1.0f;
- setMe->alpha_range[2] = setMe->alpha_range[3] = 0.0f;
-
- setMe->vel_offset[0] = 0.0f;
- setMe->vel_offset[1] = 0.0f;
- setMe->vel_offset[2] = 0.0f;
-
- // start dropping particles when I'm more then one sim away
- setMe->mDistBeginFadeout = 256.0f;
- setMe->mDistEndFadeout = 1.414f * 512.0f;
- // stop displaying particles when I'm more then two sim diagonals away
-
- setMe->mImageUuid = IMG_SHOT;
-
- for(i = 0; i < 8; i++)
- {
- setMe->mFlags[i] = 0x00;
- }
-
- setMe->createMe = true;
-
- setMe->maxParticles = 25;
- setMe->initialParticles = 25;
-
- //These defaults are for an explosion - a short lived set of debris affected by gravity.
- //Action flags default to PART_SYS_AFFECTED_BY_WIND + PART_SYS_AFFECTED_BY_GRAVITY + PART_SYS_DISTANCE_DEATH
- setMe->mFlags[PART_SYS_ACTION_BYTE] = PART_SYS_AFFECTED_BY_WIND | PART_SYS_AFFECTED_BY_GRAVITY | PART_SYS_DISTANCE_DEATH;
- setMe->mFlags[PART_SYS_KILL_BYTE] = PART_SYS_DISTANCE_DEATH + PART_SYS_TIME_DEATH;
-
- setMe->killPlaneNormal[0] = 0.0f;setMe->killPlaneNormal[1] = 0.0f;setMe->killPlaneNormal[2] = 1.0f; //Straight up
- setMe->killPlaneZ = 0.0f; //get local ground z as an approximation if turn on PART_SYS_KILL_PLANE
- setMe->bouncePlaneNormal[0] = 0.0f;setMe->bouncePlaneNormal[1] = 0.0f;setMe->bouncePlaneNormal[2] = 1.0f; //Straight up
- setMe->bouncePlaneZ = 0.0f; //get local ground z as an approximation if turn on PART_SYS_BOUNCE
- setMe->spawnRange = 1.0f;
- setMe->spawnFrequency = 0.0f; //Create the instant one dies
- setMe->spawnFreqencyRange = 0.0f;
- setMe->spawnDirection[0] = 0.0f;setMe->spawnDirection[1] = 0.0f;setMe->spawnDirection[2] = 1.0f; //Straight up
- setMe->spawnDirectionRange = 1.0f; //global scattering
- setMe->spawnVelocity = 0.75f;
- setMe->spawnVelocityRange = 0.25f; //velocity +/- 0.25
- setMe->speedLimit = 1.0f;
-
- setMe->windWeight = 0.5f; //0.0f means looks like a heavy object (if gravity is on), 1.0f means light and fluffy
- setMe->currentGravity[0] = 0.0f;setMe->currentGravity[1] = 0.0f;setMe->currentGravity[2] = -9.81f;
- //This has to be constant to allow for compression
-
- setMe->gravityWeight = 0.5f; //0.0f means boyed by air, 1.0f means it's a lead weight
- setMe->globalLifetime = 0.0f; //Arbitrary, but default is no global die, so doesn't matter
- setMe->individualLifetime = 5.0f;
- setMe->individualLifetimeRange = 1.0f; //Particles last 5 secs +/- 1
- setMe->alphaDecay = 1.0f; //normal alpha fadeout
- setMe->scaleDecay = 0.0f; //no scale decay
- setMe->distanceDeath = 10.0f; //die if hit unit radius
- setMe->dampMotionFactor = 0.0f;
-
- setMe->windDiffusionFactor[0] = 0.0f;
- setMe->windDiffusionFactor[1] = 0.0f;
- setMe->windDiffusionFactor[2] = 0.0f;
-}
-
-LLPartSysCompressedPacket::LLPartSysCompressedPacket()
-{
- // default constructor for mDefaults called implicitly/automatically here
- for(int i = 0; i < MAX_PART_SYS_PACKET_SIZE; i++)
- {
- mData[i] = '\0';
- }
-
- mNumBytes = 0;
-
- gSetInitDataDefaults(&mDefaults);
-}
-
-LLPartSysCompressedPacket::~LLPartSysCompressedPacket()
-{
- // no dynamic data is stored by this class, do nothing.
-}
-
-void LLPartSysCompressedPacket::writeFlagByte(LLPartInitData *in)
-{
- mData[0] = mData[1] = mData[2] = '\0';
-
- U32 i;
- //for(i = 1; i < 18; i++) {
- // if(in->k[i] != mDefaults.k[i])
- // {
- // mData[0] |= PART_SYS_K_MASK;
- // break;
- // }
- //}
-
- if(in->killPlaneZ != mDefaults.killPlaneZ ||
- in->killPlaneNormal[0] != mDefaults.killPlaneNormal[0] ||
- in->killPlaneNormal[1] != mDefaults.killPlaneNormal[1] ||
- in->killPlaneNormal[2] != mDefaults.killPlaneNormal[2] ||
- in->distanceDeath != mDefaults.distanceDeath)
- {
- mData[0] |= PART_SYS_KILL_P_MASK;
- }
-
-
-
- if(in->bouncePlaneZ != mDefaults.bouncePlaneZ ||
- in->bouncePlaneNormal[0] != mDefaults.bouncePlaneNormal[0] ||
- in->bouncePlaneNormal[1] != mDefaults.bouncePlaneNormal[1] ||
- in->bouncePlaneNormal[2] != mDefaults.bouncePlaneNormal[2])
- {
- mData[0] |= PART_SYS_BOUNCE_P_MASK;
- }
-
- if(in->bounce_b != mDefaults.bounce_b)
- {
- mData[0] |= PART_SYS_BOUNCE_B_MASK;
- }
-
-
- //if(in->pos_ranges[0] != mDefaults.pos_ranges[0] || in->pos_ranges[1] != mDefaults.pos_ranges[1] ||
- // in->pos_ranges[2] != mDefaults.pos_ranges[2] || in->pos_ranges[3] != mDefaults.pos_ranges[3] ||
- // in->pos_ranges[4] != mDefaults.pos_ranges[4] || in->pos_ranges[5] != mDefaults.pos_ranges[5])
- //{
- // mData[0] |= PART_SYS_POS_RANGES_MASK;
- //}
-
- //if(in->vel_ranges[0] != mDefaults.vel_ranges[0] || in->vel_ranges[1] != mDefaults.vel_ranges[1] ||
- // in->vel_ranges[2] != mDefaults.vel_ranges[2] || in->vel_ranges[3] != mDefaults.vel_ranges[3] ||
- // in->vel_ranges[4] != mDefaults.vel_ranges[4] || in->vel_ranges[5] != mDefaults.vel_ranges[5])
- //{
-// mData[0] |= PART_SYS_VEL_RANGES_MASK;
- //}
-
-
- if(in->diffEqAlpha[0] != mDefaults.diffEqAlpha[0] ||
- in->diffEqAlpha[1] != mDefaults.diffEqAlpha[1] ||
- in->diffEqAlpha[2] != mDefaults.diffEqAlpha[2] ||
- in->diffEqScale[0] != mDefaults.diffEqScale[0] ||
- in->diffEqScale[1] != mDefaults.diffEqScale[1] ||
- in->diffEqScale[2] != mDefaults.diffEqScale[2])
- {
- mData[0] |= PART_SYS_ALPHA_SCALE_DIFF_MASK;
- }
-
-
- if(in->scale_range[0] != mDefaults.scale_range[0] ||
- in->scale_range[1] != mDefaults.scale_range[1] ||
- in->scale_range[2] != mDefaults.scale_range[2] ||
- in->scale_range[3] != mDefaults.scale_range[3])
- {
- mData[0] |= PART_SYS_SCALE_RANGE_MASK;
- }
-
-
- if(in->alpha_range[0] != mDefaults.alpha_range[0] ||
- in->alpha_range[1] != mDefaults.alpha_range[1] ||
- in->alpha_range[2] != mDefaults.alpha_range[2] ||
- in->alpha_range[3] != mDefaults.alpha_range[3])
- {
- mData[2] |= PART_SYS_BYTE_3_ALPHA_MASK;
- }
-
- if(in->vel_offset[0] != mDefaults.vel_offset[0] ||
- in->vel_offset[1] != mDefaults.vel_offset[1] ||
- in->vel_offset[2] != mDefaults.vel_offset[2])
- {
- mData[0] |= PART_SYS_VEL_OFFSET_MASK;
- }
-
-
- if(in->mImageUuid != mDefaults.mImageUuid)
- {
- mData[0] |= PART_SYS_M_IMAGE_UUID_MASK;
- }
-
- for( i = 0; i < 8; i++)
- {
- if(in->mFlags[i])
- {
- mData[1] |= 1<<i;
-// llprintline("Flag \"%x\" gets byte \"%x\"\n", i<<i, in->mFlags[i]);
- }
- }
-
-
- if(in->spawnRange != mDefaults.spawnRange ||
- in->spawnFrequency != mDefaults.spawnFrequency ||
- in->spawnFreqencyRange != mDefaults.spawnFreqencyRange ||
- in->spawnDirection[0] != mDefaults.spawnDirection[0] ||
- in->spawnDirection[1] != mDefaults.spawnDirection[1] ||
- in->spawnDirection[2] != mDefaults.spawnDirection[2] ||
- in->spawnDirectionRange != mDefaults.spawnDirectionRange ||
- in->spawnVelocity != mDefaults.spawnVelocity ||
- in->spawnVelocityRange != mDefaults.spawnVelocityRange)
- {
- mData[3] |= PART_SYS_BYTE_SPAWN_MASK;
- }
-
-
- if(in->windWeight != mDefaults.windWeight ||
- in->currentGravity[0] != mDefaults.currentGravity[0] ||
- in->currentGravity[1] != mDefaults.currentGravity[1] ||
- in->currentGravity[2] != mDefaults.currentGravity[2] ||
- in->gravityWeight != mDefaults.gravityWeight)
- {
- mData[3] |= PART_SYS_BYTE_ENVIRONMENT_MASK;
- }
-
-
- if(in->globalLifetime != mDefaults.globalLifetime ||
- in->individualLifetime != mDefaults.individualLifetime ||
- in->individualLifetimeRange != mDefaults.individualLifetimeRange)
- {
- mData[3] |= PART_SYS_BYTE_LIFESPAN_MASK;
- }
-
-
- if(in->speedLimit != mDefaults.speedLimit ||
- in->alphaDecay != mDefaults.alphaDecay ||
- in->scaleDecay != mDefaults.scaleDecay ||
- in->dampMotionFactor != mDefaults.dampMotionFactor)
- {
- mData[3] |= PART_SYS_BYTE_DECAY_DAMP_MASK;
- }
-
- if(in->windDiffusionFactor[0] != mDefaults.windDiffusionFactor[0] ||
- in->windDiffusionFactor[1] != mDefaults.windDiffusionFactor[1] ||
- in->windDiffusionFactor[2] != mDefaults.windDiffusionFactor[2])
- {
- mData[3] |= PART_SYS_BYTE_WIND_DIFF_MASK;
- }
-}
-
-F32 floatFromTwoBytes(S8 bMant, S8 bExp)
-{
- F32 result = bMant;
- while(bExp > 0)
- {
- result *= 2.0f;
- bExp--;
- }
- while(bExp < 0)
- {
- result *= 0.5f;
- bExp++;
- }
- return result;
-}
-
-void twoBytesFromFloat(F32 fIn, S8 &bMant, S8 &bExp)
-{
- bExp = 0;
- if(fIn > 127.0f)
- {
- fIn = 127.0f;
- }
- if(fIn < -127.0f)
- {
- fIn = -127.0f;
- }
- while(fIn < 64 && fIn > -64 && bExp > -127)
- {
- fIn *= 2.0f;
- bExp--;
- }
- while((fIn > 128 || fIn < -128) && bExp < 127)
- {
- fIn *= 0.5f;
- bExp++;
- }
- bMant = (S8)fIn;
-}
-
-
-
-/*
-U32 LLPartSysCompressedPacket::writeK(LLPartInitData *in, U32 startByte)
-{
- U32 i, kFlag, i_mod_eight;
- S8 bMant, bExp;
-
- kFlag = startByte;
-
- startByte += 3; // 3 bytes contain enough room for 18 flag bits
- mData[kFlag] = 0x00;
-// llprintline("In the writeK\n");
-
- i_mod_eight = 0;
- for(i = 0; i < 18; i++)
- {
- if(in->k[i] != mDefaults.k[i])
- {
-
- mData[kFlag] |= 1<<i_mod_eight;
- twoBytesFromFloat(in->k[i], bMant, bExp);
-
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- i_mod_eight++;
- while(i_mod_eight >= 8)
- {
- kFlag++;
- i_mod_eight -= 8;
- }
- }
-
- return startByte;
-}*/
-
-U32 LLPartSysCompressedPacket::writeKill_p(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
-
- twoBytesFromFloat(in->killPlaneNormal[0], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->killPlaneNormal[1], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->killPlaneNormal[2], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->killPlaneZ, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->distanceDeath, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeBounce_p(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
-
- twoBytesFromFloat(in->bouncePlaneNormal[0], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->bouncePlaneNormal[1], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->bouncePlaneNormal[2], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
-
- twoBytesFromFloat(in->bouncePlaneZ, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeBounce_b(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
- twoBytesFromFloat(in->bounce_b, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- return startByte;
-}
-
-//U32 LLPartSysCompressedPacket::writePos_ranges(LLPartInitData *in, U32 startByte)
-//{
-// S8 tmp;
-// int i;
-// for(i = 0; i < 6; i++)
-// {
-// tmp = (S8) in->pos_ranges[i]; // float to int conversion (keep the sign)
-// mData[startByte++] = (U8)tmp; // signed to unsigned typecast
-// }
-// return startByte;
-//}
-
-//U32 LLPartSysCompressedPacket::writeVel_ranges(LLPartInitData *in, U32 startByte)
-//{
-// S8 tmp;
-// int i;
-// for(i = 0; i < 6; i++)
-// {
-// tmp = (S8) in->vel_ranges[i]; // float to int conversion (keep the sign)
-// mData[startByte++] = (U8)tmp; // signed to unsigned typecast
-// }
-// return startByte;
-//}
-
-U32 LLPartSysCompressedPacket::writeAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
- for(i = 0; i < 3; i++)
- {
- twoBytesFromFloat(in->diffEqAlpha[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- for(i = 0; i < 3; i++)
- {
- twoBytesFromFloat(in->diffEqScale[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeScale_range(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
- for(i = 0; i < 4; i++)
- {
- twoBytesFromFloat(in->scale_range[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- return startByte;
-}
-
-
-U32 LLPartSysCompressedPacket::writeAlpha_range(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
- for(i = 0; i < 4; i++)
- {
- twoBytesFromFloat(in->alpha_range[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeVelocityOffset(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
- for(i = 0; i < 3; i++)
- {
- twoBytesFromFloat(in->vel_offset[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeUUID(LLPartInitData *in, U32 startByte)
-{
- U8 * bufPtr = mData + startByte;
- if(in->mImageUuid == IMG_SHOT) {
- mData[startByte++] = 0x01;
- return startByte;
- }
-
- if(in->mImageUuid == IMG_SPARK) {
- mData[startByte++] = 0x02;
- return startByte;
- }
-
-
- if(in->mImageUuid == IMG_BIG_EXPLOSION_1) {
- mData[startByte++] = 0x03;
- return startByte;
- }
-
- if(in->mImageUuid == IMG_BIG_EXPLOSION_2) {
- mData[startByte++] = 0x04;
- return startByte;
- }
-
-
- if(in->mImageUuid == IMG_SMOKE_POOF) {
- mData[startByte++] = 0x05;
- return startByte;
- }
-
- if(in->mImageUuid == IMG_FIRE) {
- mData[startByte++] = 0x06;
- return startByte;
- }
-
-
- if(in->mImageUuid == IMG_EXPLOSION) {
- mData[startByte++] = 0x07;
- return startByte;
- }
-
- if(in->mImageUuid == IMG_EXPLOSION_2) {
- mData[startByte++] = 0x08;
- return startByte;
- }
-
-
- if(in->mImageUuid == IMG_EXPLOSION_3) {
- mData[startByte++] = 0x09;
- return startByte;
- }
-
- if(in->mImageUuid == IMG_EXPLOSION_4) {
- mData[startByte++] = 0x0A;
- return startByte;
- }
-
- mData[startByte++] = 0x00; // flag for "read whole UUID"
-
- memcpy(bufPtr, in->mImageUuid.mData, 16); /* Flawfinder: ignore */
- return (startByte+16);
-}
-
-U32 LLPartSysCompressedPacket::writeSpawn(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
-
- twoBytesFromFloat(in->spawnRange, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->spawnFrequency, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->spawnFreqencyRange, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
-
-
- for(i = 0; i < 3; i++)
- {
- twoBytesFromFloat(in->spawnDirection[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
-
- twoBytesFromFloat(in->spawnDirectionRange, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->spawnVelocity, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- twoBytesFromFloat(in->spawnVelocityRange, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeEnvironment(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
- int i;
-
- twoBytesFromFloat(in->windWeight, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- for(i = 0; i < 3; i++)
- {
- twoBytesFromFloat(in->currentGravity[i], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- }
-
- twoBytesFromFloat(in->gravityWeight, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeLifespan(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
-
- twoBytesFromFloat(in->globalLifetime, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->individualLifetime, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->individualLifetimeRange, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-
-U32 LLPartSysCompressedPacket::writeDecayDamp(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
-
- twoBytesFromFloat(in->speedLimit, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->alphaDecay, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->scaleDecay, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->dampMotionFactor, bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::writeWindDiffusionFactor(LLPartInitData *in, U32 startByte)
-{
- S8 bExp, bMant;
-
- twoBytesFromFloat(in->windDiffusionFactor[0], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->windDiffusionFactor[1], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- twoBytesFromFloat(in->windDiffusionFactor[2], bMant, bExp);
- mData[startByte++] = bMant;
- mData[startByte++] = bExp;
-
- return startByte;
-}
-
-
-
-
-
-
-/*
-U32 LLPartSysCompressedPacket::readK(LLPartInitData *in, U32 startByte)
-{
- U32 i, i_mod_eight, kFlag;
- S8 bMant, bExp; // 1 bytes mantissa and exponent for a float
- kFlag = startByte;
- startByte += 3; // 3 bytes has enough room for 18 bits
-
- i_mod_eight = 0;
- for(i = 0; i < 18; i++)
- {
- if(mData[kFlag]&(1<<i_mod_eight))
- {
-
-
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
-
-
- in->k[i] = floatFromTwoBytes(bMant, bExp); // much tighter platform-independent
- // way to ship floats
-
- }
- i_mod_eight++;
- if(i_mod_eight >= 8)
- {
- i_mod_eight -= 8;
- kFlag++;
- }
- }
-
- return startByte;
-}
-*/
-
-U32 LLPartSysCompressedPacket::readKill_p(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->killPlaneNormal[0] = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->killPlaneNormal[1] = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->killPlaneNormal[2] = floatFromTwoBytes(bMant, bExp);
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->killPlaneZ = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->distanceDeath = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readBounce_p(LLPartInitData *in, U32 startByte)
-{
-
- S8 bMant, bExp;
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->bouncePlaneNormal[0] = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->bouncePlaneNormal[1] = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->bouncePlaneNormal[2] = floatFromTwoBytes(bMant, bExp);
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->bouncePlaneZ = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readBounce_b(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->bounce_b = floatFromTwoBytes(bMant, bExp);
- return startByte;
-}
-
-
-//U32 LLPartSysCompressedPacket::readPos_ranges(LLPartInitData *in, U32 startByte)
-//{
-// S8 tmp;
-// int i;
-// for(i = 0; i < 6; i++)
-// {
-// tmp = (S8)mData[startByte++];
-// in->pos_ranges[i] = tmp;
-// }
-// return startByte;
-//}
-
-//U32 LLPartSysCompressedPacket::readVel_ranges(LLPartInitData *in, U32 startByte)
-//{
-// S8 tmp;
-// int i;
-// for(i = 0; i < 6; i++)
-// {
-// tmp = (S8)mData[startByte++];
-// in->vel_ranges[i] = tmp;
-// }
-// return startByte;
-//}
-
-
-
-U32 LLPartSysCompressedPacket::readAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte)
-{
- int i;
- S8 bMant, bExp;
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->diffEqAlpha[i] = floatFromTwoBytes(bMant, bExp);
- }
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->diffEqScale[i] = floatFromTwoBytes(bMant, bExp);
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readAlpha_range(LLPartInitData *in, U32 startByte)
-{
- int i;
- S8 bMant, bExp;
- for(i = 0; i < 4; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->alpha_range[i] = floatFromTwoBytes(bMant, bExp);
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readScale_range(LLPartInitData *in, U32 startByte)
-{
- int i;
- S8 bMant, bExp;
- for(i = 0; i < 4; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->scale_range[i] = floatFromTwoBytes(bMant, bExp);
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readVelocityOffset(LLPartInitData *in, U32 startByte)
-{
- int i;
- S8 bMant, bExp;
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->vel_offset[i] = floatFromTwoBytes(bMant, bExp);
- }
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readUUID(LLPartInitData *in, U32 startByte)
-{
- U8 * bufPtr = mData + startByte;
-
- if(mData[startByte] == 0x01)
- {
- in->mImageUuid = IMG_SHOT;
- return startByte+1;
- }
- if(mData[startByte] == 0x02)
- {
- in->mImageUuid = IMG_SPARK;
- return startByte+1;
- }
- if(mData[startByte] == 0x03)
- {
- in->mImageUuid = IMG_BIG_EXPLOSION_1;
- return startByte+1;
- }
- if(mData[startByte] == 0x04)
- {
- in->mImageUuid = IMG_BIG_EXPLOSION_2;
- return startByte+1;
- }
- if(mData[startByte] == 0x05)
- {
- in->mImageUuid = IMG_SMOKE_POOF;
- return startByte+1;
- }
- if(mData[startByte] == 0x06)
- {
- in->mImageUuid = IMG_FIRE;
- return startByte+1;
- }
- if(mData[startByte] == 0x07)
- {
- in->mImageUuid = IMG_EXPLOSION;
- return startByte+1;
- }
- if(mData[startByte] == 0x08)
- {
- in->mImageUuid = IMG_EXPLOSION_2;
- return startByte+1;
- }
- if(mData[startByte] == 0x09)
- {
- in->mImageUuid = IMG_EXPLOSION_3;
- return startByte+1;
- }
- if(mData[startByte] == 0x0A)
- {
- in->mImageUuid = IMG_EXPLOSION_4;
- return startByte+1;
- }
-
- startByte++; // cause we actually have to read the UUID now.
- memcpy(in->mImageUuid.mData, bufPtr, 16); /* Flawfinder: ignore */
- return (startByte+16);
-}
-
-
-
-
-U32 LLPartSysCompressedPacket::readSpawn(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
- U32 i;
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnRange = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnFrequency = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnFreqencyRange = floatFromTwoBytes(bMant, bExp);
-
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnDirection[i] = floatFromTwoBytes(bMant, bExp);
- }
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnDirectionRange = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnVelocity = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->spawnVelocityRange = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readEnvironment(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
- U32 i;
-
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->windWeight = floatFromTwoBytes(bMant, bExp);
-
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->currentGravity[i] = floatFromTwoBytes(bMant, bExp);
- }
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->gravityWeight = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readLifespan(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->globalLifetime = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->individualLifetime = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->individualLifetimeRange = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readDecayDamp(LLPartInitData *in, U32 startByte)
-{
- S8 bMant, bExp;
-
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->speedLimit = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->alphaDecay = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->scaleDecay = floatFromTwoBytes(bMant, bExp);
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->dampMotionFactor = floatFromTwoBytes(bMant, bExp);
-
- return startByte;
-}
-
-U32 LLPartSysCompressedPacket::readWindDiffusionFactor(LLPartInitData *in, U32 startByte)
-{
- int i;
- S8 bMant, bExp;
- for(i = 0; i < 3; i++)
- {
- bMant = mData[startByte++];
- bExp = mData[startByte++];
- in->windDiffusionFactor[i] = floatFromTwoBytes(bMant, bExp);
- }
- return startByte;
-}
-
-bool LLPartSysCompressedPacket::fromLLPartInitData(LLPartInitData *in, U32 &bytesUsed)
-{
-
- writeFlagByte(in);
- U32 currByte = 4;
-
-// llprintline("calling \"fromLLPartInitData\"\n");
-
- //if(mData[0] & PART_SYS_K_MASK)
- //{
- // currByte = writeK(in, 3); // first 3 bytes are reserved for header data
- //}
-
-
-
- if(mData[0] & PART_SYS_KILL_P_MASK)
- {
- currByte = writeKill_p(in, currByte);
- }
-
- if(mData[0] & PART_SYS_BOUNCE_P_MASK)
- {
- currByte = writeBounce_p(in, currByte);
- }
-
- if(mData[0] & PART_SYS_BOUNCE_B_MASK)
- {
- currByte = writeBounce_b(in, currByte);
- }
-
- //if(mData[0] & PART_SYS_POS_RANGES_MASK)
- //{
- // currByte = writePos_ranges(in, currByte);
- //}
-
- //if(mData[0] & PART_SYS_VEL_RANGES_MASK)
- //{
- // currByte = writeVel_ranges(in, currByte);
- //}
-
- if(mData[0] & PART_SYS_ALPHA_SCALE_DIFF_MASK)
- {
- currByte = writeAlphaScaleDiffEqn_range(in, currByte);
- }
-
- if(mData[0] & PART_SYS_SCALE_RANGE_MASK)
- {
- currByte = writeScale_range(in, currByte);
- }
-
- if(mData[0] & PART_SYS_VEL_OFFSET_MASK)
- {
- currByte = writeVelocityOffset(in, currByte);
- }
-
- if(mData[0] & PART_SYS_M_IMAGE_UUID_MASK)
- {
- currByte = writeUUID(in, currByte);
- }
-
-
- if(mData[3] & PART_SYS_BYTE_SPAWN_MASK)
- {
- currByte = writeSpawn(in, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_ENVIRONMENT_MASK)
- {
- currByte = writeEnvironment(in, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_LIFESPAN_MASK)
- {
- currByte = writeLifespan(in, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_DECAY_DAMP_MASK)
- {
- currByte = writeDecayDamp(in, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_WIND_DIFF_MASK)
- {
- currByte = writeWindDiffusionFactor(in, currByte);
- }
-
-
- if(mData[2] & PART_SYS_BYTE_3_ALPHA_MASK)
- {
- currByte = writeAlpha_range(in, currByte);
- }
-
- mData[currByte++] = (U8)in->maxParticles;
- mData[currByte++] = (U8)in->initialParticles;
-
-
- U32 flagFlag = 1; // flag indicating which flag bytes are non-zero
- // yeah, I know, the name sounds funny
- for(U32 i = 0; i < 8; i++)
- {
-
-// llprintline("Flag \"%x\" gets byte \"%x\"\n", flagFlag, in->mFlags[i]);
- if(mData[1] & flagFlag)
- {
- mData[currByte++] = in->mFlags[i];
-// llprintline("and is valid...\n");
- }
- flagFlag <<= 1;
- }
-
- bytesUsed = mNumBytes = currByte;
-
-
-
-// llprintline("returning from \"fromLLPartInitData\" with %d bytes\n", bytesUsed);
-
- return true;
-}
-
-bool LLPartSysCompressedPacket::toLLPartInitData(LLPartInitData *out, U32 *bytesUsed)
-{
- U32 currByte = 4;
-
- gSetInitDataDefaults(out);
-
- if(mData[0] & PART_SYS_KILL_P_MASK)
- {
- currByte = readKill_p(out, currByte);
- }
-
- if(mData[0] & PART_SYS_BOUNCE_P_MASK)
- {
- currByte = readBounce_p(out, currByte);
- }
-
- if(mData[0] & PART_SYS_BOUNCE_B_MASK)
- {
- currByte = readBounce_b(out, currByte);
- }
-
- if(mData[0] & PART_SYS_ALPHA_SCALE_DIFF_MASK)
- {
- currByte = readAlphaScaleDiffEqn_range(out, currByte);
- }
-
- if(mData[0] & PART_SYS_SCALE_RANGE_MASK)
- {
- currByte = readScale_range(out, currByte);
- }
-
- if(mData[0] & PART_SYS_VEL_OFFSET_MASK)
- {
- currByte = readVelocityOffset(out, currByte);
- }
-
- if(mData[0] & PART_SYS_M_IMAGE_UUID_MASK)
- {
- currByte = readUUID(out, currByte);
- }
-
-
- if(mData[3] & PART_SYS_BYTE_SPAWN_MASK)
- {
- currByte = readSpawn(out, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_ENVIRONMENT_MASK)
- {
- currByte = readEnvironment(out, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_LIFESPAN_MASK)
- {
- currByte = readLifespan(out, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_DECAY_DAMP_MASK)
- {
- currByte = readDecayDamp(out, currByte);
- }
-
- if(mData[3] & PART_SYS_BYTE_WIND_DIFF_MASK)
- {
- currByte = readWindDiffusionFactor(out, currByte);
- }
-
- if(mData[2] & PART_SYS_BYTE_3_ALPHA_MASK)
- {
- currByte = readAlpha_range(out, currByte);
- }
-
- out->maxParticles = mData[currByte++];
- out->initialParticles = mData[currByte++];
-
- U32 flagFlag = 1; // flag indicating which flag bytes are non-zero
- // yeah, I know, the name sounds funny
- for(U32 i = 0; i < 8; i++)
- {
- flagFlag = 1<<i;
-
- if((mData[1] & flagFlag))
- {
- out->mFlags[i] = mData[currByte++];
- }
- }
-
- *bytesUsed = currByte;
- return true;
-}
-
-bool LLPartSysCompressedPacket::fromUnsignedBytes(U8 *in, U32 bytesUsed)
-{
- if ((in != NULL) && (bytesUsed <= sizeof(mData)))
- {
- memcpy(mData, in, bytesUsed); /* Flawfinder: ignore */
- mNumBytes = bytesUsed;
- return true;
- }
- else
- {
- LL_ERRS() << "NULL input data or number of bytes exceed mData size" << LL_ENDL;
- return false;
- }
-}
-
-
-U32 LLPartSysCompressedPacket::bufferSize()
-{
- return mNumBytes;
-}
-
-bool LLPartSysCompressedPacket::toUnsignedBytes(U8 *out)
-{
- memcpy(out, mData, mNumBytes); /* Flawfinder: ignore */
- return true;
-}
-
-U8 * LLPartSysCompressedPacket::getBytePtr()
-{
- return mData;
-}
-
-
+/**
+ * @file partsyspacket.cpp
+ * @brief Object for packing particle system initialization parameters
+ * before sending them over the network.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "partsyspacket.h"
+#include "indra_constants.h"
+
+// this function is global
+void gSetInitDataDefaults(LLPartInitData *setMe)
+{
+ U32 i;
+
+ //for(i = 0; i < 18; i++)
+ //{
+ // setMe->k[i] = 0.0f;
+ //}
+
+ //setMe->kill_p[0] = setMe->kill_p[1] = setMe->kill_p[2] = 0.0f;
+ //setMe->kill_p[3] = -0.2f; // time parameter, die when t= 5.0f
+ //setMe->kill_p[4] = 1.0f;
+ //setMe->kill_p[5] = -0.5f; // or radius == 2 (contracting)
+
+ //setMe->bounce_p[0] = setMe->bounce_p[1] =
+ // setMe->bounce_p[2] = setMe->bounce_p[3] = 0.0f;
+ //setMe->bounce_p[4] = 1.0f;
+
+ setMe->bounce_b = 1.0f;
+ // i just changed the meaning of bounce_b
+ // its now the attenuation from revlecting your velocity across the normal
+ // set by bounce_p
+
+ //setMe->pos_ranges[0] = setMe->pos_ranges[2] = setMe->pos_ranges[4] = -1.0f;
+ //setMe->pos_ranges[1] = setMe->pos_ranges[3] = setMe->pos_ranges[5] = 1.0f;
+
+ //setMe->vel_ranges[0] = setMe->vel_ranges[2] = setMe->vel_ranges[4] = -1.0f;
+ //setMe->vel_ranges[1] = setMe->vel_ranges[3] = setMe->vel_ranges[5] = 1.0f;
+
+ for(i = 0; i < 3; i++)
+ {
+ setMe->diffEqAlpha[i] = 0.0f;
+ setMe->diffEqScale[i] = 0.0f;
+ }
+
+ setMe->scale_range[0] = 1.00f;
+ setMe->scale_range[1] = 5.00f;
+ setMe->scale_range[2] = setMe->scale_range[3] = 0.0f;
+
+ setMe->alpha_range[0] = setMe->alpha_range[1] = 1.0f;
+ setMe->alpha_range[2] = setMe->alpha_range[3] = 0.0f;
+
+ setMe->vel_offset[0] = 0.0f;
+ setMe->vel_offset[1] = 0.0f;
+ setMe->vel_offset[2] = 0.0f;
+
+ // start dropping particles when I'm more then one sim away
+ setMe->mDistBeginFadeout = 256.0f;
+ setMe->mDistEndFadeout = 1.414f * 512.0f;
+ // stop displaying particles when I'm more then two sim diagonals away
+
+ setMe->mImageUuid = IMG_SHOT;
+
+ for(i = 0; i < 8; i++)
+ {
+ setMe->mFlags[i] = 0x00;
+ }
+
+ setMe->createMe = true;
+
+ setMe->maxParticles = 25;
+ setMe->initialParticles = 25;
+
+ //These defaults are for an explosion - a short lived set of debris affected by gravity.
+ //Action flags default to PART_SYS_AFFECTED_BY_WIND + PART_SYS_AFFECTED_BY_GRAVITY + PART_SYS_DISTANCE_DEATH
+ setMe->mFlags[PART_SYS_ACTION_BYTE] = PART_SYS_AFFECTED_BY_WIND | PART_SYS_AFFECTED_BY_GRAVITY | PART_SYS_DISTANCE_DEATH;
+ setMe->mFlags[PART_SYS_KILL_BYTE] = PART_SYS_DISTANCE_DEATH + PART_SYS_TIME_DEATH;
+
+ setMe->killPlaneNormal[0] = 0.0f;setMe->killPlaneNormal[1] = 0.0f;setMe->killPlaneNormal[2] = 1.0f; //Straight up
+ setMe->killPlaneZ = 0.0f; //get local ground z as an approximation if turn on PART_SYS_KILL_PLANE
+ setMe->bouncePlaneNormal[0] = 0.0f;setMe->bouncePlaneNormal[1] = 0.0f;setMe->bouncePlaneNormal[2] = 1.0f; //Straight up
+ setMe->bouncePlaneZ = 0.0f; //get local ground z as an approximation if turn on PART_SYS_BOUNCE
+ setMe->spawnRange = 1.0f;
+ setMe->spawnFrequency = 0.0f; //Create the instant one dies
+ setMe->spawnFreqencyRange = 0.0f;
+ setMe->spawnDirection[0] = 0.0f;setMe->spawnDirection[1] = 0.0f;setMe->spawnDirection[2] = 1.0f; //Straight up
+ setMe->spawnDirectionRange = 1.0f; //global scattering
+ setMe->spawnVelocity = 0.75f;
+ setMe->spawnVelocityRange = 0.25f; //velocity +/- 0.25
+ setMe->speedLimit = 1.0f;
+
+ setMe->windWeight = 0.5f; //0.0f means looks like a heavy object (if gravity is on), 1.0f means light and fluffy
+ setMe->currentGravity[0] = 0.0f;setMe->currentGravity[1] = 0.0f;setMe->currentGravity[2] = -9.81f;
+ //This has to be constant to allow for compression
+
+ setMe->gravityWeight = 0.5f; //0.0f means boyed by air, 1.0f means it's a lead weight
+ setMe->globalLifetime = 0.0f; //Arbitrary, but default is no global die, so doesn't matter
+ setMe->individualLifetime = 5.0f;
+ setMe->individualLifetimeRange = 1.0f; //Particles last 5 secs +/- 1
+ setMe->alphaDecay = 1.0f; //normal alpha fadeout
+ setMe->scaleDecay = 0.0f; //no scale decay
+ setMe->distanceDeath = 10.0f; //die if hit unit radius
+ setMe->dampMotionFactor = 0.0f;
+
+ setMe->windDiffusionFactor[0] = 0.0f;
+ setMe->windDiffusionFactor[1] = 0.0f;
+ setMe->windDiffusionFactor[2] = 0.0f;
+}
+
+LLPartSysCompressedPacket::LLPartSysCompressedPacket()
+{
+ // default constructor for mDefaults called implicitly/automatically here
+ for(int i = 0; i < MAX_PART_SYS_PACKET_SIZE; i++)
+ {
+ mData[i] = '\0';
+ }
+
+ mNumBytes = 0;
+
+ gSetInitDataDefaults(&mDefaults);
+}
+
+LLPartSysCompressedPacket::~LLPartSysCompressedPacket()
+{
+ // no dynamic data is stored by this class, do nothing.
+}
+
+void LLPartSysCompressedPacket::writeFlagByte(LLPartInitData *in)
+{
+ mData[0] = mData[1] = mData[2] = '\0';
+
+ U32 i;
+ //for(i = 1; i < 18; i++) {
+ // if(in->k[i] != mDefaults.k[i])
+ // {
+ // mData[0] |= PART_SYS_K_MASK;
+ // break;
+ // }
+ //}
+
+ if(in->killPlaneZ != mDefaults.killPlaneZ ||
+ in->killPlaneNormal[0] != mDefaults.killPlaneNormal[0] ||
+ in->killPlaneNormal[1] != mDefaults.killPlaneNormal[1] ||
+ in->killPlaneNormal[2] != mDefaults.killPlaneNormal[2] ||
+ in->distanceDeath != mDefaults.distanceDeath)
+ {
+ mData[0] |= PART_SYS_KILL_P_MASK;
+ }
+
+
+
+ if(in->bouncePlaneZ != mDefaults.bouncePlaneZ ||
+ in->bouncePlaneNormal[0] != mDefaults.bouncePlaneNormal[0] ||
+ in->bouncePlaneNormal[1] != mDefaults.bouncePlaneNormal[1] ||
+ in->bouncePlaneNormal[2] != mDefaults.bouncePlaneNormal[2])
+ {
+ mData[0] |= PART_SYS_BOUNCE_P_MASK;
+ }
+
+ if(in->bounce_b != mDefaults.bounce_b)
+ {
+ mData[0] |= PART_SYS_BOUNCE_B_MASK;
+ }
+
+
+ //if(in->pos_ranges[0] != mDefaults.pos_ranges[0] || in->pos_ranges[1] != mDefaults.pos_ranges[1] ||
+ // in->pos_ranges[2] != mDefaults.pos_ranges[2] || in->pos_ranges[3] != mDefaults.pos_ranges[3] ||
+ // in->pos_ranges[4] != mDefaults.pos_ranges[4] || in->pos_ranges[5] != mDefaults.pos_ranges[5])
+ //{
+ // mData[0] |= PART_SYS_POS_RANGES_MASK;
+ //}
+
+ //if(in->vel_ranges[0] != mDefaults.vel_ranges[0] || in->vel_ranges[1] != mDefaults.vel_ranges[1] ||
+ // in->vel_ranges[2] != mDefaults.vel_ranges[2] || in->vel_ranges[3] != mDefaults.vel_ranges[3] ||
+ // in->vel_ranges[4] != mDefaults.vel_ranges[4] || in->vel_ranges[5] != mDefaults.vel_ranges[5])
+ //{
+// mData[0] |= PART_SYS_VEL_RANGES_MASK;
+ //}
+
+
+ if(in->diffEqAlpha[0] != mDefaults.diffEqAlpha[0] ||
+ in->diffEqAlpha[1] != mDefaults.diffEqAlpha[1] ||
+ in->diffEqAlpha[2] != mDefaults.diffEqAlpha[2] ||
+ in->diffEqScale[0] != mDefaults.diffEqScale[0] ||
+ in->diffEqScale[1] != mDefaults.diffEqScale[1] ||
+ in->diffEqScale[2] != mDefaults.diffEqScale[2])
+ {
+ mData[0] |= PART_SYS_ALPHA_SCALE_DIFF_MASK;
+ }
+
+
+ if(in->scale_range[0] != mDefaults.scale_range[0] ||
+ in->scale_range[1] != mDefaults.scale_range[1] ||
+ in->scale_range[2] != mDefaults.scale_range[2] ||
+ in->scale_range[3] != mDefaults.scale_range[3])
+ {
+ mData[0] |= PART_SYS_SCALE_RANGE_MASK;
+ }
+
+
+ if(in->alpha_range[0] != mDefaults.alpha_range[0] ||
+ in->alpha_range[1] != mDefaults.alpha_range[1] ||
+ in->alpha_range[2] != mDefaults.alpha_range[2] ||
+ in->alpha_range[3] != mDefaults.alpha_range[3])
+ {
+ mData[2] |= PART_SYS_BYTE_3_ALPHA_MASK;
+ }
+
+ if(in->vel_offset[0] != mDefaults.vel_offset[0] ||
+ in->vel_offset[1] != mDefaults.vel_offset[1] ||
+ in->vel_offset[2] != mDefaults.vel_offset[2])
+ {
+ mData[0] |= PART_SYS_VEL_OFFSET_MASK;
+ }
+
+
+ if(in->mImageUuid != mDefaults.mImageUuid)
+ {
+ mData[0] |= PART_SYS_M_IMAGE_UUID_MASK;
+ }
+
+ for( i = 0; i < 8; i++)
+ {
+ if(in->mFlags[i])
+ {
+ mData[1] |= 1<<i;
+// llprintline("Flag \"%x\" gets byte \"%x\"\n", i<<i, in->mFlags[i]);
+ }
+ }
+
+
+ if(in->spawnRange != mDefaults.spawnRange ||
+ in->spawnFrequency != mDefaults.spawnFrequency ||
+ in->spawnFreqencyRange != mDefaults.spawnFreqencyRange ||
+ in->spawnDirection[0] != mDefaults.spawnDirection[0] ||
+ in->spawnDirection[1] != mDefaults.spawnDirection[1] ||
+ in->spawnDirection[2] != mDefaults.spawnDirection[2] ||
+ in->spawnDirectionRange != mDefaults.spawnDirectionRange ||
+ in->spawnVelocity != mDefaults.spawnVelocity ||
+ in->spawnVelocityRange != mDefaults.spawnVelocityRange)
+ {
+ mData[3] |= PART_SYS_BYTE_SPAWN_MASK;
+ }
+
+
+ if(in->windWeight != mDefaults.windWeight ||
+ in->currentGravity[0] != mDefaults.currentGravity[0] ||
+ in->currentGravity[1] != mDefaults.currentGravity[1] ||
+ in->currentGravity[2] != mDefaults.currentGravity[2] ||
+ in->gravityWeight != mDefaults.gravityWeight)
+ {
+ mData[3] |= PART_SYS_BYTE_ENVIRONMENT_MASK;
+ }
+
+
+ if(in->globalLifetime != mDefaults.globalLifetime ||
+ in->individualLifetime != mDefaults.individualLifetime ||
+ in->individualLifetimeRange != mDefaults.individualLifetimeRange)
+ {
+ mData[3] |= PART_SYS_BYTE_LIFESPAN_MASK;
+ }
+
+
+ if(in->speedLimit != mDefaults.speedLimit ||
+ in->alphaDecay != mDefaults.alphaDecay ||
+ in->scaleDecay != mDefaults.scaleDecay ||
+ in->dampMotionFactor != mDefaults.dampMotionFactor)
+ {
+ mData[3] |= PART_SYS_BYTE_DECAY_DAMP_MASK;
+ }
+
+ if(in->windDiffusionFactor[0] != mDefaults.windDiffusionFactor[0] ||
+ in->windDiffusionFactor[1] != mDefaults.windDiffusionFactor[1] ||
+ in->windDiffusionFactor[2] != mDefaults.windDiffusionFactor[2])
+ {
+ mData[3] |= PART_SYS_BYTE_WIND_DIFF_MASK;
+ }
+}
+
+F32 floatFromTwoBytes(S8 bMant, S8 bExp)
+{
+ F32 result = bMant;
+ while(bExp > 0)
+ {
+ result *= 2.0f;
+ bExp--;
+ }
+ while(bExp < 0)
+ {
+ result *= 0.5f;
+ bExp++;
+ }
+ return result;
+}
+
+void twoBytesFromFloat(F32 fIn, S8 &bMant, S8 &bExp)
+{
+ bExp = 0;
+ if(fIn > 127.0f)
+ {
+ fIn = 127.0f;
+ }
+ if(fIn < -127.0f)
+ {
+ fIn = -127.0f;
+ }
+ while(fIn < 64 && fIn > -64 && bExp > -127)
+ {
+ fIn *= 2.0f;
+ bExp--;
+ }
+ while((fIn > 128 || fIn < -128) && bExp < 127)
+ {
+ fIn *= 0.5f;
+ bExp++;
+ }
+ bMant = (S8)fIn;
+}
+
+
+
+/*
+U32 LLPartSysCompressedPacket::writeK(LLPartInitData *in, U32 startByte)
+{
+ U32 i, kFlag, i_mod_eight;
+ S8 bMant, bExp;
+
+ kFlag = startByte;
+
+ startByte += 3; // 3 bytes contain enough room for 18 flag bits
+ mData[kFlag] = 0x00;
+// llprintline("In the writeK\n");
+
+ i_mod_eight = 0;
+ for(i = 0; i < 18; i++)
+ {
+ if(in->k[i] != mDefaults.k[i])
+ {
+
+ mData[kFlag] |= 1<<i_mod_eight;
+ twoBytesFromFloat(in->k[i], bMant, bExp);
+
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ i_mod_eight++;
+ while(i_mod_eight >= 8)
+ {
+ kFlag++;
+ i_mod_eight -= 8;
+ }
+ }
+
+ return startByte;
+}*/
+
+U32 LLPartSysCompressedPacket::writeKill_p(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+
+ twoBytesFromFloat(in->killPlaneNormal[0], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->killPlaneNormal[1], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->killPlaneNormal[2], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->killPlaneZ, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->distanceDeath, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeBounce_p(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+
+ twoBytesFromFloat(in->bouncePlaneNormal[0], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->bouncePlaneNormal[1], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->bouncePlaneNormal[2], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+
+ twoBytesFromFloat(in->bouncePlaneZ, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeBounce_b(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+ twoBytesFromFloat(in->bounce_b, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ return startByte;
+}
+
+//U32 LLPartSysCompressedPacket::writePos_ranges(LLPartInitData *in, U32 startByte)
+//{
+// S8 tmp;
+// int i;
+// for(i = 0; i < 6; i++)
+// {
+// tmp = (S8) in->pos_ranges[i]; // float to int conversion (keep the sign)
+// mData[startByte++] = (U8)tmp; // signed to unsigned typecast
+// }
+// return startByte;
+//}
+
+//U32 LLPartSysCompressedPacket::writeVel_ranges(LLPartInitData *in, U32 startByte)
+//{
+// S8 tmp;
+// int i;
+// for(i = 0; i < 6; i++)
+// {
+// tmp = (S8) in->vel_ranges[i]; // float to int conversion (keep the sign)
+// mData[startByte++] = (U8)tmp; // signed to unsigned typecast
+// }
+// return startByte;
+//}
+
+U32 LLPartSysCompressedPacket::writeAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+ for(i = 0; i < 3; i++)
+ {
+ twoBytesFromFloat(in->diffEqAlpha[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ for(i = 0; i < 3; i++)
+ {
+ twoBytesFromFloat(in->diffEqScale[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeScale_range(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+ for(i = 0; i < 4; i++)
+ {
+ twoBytesFromFloat(in->scale_range[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ return startByte;
+}
+
+
+U32 LLPartSysCompressedPacket::writeAlpha_range(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+ for(i = 0; i < 4; i++)
+ {
+ twoBytesFromFloat(in->alpha_range[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeVelocityOffset(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+ for(i = 0; i < 3; i++)
+ {
+ twoBytesFromFloat(in->vel_offset[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeUUID(LLPartInitData *in, U32 startByte)
+{
+ U8 * bufPtr = mData + startByte;
+ if(in->mImageUuid == IMG_SHOT) {
+ mData[startByte++] = 0x01;
+ return startByte;
+ }
+
+ if(in->mImageUuid == IMG_SPARK) {
+ mData[startByte++] = 0x02;
+ return startByte;
+ }
+
+
+ if(in->mImageUuid == IMG_BIG_EXPLOSION_1) {
+ mData[startByte++] = 0x03;
+ return startByte;
+ }
+
+ if(in->mImageUuid == IMG_BIG_EXPLOSION_2) {
+ mData[startByte++] = 0x04;
+ return startByte;
+ }
+
+
+ if(in->mImageUuid == IMG_SMOKE_POOF) {
+ mData[startByte++] = 0x05;
+ return startByte;
+ }
+
+ if(in->mImageUuid == IMG_FIRE) {
+ mData[startByte++] = 0x06;
+ return startByte;
+ }
+
+
+ if(in->mImageUuid == IMG_EXPLOSION) {
+ mData[startByte++] = 0x07;
+ return startByte;
+ }
+
+ if(in->mImageUuid == IMG_EXPLOSION_2) {
+ mData[startByte++] = 0x08;
+ return startByte;
+ }
+
+
+ if(in->mImageUuid == IMG_EXPLOSION_3) {
+ mData[startByte++] = 0x09;
+ return startByte;
+ }
+
+ if(in->mImageUuid == IMG_EXPLOSION_4) {
+ mData[startByte++] = 0x0A;
+ return startByte;
+ }
+
+ mData[startByte++] = 0x00; // flag for "read whole UUID"
+
+ memcpy(bufPtr, in->mImageUuid.mData, 16); /* Flawfinder: ignore */
+ return (startByte+16);
+}
+
+U32 LLPartSysCompressedPacket::writeSpawn(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+
+ twoBytesFromFloat(in->spawnRange, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->spawnFrequency, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->spawnFreqencyRange, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+
+
+ for(i = 0; i < 3; i++)
+ {
+ twoBytesFromFloat(in->spawnDirection[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+
+ twoBytesFromFloat(in->spawnDirectionRange, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->spawnVelocity, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ twoBytesFromFloat(in->spawnVelocityRange, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeEnvironment(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+ int i;
+
+ twoBytesFromFloat(in->windWeight, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ for(i = 0; i < 3; i++)
+ {
+ twoBytesFromFloat(in->currentGravity[i], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ }
+
+ twoBytesFromFloat(in->gravityWeight, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeLifespan(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+
+ twoBytesFromFloat(in->globalLifetime, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->individualLifetime, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->individualLifetimeRange, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+
+U32 LLPartSysCompressedPacket::writeDecayDamp(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+
+ twoBytesFromFloat(in->speedLimit, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->alphaDecay, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->scaleDecay, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->dampMotionFactor, bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::writeWindDiffusionFactor(LLPartInitData *in, U32 startByte)
+{
+ S8 bExp, bMant;
+
+ twoBytesFromFloat(in->windDiffusionFactor[0], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->windDiffusionFactor[1], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ twoBytesFromFloat(in->windDiffusionFactor[2], bMant, bExp);
+ mData[startByte++] = bMant;
+ mData[startByte++] = bExp;
+
+ return startByte;
+}
+
+
+
+
+
+
+/*
+U32 LLPartSysCompressedPacket::readK(LLPartInitData *in, U32 startByte)
+{
+ U32 i, i_mod_eight, kFlag;
+ S8 bMant, bExp; // 1 bytes mantissa and exponent for a float
+ kFlag = startByte;
+ startByte += 3; // 3 bytes has enough room for 18 bits
+
+ i_mod_eight = 0;
+ for(i = 0; i < 18; i++)
+ {
+ if(mData[kFlag]&(1<<i_mod_eight))
+ {
+
+
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+
+
+ in->k[i] = floatFromTwoBytes(bMant, bExp); // much tighter platform-independent
+ // way to ship floats
+
+ }
+ i_mod_eight++;
+ if(i_mod_eight >= 8)
+ {
+ i_mod_eight -= 8;
+ kFlag++;
+ }
+ }
+
+ return startByte;
+}
+*/
+
+U32 LLPartSysCompressedPacket::readKill_p(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->killPlaneNormal[0] = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->killPlaneNormal[1] = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->killPlaneNormal[2] = floatFromTwoBytes(bMant, bExp);
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->killPlaneZ = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->distanceDeath = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readBounce_p(LLPartInitData *in, U32 startByte)
+{
+
+ S8 bMant, bExp;
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->bouncePlaneNormal[0] = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->bouncePlaneNormal[1] = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->bouncePlaneNormal[2] = floatFromTwoBytes(bMant, bExp);
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->bouncePlaneZ = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readBounce_b(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->bounce_b = floatFromTwoBytes(bMant, bExp);
+ return startByte;
+}
+
+
+//U32 LLPartSysCompressedPacket::readPos_ranges(LLPartInitData *in, U32 startByte)
+//{
+// S8 tmp;
+// int i;
+// for(i = 0; i < 6; i++)
+// {
+// tmp = (S8)mData[startByte++];
+// in->pos_ranges[i] = tmp;
+// }
+// return startByte;
+//}
+
+//U32 LLPartSysCompressedPacket::readVel_ranges(LLPartInitData *in, U32 startByte)
+//{
+// S8 tmp;
+// int i;
+// for(i = 0; i < 6; i++)
+// {
+// tmp = (S8)mData[startByte++];
+// in->vel_ranges[i] = tmp;
+// }
+// return startByte;
+//}
+
+
+
+U32 LLPartSysCompressedPacket::readAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte)
+{
+ int i;
+ S8 bMant, bExp;
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->diffEqAlpha[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->diffEqScale[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readAlpha_range(LLPartInitData *in, U32 startByte)
+{
+ int i;
+ S8 bMant, bExp;
+ for(i = 0; i < 4; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->alpha_range[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readScale_range(LLPartInitData *in, U32 startByte)
+{
+ int i;
+ S8 bMant, bExp;
+ for(i = 0; i < 4; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->scale_range[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readVelocityOffset(LLPartInitData *in, U32 startByte)
+{
+ int i;
+ S8 bMant, bExp;
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->vel_offset[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readUUID(LLPartInitData *in, U32 startByte)
+{
+ U8 * bufPtr = mData + startByte;
+
+ if(mData[startByte] == 0x01)
+ {
+ in->mImageUuid = IMG_SHOT;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x02)
+ {
+ in->mImageUuid = IMG_SPARK;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x03)
+ {
+ in->mImageUuid = IMG_BIG_EXPLOSION_1;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x04)
+ {
+ in->mImageUuid = IMG_BIG_EXPLOSION_2;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x05)
+ {
+ in->mImageUuid = IMG_SMOKE_POOF;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x06)
+ {
+ in->mImageUuid = IMG_FIRE;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x07)
+ {
+ in->mImageUuid = IMG_EXPLOSION;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x08)
+ {
+ in->mImageUuid = IMG_EXPLOSION_2;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x09)
+ {
+ in->mImageUuid = IMG_EXPLOSION_3;
+ return startByte+1;
+ }
+ if(mData[startByte] == 0x0A)
+ {
+ in->mImageUuid = IMG_EXPLOSION_4;
+ return startByte+1;
+ }
+
+ startByte++; // cause we actually have to read the UUID now.
+ memcpy(in->mImageUuid.mData, bufPtr, 16); /* Flawfinder: ignore */
+ return (startByte+16);
+}
+
+
+
+
+U32 LLPartSysCompressedPacket::readSpawn(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+ U32 i;
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnRange = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnFrequency = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnFreqencyRange = floatFromTwoBytes(bMant, bExp);
+
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnDirection[i] = floatFromTwoBytes(bMant, bExp);
+ }
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnDirectionRange = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnVelocity = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->spawnVelocityRange = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readEnvironment(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+ U32 i;
+
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->windWeight = floatFromTwoBytes(bMant, bExp);
+
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->currentGravity[i] = floatFromTwoBytes(bMant, bExp);
+ }
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->gravityWeight = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readLifespan(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->globalLifetime = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->individualLifetime = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->individualLifetimeRange = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readDecayDamp(LLPartInitData *in, U32 startByte)
+{
+ S8 bMant, bExp;
+
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->speedLimit = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->alphaDecay = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->scaleDecay = floatFromTwoBytes(bMant, bExp);
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->dampMotionFactor = floatFromTwoBytes(bMant, bExp);
+
+ return startByte;
+}
+
+U32 LLPartSysCompressedPacket::readWindDiffusionFactor(LLPartInitData *in, U32 startByte)
+{
+ int i;
+ S8 bMant, bExp;
+ for(i = 0; i < 3; i++)
+ {
+ bMant = mData[startByte++];
+ bExp = mData[startByte++];
+ in->windDiffusionFactor[i] = floatFromTwoBytes(bMant, bExp);
+ }
+ return startByte;
+}
+
+bool LLPartSysCompressedPacket::fromLLPartInitData(LLPartInitData *in, U32 &bytesUsed)
+{
+
+ writeFlagByte(in);
+ U32 currByte = 4;
+
+// llprintline("calling \"fromLLPartInitData\"\n");
+
+ //if(mData[0] & PART_SYS_K_MASK)
+ //{
+ // currByte = writeK(in, 3); // first 3 bytes are reserved for header data
+ //}
+
+
+
+ if(mData[0] & PART_SYS_KILL_P_MASK)
+ {
+ currByte = writeKill_p(in, currByte);
+ }
+
+ if(mData[0] & PART_SYS_BOUNCE_P_MASK)
+ {
+ currByte = writeBounce_p(in, currByte);
+ }
+
+ if(mData[0] & PART_SYS_BOUNCE_B_MASK)
+ {
+ currByte = writeBounce_b(in, currByte);
+ }
+
+ //if(mData[0] & PART_SYS_POS_RANGES_MASK)
+ //{
+ // currByte = writePos_ranges(in, currByte);
+ //}
+
+ //if(mData[0] & PART_SYS_VEL_RANGES_MASK)
+ //{
+ // currByte = writeVel_ranges(in, currByte);
+ //}
+
+ if(mData[0] & PART_SYS_ALPHA_SCALE_DIFF_MASK)
+ {
+ currByte = writeAlphaScaleDiffEqn_range(in, currByte);
+ }
+
+ if(mData[0] & PART_SYS_SCALE_RANGE_MASK)
+ {
+ currByte = writeScale_range(in, currByte);
+ }
+
+ if(mData[0] & PART_SYS_VEL_OFFSET_MASK)
+ {
+ currByte = writeVelocityOffset(in, currByte);
+ }
+
+ if(mData[0] & PART_SYS_M_IMAGE_UUID_MASK)
+ {
+ currByte = writeUUID(in, currByte);
+ }
+
+
+ if(mData[3] & PART_SYS_BYTE_SPAWN_MASK)
+ {
+ currByte = writeSpawn(in, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_ENVIRONMENT_MASK)
+ {
+ currByte = writeEnvironment(in, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_LIFESPAN_MASK)
+ {
+ currByte = writeLifespan(in, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_DECAY_DAMP_MASK)
+ {
+ currByte = writeDecayDamp(in, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_WIND_DIFF_MASK)
+ {
+ currByte = writeWindDiffusionFactor(in, currByte);
+ }
+
+
+ if(mData[2] & PART_SYS_BYTE_3_ALPHA_MASK)
+ {
+ currByte = writeAlpha_range(in, currByte);
+ }
+
+ mData[currByte++] = (U8)in->maxParticles;
+ mData[currByte++] = (U8)in->initialParticles;
+
+
+ U32 flagFlag = 1; // flag indicating which flag bytes are non-zero
+ // yeah, I know, the name sounds funny
+ for(U32 i = 0; i < 8; i++)
+ {
+
+// llprintline("Flag \"%x\" gets byte \"%x\"\n", flagFlag, in->mFlags[i]);
+ if(mData[1] & flagFlag)
+ {
+ mData[currByte++] = in->mFlags[i];
+// llprintline("and is valid...\n");
+ }
+ flagFlag <<= 1;
+ }
+
+ bytesUsed = mNumBytes = currByte;
+
+
+
+// llprintline("returning from \"fromLLPartInitData\" with %d bytes\n", bytesUsed);
+
+ return true;
+}
+
+bool LLPartSysCompressedPacket::toLLPartInitData(LLPartInitData *out, U32 *bytesUsed)
+{
+ U32 currByte = 4;
+
+ gSetInitDataDefaults(out);
+
+ if(mData[0] & PART_SYS_KILL_P_MASK)
+ {
+ currByte = readKill_p(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_BOUNCE_P_MASK)
+ {
+ currByte = readBounce_p(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_BOUNCE_B_MASK)
+ {
+ currByte = readBounce_b(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_ALPHA_SCALE_DIFF_MASK)
+ {
+ currByte = readAlphaScaleDiffEqn_range(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_SCALE_RANGE_MASK)
+ {
+ currByte = readScale_range(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_VEL_OFFSET_MASK)
+ {
+ currByte = readVelocityOffset(out, currByte);
+ }
+
+ if(mData[0] & PART_SYS_M_IMAGE_UUID_MASK)
+ {
+ currByte = readUUID(out, currByte);
+ }
+
+
+ if(mData[3] & PART_SYS_BYTE_SPAWN_MASK)
+ {
+ currByte = readSpawn(out, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_ENVIRONMENT_MASK)
+ {
+ currByte = readEnvironment(out, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_LIFESPAN_MASK)
+ {
+ currByte = readLifespan(out, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_DECAY_DAMP_MASK)
+ {
+ currByte = readDecayDamp(out, currByte);
+ }
+
+ if(mData[3] & PART_SYS_BYTE_WIND_DIFF_MASK)
+ {
+ currByte = readWindDiffusionFactor(out, currByte);
+ }
+
+ if(mData[2] & PART_SYS_BYTE_3_ALPHA_MASK)
+ {
+ currByte = readAlpha_range(out, currByte);
+ }
+
+ out->maxParticles = mData[currByte++];
+ out->initialParticles = mData[currByte++];
+
+ U32 flagFlag = 1; // flag indicating which flag bytes are non-zero
+ // yeah, I know, the name sounds funny
+ for(U32 i = 0; i < 8; i++)
+ {
+ flagFlag = 1<<i;
+
+ if((mData[1] & flagFlag))
+ {
+ out->mFlags[i] = mData[currByte++];
+ }
+ }
+
+ *bytesUsed = currByte;
+ return true;
+}
+
+bool LLPartSysCompressedPacket::fromUnsignedBytes(U8 *in, U32 bytesUsed)
+{
+ if ((in != NULL) && (bytesUsed <= sizeof(mData)))
+ {
+ memcpy(mData, in, bytesUsed); /* Flawfinder: ignore */
+ mNumBytes = bytesUsed;
+ return true;
+ }
+ else
+ {
+ LL_ERRS() << "NULL input data or number of bytes exceed mData size" << LL_ENDL;
+ return false;
+ }
+}
+
+
+U32 LLPartSysCompressedPacket::bufferSize()
+{
+ return mNumBytes;
+}
+
+bool LLPartSysCompressedPacket::toUnsignedBytes(U8 *out)
+{
+ memcpy(out, mData, mNumBytes); /* Flawfinder: ignore */
+ return true;
+}
+
+U8 * LLPartSysCompressedPacket::getBytePtr()
+{
+ return mData;
+}
+
+
diff --git a/indra/llmessage/partsyspacket.h b/indra/llmessage/partsyspacket.h
index 76c6b3e202..09d0ef76d5 100644
--- a/indra/llmessage/partsyspacket.h
+++ b/indra/llmessage/partsyspacket.h
@@ -1,261 +1,261 @@
-/**
- * @file partsyspacket.h
- * @brief Object for packing particle system initialization parameters
- * before sending them over the network
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_PARTSYSPACKET_H
-#define LL_PARTSYSPACKET_H
-
-#include "lluuid.h"
-
-// Particle system stuff
-
-const U64 PART_SYS_MAX_TIME_IN_USEC = 1000000; // 1 second, die not quite near instantaneously
-
-
-// this struct is for particle system initialization parameters
-// I'm breaking some rules here, but I need a storage structure to hold initialization data
-// for these things. Sorry guys, they're not simple enough (yet) to avoid this cleanly
-struct LLPartInitData {
- // please do not add functions to this class -- data only!
- //F32 k[18]; // first 9 --> x,y,z last 9 --> scale, alpha, rot
- //F32 kill_p[6]; // last one is for particles that die when they reach a spherical bounding radius
- //F32 kill_plane[3];
- //F32 bounce_p[5];
- F32 bounce_b; // recently changed
- // no need to store orientation and position here, as they're sent over seperately
- //F32 pos_ranges[6];
- //F32 vel_ranges[6];
- F32 scale_range[4];
- F32 alpha_range[4];
- F32 vel_offset[3]; //new - more understandable!
-
- F32 mDistBeginFadeout; // for fadeout LOD optimization
- F32 mDistEndFadeout;
-
- LLUUID mImageUuid;
- //U8 n; // number of particles
- U8 mFlags[8]; // for miscellaneous data --> its interpretation can change at my whim!
- U8 createMe; // do I need to be created? or has the work allready been done?
- //ActionFlag is now mFlags[PART_SYS_ACTION_BYTE]
- //Spawn point is initially object creation center
-
- F32 diffEqAlpha[3];
- F32 diffEqScale[3];
-
- U8 maxParticles;
- //How many particles exist at any time within the system?
- U8 initialParticles;
- //How many particles exist when the system is created?
- F32 killPlaneZ;
- //For simplicity assume the XY plane, so this sets an altitude at which to die
- F32 killPlaneNormal[3];
- //Normal if not planar XY
- F32 bouncePlaneZ;
- //For simplicity assume the XY plane, so this sets an altitude at which to bounce
- F32 bouncePlaneNormal[3];
- //Normal if not planar XY
- F32 spawnRange;
- //Range of emission points about the mSpawnPoint
- F32 spawnFrequency;
- //Required if the system is to spawn new particles.
- //This variable determines the time after a particle dies when it is respawned.
- F32 spawnFreqencyRange;
- //Determines the random range of time until a new particle is spawned.
- F32 spawnDirection[3];
- //Direction vector giving the mean direction in which particles are spawned
- F32 spawnDirectionRange;
- //Direction limiting the angular range of emissions about the mean direction. 1.0f means everywhere, 0.0f means uni-directional
- F32 spawnVelocity;
- //The mean speed at which particles are emitted
- F32 spawnVelocityRange;
- //The range of speeds about the mean at which particles are emitted.
- F32 speedLimit;
- //Used to constrain particle maximum velocity
- F32 windWeight;
- //How much of an effect does wind have
- F32 currentGravity[3];
- //Gravity direction used in update calculations
- F32 gravityWeight;
- //How much of an effect does gravity have
- F32 globalLifetime;
- //If particles re-spawn, a system can exist forever.
- //If (ActionFlags & PART_SYS_GLOBAL_DIE) is true this variable is used to determine how long the system lasts.
- F32 individualLifetime;
- //How long does each particle last if nothing else happens to it
- F32 individualLifetimeRange;
- //Range of variation in individual lifetimes
- F32 alphaDecay;
- //By what factor does alpha decrease as the lifetime of a particle is approached.
- F32 scaleDecay;
- //By what factor does scale decrease as the lifetime of a particle is approached.
- F32 distanceDeath;
- //With the increased functionality, particle systems can expand to indefinite size
- //(e.g. wind can chaotically move particles into a wide spread).
- //To avoid particles exceeding normal object size constraints,
- //set the PART_SYS_DISTANCE_DEATH flag, and set a distance value here, representing a radius around the spawn point.
- F32 dampMotionFactor;
- //How much to damp motion
- F32 windDiffusionFactor[3];
- //Change the size and alpha of particles as wind speed increases (scale gets bigger, alpha smaller)
-};
-
-// constants for setting flag values
-// BYTES are in range 0-8, bits are in range 2^0 - 2^8 and can only be powers of two
-const int PART_SYS_NO_Z_BUFFER_BYTE = 0; // option to turn off z-buffer when rendering
-const int PART_SYS_NO_Z_BUFFER_BIT = 2; // particle systems --
-// I advise against using this, as it looks bad in every case I've tried
-
-const int PART_SYS_SLOW_ANIM_BYTE = 0; // slow animation down by a factor of 10
-const int PART_SYS_SLOW_ANIM_BIT = 1; // useful for tweaking anims during debugging
-
-const int PART_SYS_FOLLOW_VEL_BYTE = 0; // indicates whether to orient sprites towards
-const int PART_SYS_FOLLOW_VEL_BIT = 4; // their velocity vector -- default is false
-
-const int PART_SYS_IS_LIGHT_BYTE = 0; // indicates whether a particular particle system
-const int PART_SYS_IS_LIGHT_BIT = 8; // is also a light object -- for andrew
-// should deprecate this once there is a general method for setting light properties of objects
-
-const int PART_SYS_SPAWN_COPY_BYTE = 0; // indicates whether to spawn baby particle systems on
-const int PART_SYS_SPAWN_COPY_BIT = 0x10; // particle death -- intended for smoke trails
-
-const int PART_SYS_COPY_VEL_BYTE = 0; // indicates whether baby particle systems inherit parents vel
-const int PART_SYS_COPY_VEL_BIT = 0x20; // (by default they don't)
-
-const int PART_SYS_INVISIBLE_BYTE = 0; // optional -- turn off display, just simulate
-const int PART_SYS_INVISIBLE_BIT = 0x40; // useful for smoke trails
-
-const int PART_SYS_ADAPT_TO_FRAMERATE_BYTE = 0; // drop sprites from render call proportionally
-const int PART_SYS_ADAPT_TO_FRAMERATE_BIT = 0x80; // to how far we are below 60 fps
-
-
-// 26 September 2001 - not even big enough to hold all changes, so should enlarge anyway
-//const U16 MAX_PART_SYS_PACKET_SIZE = 180;
-const U16 MAX_PART_SYS_PACKET_SIZE = 256;
-
-//const U8 PART_SYS_K_MASK = 0x01;
-const U8 PART_SYS_KILL_P_MASK = 0x02;
-const U8 PART_SYS_BOUNCE_P_MASK = 0x04;
-const U8 PART_SYS_BOUNCE_B_MASK = 0x08;
-//const U8 PART_SYS_POS_RANGES_MASK = 0x10;
-//const U8 PART_SYS_VEL_RANGES_MASK = 0x20;
-const U8 PART_SYS_VEL_OFFSET_MASK = 0x10; //re-use one of the original slots now commented out
-const U8 PART_SYS_ALPHA_SCALE_DIFF_MASK = 0x20; //re-use one of the original slots now commented out
-const U8 PART_SYS_SCALE_RANGE_MASK = 0x40;
-const U8 PART_SYS_M_IMAGE_UUID_MASK = 0x80;
-const U8 PART_SYS_BYTE_3_ALPHA_MASK = 0x01; // wrapped around, didn't we?
-
-const U8 PART_SYS_BYTE_SPAWN_MASK = 0x01;
-const U8 PART_SYS_BYTE_ENVIRONMENT_MASK = 0x02;
-const U8 PART_SYS_BYTE_LIFESPAN_MASK = 0x04;
-const U8 PART_SYS_BYTE_DECAY_DAMP_MASK = 0x08;
-const U8 PART_SYS_BYTE_WIND_DIFF_MASK = 0x10;
-
-
-// 26 September 2001 - new constants for mActionFlags
-const int PART_SYS_ACTION_BYTE = 1;
-const U8 PART_SYS_SPAWN = 0x01;
-const U8 PART_SYS_BOUNCE = 0x02;
-const U8 PART_SYS_AFFECTED_BY_WIND = 0x04;
-const U8 PART_SYS_AFFECTED_BY_GRAVITY = 0x08;
-const U8 PART_SYS_EVALUATE_WIND_PER_PARTICLE = 0x10;
-const U8 PART_SYS_DAMP_MOTION = 0x20;
-const U8 PART_SYS_WIND_DIFFUSION = 0x40;
-
-// 26 September 2001 - new constants for mKillFlags
-const int PART_SYS_KILL_BYTE = 2;
-const U8 PART_SYS_KILL_PLANE = 0x01;
-const U8 PART_SYS_GLOBAL_DIE = 0x02;
-const U8 PART_SYS_DISTANCE_DEATH = 0x04;
-const U8 PART_SYS_TIME_DEATH = 0x08;
-
-
-// global, because the sim-side also calls it in the LLPartInitDataFactory
-
-
-void gSetInitDataDefaults(LLPartInitData *setMe);
-
-class LLPartSysCompressedPacket
-{
-public:
- LLPartSysCompressedPacket();
- ~LLPartSysCompressedPacket();
- bool fromLLPartInitData(LLPartInitData *in, U32 &bytesUsed);
- bool toLLPartInitData(LLPartInitData *out, U32 *bytesUsed);
- bool fromUnsignedBytes(U8 *in, U32 bytesUsed);
- bool toUnsignedBytes(U8 *out);
- U32 bufferSize();
- U8 *getBytePtr();
-
-protected:
- U8 mData[MAX_PART_SYS_PACKET_SIZE];
- U32 mNumBytes;
- LLPartInitData mDefaults; // this is intended to hold default LLPartInitData values
- // please do not modify it
- LLPartInitData mWorkingCopy; // uncompressed data I'm working with
-
-protected:
- // private functions (used only to break up code)
- void writeFlagByte(LLPartInitData *in);
- //U32 writeK(LLPartInitData *in, U32 startByte);
- U32 writeKill_p(LLPartInitData *in, U32 startByte);
- U32 writeBounce_p(LLPartInitData *in, U32 startByte);
- U32 writeBounce_b(LLPartInitData *in, U32 startByte);
- //U32 writePos_ranges(LLPartInitData *in, U32 startByte);
- //U32 writeVel_ranges(LLPartInitData *in, U32 startByte);
- U32 writeAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte);
- U32 writeScale_range(LLPartInitData *in, U32 startByte);
- U32 writeAlpha_range(LLPartInitData *in, U32 startByte);
- U32 writeUUID(LLPartInitData *in, U32 startByte);
-
- U32 writeVelocityOffset(LLPartInitData *in, U32 startByte);
- U32 writeSpawn(LLPartInitData *in, U32 startByte); //all spawn data
- U32 writeEnvironment(LLPartInitData *in, U32 startByte); //wind and gravity
- U32 writeLifespan(LLPartInitData *in, U32 startByte); //lifespan data - individual and global
- U32 writeDecayDamp(LLPartInitData *in, U32 startByte); //alpha and scale, and motion damp
- U32 writeWindDiffusionFactor(LLPartInitData *in, U32 startByte);
-
-
- //U32 readK(LLPartInitData *in, U32 startByte);
- U32 readKill_p(LLPartInitData *in, U32 startByte);
- U32 readBounce_p(LLPartInitData *in, U32 startByte);
- U32 readBounce_b(LLPartInitData *in, U32 startByte);
- //U32 readPos_ranges(LLPartInitData *in, U32 startByte);
- //U32 readVel_ranges(LLPartInitData *in, U32 startByte);
- U32 readAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte);
- U32 readScale_range(LLPartInitData *in, U32 startByte);
- U32 readAlpha_range(LLPartInitData *in, U32 startByte);
- U32 readUUID(LLPartInitData *in, U32 startByte);
-
- U32 readVelocityOffset(LLPartInitData *in, U32 startByte);
- U32 readSpawn(LLPartInitData *in, U32 startByte); //all spawn data
- U32 readEnvironment(LLPartInitData *in, U32 startByte); //wind and gravity
- U32 readLifespan(LLPartInitData *in, U32 startByte); //lifespan data - individual and global
- U32 readDecayDamp(LLPartInitData *in, U32 startByte); //alpha and scale, and motion damp
- U32 readWindDiffusionFactor(LLPartInitData *in, U32 startByte);
-};
-
-#endif
-
+/**
+ * @file partsyspacket.h
+ * @brief Object for packing particle system initialization parameters
+ * before sending them over the network
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_PARTSYSPACKET_H
+#define LL_PARTSYSPACKET_H
+
+#include "lluuid.h"
+
+// Particle system stuff
+
+const U64 PART_SYS_MAX_TIME_IN_USEC = 1000000; // 1 second, die not quite near instantaneously
+
+
+// this struct is for particle system initialization parameters
+// I'm breaking some rules here, but I need a storage structure to hold initialization data
+// for these things. Sorry guys, they're not simple enough (yet) to avoid this cleanly
+struct LLPartInitData {
+ // please do not add functions to this class -- data only!
+ //F32 k[18]; // first 9 --> x,y,z last 9 --> scale, alpha, rot
+ //F32 kill_p[6]; // last one is for particles that die when they reach a spherical bounding radius
+ //F32 kill_plane[3];
+ //F32 bounce_p[5];
+ F32 bounce_b; // recently changed
+ // no need to store orientation and position here, as they're sent over seperately
+ //F32 pos_ranges[6];
+ //F32 vel_ranges[6];
+ F32 scale_range[4];
+ F32 alpha_range[4];
+ F32 vel_offset[3]; //new - more understandable!
+
+ F32 mDistBeginFadeout; // for fadeout LOD optimization
+ F32 mDistEndFadeout;
+
+ LLUUID mImageUuid;
+ //U8 n; // number of particles
+ U8 mFlags[8]; // for miscellaneous data --> its interpretation can change at my whim!
+ U8 createMe; // do I need to be created? or has the work allready been done?
+ //ActionFlag is now mFlags[PART_SYS_ACTION_BYTE]
+ //Spawn point is initially object creation center
+
+ F32 diffEqAlpha[3];
+ F32 diffEqScale[3];
+
+ U8 maxParticles;
+ //How many particles exist at any time within the system?
+ U8 initialParticles;
+ //How many particles exist when the system is created?
+ F32 killPlaneZ;
+ //For simplicity assume the XY plane, so this sets an altitude at which to die
+ F32 killPlaneNormal[3];
+ //Normal if not planar XY
+ F32 bouncePlaneZ;
+ //For simplicity assume the XY plane, so this sets an altitude at which to bounce
+ F32 bouncePlaneNormal[3];
+ //Normal if not planar XY
+ F32 spawnRange;
+ //Range of emission points about the mSpawnPoint
+ F32 spawnFrequency;
+ //Required if the system is to spawn new particles.
+ //This variable determines the time after a particle dies when it is respawned.
+ F32 spawnFreqencyRange;
+ //Determines the random range of time until a new particle is spawned.
+ F32 spawnDirection[3];
+ //Direction vector giving the mean direction in which particles are spawned
+ F32 spawnDirectionRange;
+ //Direction limiting the angular range of emissions about the mean direction. 1.0f means everywhere, 0.0f means uni-directional
+ F32 spawnVelocity;
+ //The mean speed at which particles are emitted
+ F32 spawnVelocityRange;
+ //The range of speeds about the mean at which particles are emitted.
+ F32 speedLimit;
+ //Used to constrain particle maximum velocity
+ F32 windWeight;
+ //How much of an effect does wind have
+ F32 currentGravity[3];
+ //Gravity direction used in update calculations
+ F32 gravityWeight;
+ //How much of an effect does gravity have
+ F32 globalLifetime;
+ //If particles re-spawn, a system can exist forever.
+ //If (ActionFlags & PART_SYS_GLOBAL_DIE) is true this variable is used to determine how long the system lasts.
+ F32 individualLifetime;
+ //How long does each particle last if nothing else happens to it
+ F32 individualLifetimeRange;
+ //Range of variation in individual lifetimes
+ F32 alphaDecay;
+ //By what factor does alpha decrease as the lifetime of a particle is approached.
+ F32 scaleDecay;
+ //By what factor does scale decrease as the lifetime of a particle is approached.
+ F32 distanceDeath;
+ //With the increased functionality, particle systems can expand to indefinite size
+ //(e.g. wind can chaotically move particles into a wide spread).
+ //To avoid particles exceeding normal object size constraints,
+ //set the PART_SYS_DISTANCE_DEATH flag, and set a distance value here, representing a radius around the spawn point.
+ F32 dampMotionFactor;
+ //How much to damp motion
+ F32 windDiffusionFactor[3];
+ //Change the size and alpha of particles as wind speed increases (scale gets bigger, alpha smaller)
+};
+
+// constants for setting flag values
+// BYTES are in range 0-8, bits are in range 2^0 - 2^8 and can only be powers of two
+const int PART_SYS_NO_Z_BUFFER_BYTE = 0; // option to turn off z-buffer when rendering
+const int PART_SYS_NO_Z_BUFFER_BIT = 2; // particle systems --
+// I advise against using this, as it looks bad in every case I've tried
+
+const int PART_SYS_SLOW_ANIM_BYTE = 0; // slow animation down by a factor of 10
+const int PART_SYS_SLOW_ANIM_BIT = 1; // useful for tweaking anims during debugging
+
+const int PART_SYS_FOLLOW_VEL_BYTE = 0; // indicates whether to orient sprites towards
+const int PART_SYS_FOLLOW_VEL_BIT = 4; // their velocity vector -- default is false
+
+const int PART_SYS_IS_LIGHT_BYTE = 0; // indicates whether a particular particle system
+const int PART_SYS_IS_LIGHT_BIT = 8; // is also a light object -- for andrew
+// should deprecate this once there is a general method for setting light properties of objects
+
+const int PART_SYS_SPAWN_COPY_BYTE = 0; // indicates whether to spawn baby particle systems on
+const int PART_SYS_SPAWN_COPY_BIT = 0x10; // particle death -- intended for smoke trails
+
+const int PART_SYS_COPY_VEL_BYTE = 0; // indicates whether baby particle systems inherit parents vel
+const int PART_SYS_COPY_VEL_BIT = 0x20; // (by default they don't)
+
+const int PART_SYS_INVISIBLE_BYTE = 0; // optional -- turn off display, just simulate
+const int PART_SYS_INVISIBLE_BIT = 0x40; // useful for smoke trails
+
+const int PART_SYS_ADAPT_TO_FRAMERATE_BYTE = 0; // drop sprites from render call proportionally
+const int PART_SYS_ADAPT_TO_FRAMERATE_BIT = 0x80; // to how far we are below 60 fps
+
+
+// 26 September 2001 - not even big enough to hold all changes, so should enlarge anyway
+//const U16 MAX_PART_SYS_PACKET_SIZE = 180;
+const U16 MAX_PART_SYS_PACKET_SIZE = 256;
+
+//const U8 PART_SYS_K_MASK = 0x01;
+const U8 PART_SYS_KILL_P_MASK = 0x02;
+const U8 PART_SYS_BOUNCE_P_MASK = 0x04;
+const U8 PART_SYS_BOUNCE_B_MASK = 0x08;
+//const U8 PART_SYS_POS_RANGES_MASK = 0x10;
+//const U8 PART_SYS_VEL_RANGES_MASK = 0x20;
+const U8 PART_SYS_VEL_OFFSET_MASK = 0x10; //re-use one of the original slots now commented out
+const U8 PART_SYS_ALPHA_SCALE_DIFF_MASK = 0x20; //re-use one of the original slots now commented out
+const U8 PART_SYS_SCALE_RANGE_MASK = 0x40;
+const U8 PART_SYS_M_IMAGE_UUID_MASK = 0x80;
+const U8 PART_SYS_BYTE_3_ALPHA_MASK = 0x01; // wrapped around, didn't we?
+
+const U8 PART_SYS_BYTE_SPAWN_MASK = 0x01;
+const U8 PART_SYS_BYTE_ENVIRONMENT_MASK = 0x02;
+const U8 PART_SYS_BYTE_LIFESPAN_MASK = 0x04;
+const U8 PART_SYS_BYTE_DECAY_DAMP_MASK = 0x08;
+const U8 PART_SYS_BYTE_WIND_DIFF_MASK = 0x10;
+
+
+// 26 September 2001 - new constants for mActionFlags
+const int PART_SYS_ACTION_BYTE = 1;
+const U8 PART_SYS_SPAWN = 0x01;
+const U8 PART_SYS_BOUNCE = 0x02;
+const U8 PART_SYS_AFFECTED_BY_WIND = 0x04;
+const U8 PART_SYS_AFFECTED_BY_GRAVITY = 0x08;
+const U8 PART_SYS_EVALUATE_WIND_PER_PARTICLE = 0x10;
+const U8 PART_SYS_DAMP_MOTION = 0x20;
+const U8 PART_SYS_WIND_DIFFUSION = 0x40;
+
+// 26 September 2001 - new constants for mKillFlags
+const int PART_SYS_KILL_BYTE = 2;
+const U8 PART_SYS_KILL_PLANE = 0x01;
+const U8 PART_SYS_GLOBAL_DIE = 0x02;
+const U8 PART_SYS_DISTANCE_DEATH = 0x04;
+const U8 PART_SYS_TIME_DEATH = 0x08;
+
+
+// global, because the sim-side also calls it in the LLPartInitDataFactory
+
+
+void gSetInitDataDefaults(LLPartInitData *setMe);
+
+class LLPartSysCompressedPacket
+{
+public:
+ LLPartSysCompressedPacket();
+ ~LLPartSysCompressedPacket();
+ bool fromLLPartInitData(LLPartInitData *in, U32 &bytesUsed);
+ bool toLLPartInitData(LLPartInitData *out, U32 *bytesUsed);
+ bool fromUnsignedBytes(U8 *in, U32 bytesUsed);
+ bool toUnsignedBytes(U8 *out);
+ U32 bufferSize();
+ U8 *getBytePtr();
+
+protected:
+ U8 mData[MAX_PART_SYS_PACKET_SIZE];
+ U32 mNumBytes;
+ LLPartInitData mDefaults; // this is intended to hold default LLPartInitData values
+ // please do not modify it
+ LLPartInitData mWorkingCopy; // uncompressed data I'm working with
+
+protected:
+ // private functions (used only to break up code)
+ void writeFlagByte(LLPartInitData *in);
+ //U32 writeK(LLPartInitData *in, U32 startByte);
+ U32 writeKill_p(LLPartInitData *in, U32 startByte);
+ U32 writeBounce_p(LLPartInitData *in, U32 startByte);
+ U32 writeBounce_b(LLPartInitData *in, U32 startByte);
+ //U32 writePos_ranges(LLPartInitData *in, U32 startByte);
+ //U32 writeVel_ranges(LLPartInitData *in, U32 startByte);
+ U32 writeAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte);
+ U32 writeScale_range(LLPartInitData *in, U32 startByte);
+ U32 writeAlpha_range(LLPartInitData *in, U32 startByte);
+ U32 writeUUID(LLPartInitData *in, U32 startByte);
+
+ U32 writeVelocityOffset(LLPartInitData *in, U32 startByte);
+ U32 writeSpawn(LLPartInitData *in, U32 startByte); //all spawn data
+ U32 writeEnvironment(LLPartInitData *in, U32 startByte); //wind and gravity
+ U32 writeLifespan(LLPartInitData *in, U32 startByte); //lifespan data - individual and global
+ U32 writeDecayDamp(LLPartInitData *in, U32 startByte); //alpha and scale, and motion damp
+ U32 writeWindDiffusionFactor(LLPartInitData *in, U32 startByte);
+
+
+ //U32 readK(LLPartInitData *in, U32 startByte);
+ U32 readKill_p(LLPartInitData *in, U32 startByte);
+ U32 readBounce_p(LLPartInitData *in, U32 startByte);
+ U32 readBounce_b(LLPartInitData *in, U32 startByte);
+ //U32 readPos_ranges(LLPartInitData *in, U32 startByte);
+ //U32 readVel_ranges(LLPartInitData *in, U32 startByte);
+ U32 readAlphaScaleDiffEqn_range(LLPartInitData *in, U32 startByte);
+ U32 readScale_range(LLPartInitData *in, U32 startByte);
+ U32 readAlpha_range(LLPartInitData *in, U32 startByte);
+ U32 readUUID(LLPartInitData *in, U32 startByte);
+
+ U32 readVelocityOffset(LLPartInitData *in, U32 startByte);
+ U32 readSpawn(LLPartInitData *in, U32 startByte); //all spawn data
+ U32 readEnvironment(LLPartInitData *in, U32 startByte); //wind and gravity
+ U32 readLifespan(LLPartInitData *in, U32 startByte); //lifespan data - individual and global
+ U32 readDecayDamp(LLPartInitData *in, U32 startByte); //alpha and scale, and motion damp
+ U32 readWindDiffusionFactor(LLPartInitData *in, U32 startByte);
+};
+
+#endif
+
diff --git a/indra/llmessage/patch_code.cpp b/indra/llmessage/patch_code.cpp
index c3c3e2b3b3..5c9dc5ad87 100644
--- a/indra/llmessage/patch_code.cpp
+++ b/indra/llmessage/patch_code.cpp
@@ -1,408 +1,408 @@
-/**
- * @file patch_code.cpp
- * @brief Encode patch DCT data into bitcode.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llmath.h"
-//#include "vmath.h"
-#include "v3math.h"
-#include "patch_dct.h"
-#include "patch_code.h"
-#include "llbitpack.h"
-
-U32 gPatchSize, gWordBits;
-
-void init_patch_coding(LLBitPack &bitpack)
-{
- bitpack.resetBitPacking();
-}
-
-void code_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
-{
-#ifdef LL_BIG_ENDIAN
- U8 *stride = (U8 *)&gopp->stride;
- bitpack.bitPack(&(stride[1]), 8);
- bitpack.bitPack(&(stride[0]), 8);
-#else
- bitpack.bitPack((U8 *)&gopp->stride, 16);
-#endif
- bitpack.bitPack((U8 *)&gopp->patch_size, 8);
- bitpack.bitPack((U8 *)&gopp->layer_type, 8);
-
- gPatchSize = gopp->patch_size;
-}
-
-void code_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, S32 *patch)
-{
- S32 i, j, temp, patch_size = gPatchSize, wbits = (ph->quant_wbits & 0xf) + 2;
- U32 max_wbits = wbits + 5, min_wbits = wbits>>1;
-
- wbits = min_wbits;
-
- for (i = 0; i < (int) patch_size*patch_size; i++)
- {
- temp = patch[i];
- if (temp)
- {
- if (temp < 0)
- temp *= -1;
- for (j = max_wbits; j > (int) min_wbits; j--)
- {
- if (temp & (1<<j))
- {
- if (j > wbits)
- wbits = j;
- break;
- }
- }
- }
- }
-
- wbits += 1;
-
- ph->quant_wbits &= 0xf0;
-
- if ( (wbits > 17)
- ||(wbits < 2))
- {
- LL_ERRS() << "Bits needed per word in code_patch_header out of legal range. Adjust compression quatization." << LL_ENDL;
- }
-
- ph->quant_wbits |= (wbits - 2);
-
- bitpack.bitPack((U8 *)&ph->quant_wbits, 8);
-#ifdef LL_BIG_ENDIAN
- U8 *offset = (U8 *)&ph->dc_offset;
- bitpack.bitPack(&(offset[3]), 8);
- bitpack.bitPack(&(offset[2]), 8);
- bitpack.bitPack(&(offset[1]), 8);
- bitpack.bitPack(&(offset[0]), 8);
-#else
- bitpack.bitPack((U8 *)&ph->dc_offset, 32);
-#endif
-#ifdef LL_BIG_ENDIAN
- U8 *range = (U8 *)&ph->range;
- bitpack.bitPack(&(range[1]), 8);
- bitpack.bitPack(&(range[0]), 8);
-#else
- bitpack.bitPack((U8 *)&ph->range, 16);
-#endif
-#ifdef LL_BIG_ENDIAN
- U8 *ids = (U8 *)&ph->patchids;
- bitpack.bitPack(&(ids[1]), 8);
- bitpack.bitPack(&(ids[0]), 2);
-#else
- bitpack.bitPack((U8 *)&ph->patchids, 10);
-#endif
-
- gWordBits = wbits;
-}
-
-void code_end_of_data(LLBitPack &bitpack)
-{
- bitpack.bitPack((U8 *)&END_OF_PATCHES, 8);
-}
-
-void code_patch(LLBitPack &bitpack, S32 *patch, S32 postquant)
-{
- S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
- S32 temp;
- bool b_eob;
-
- if ( (postquant > patch_size*patch_size)
- ||(postquant < 0))
- {
- LL_ERRS() << "Bad postquant in code_patch!" << LL_ENDL;
- }
-
- if (postquant)
- patch[patch_size*patch_size - postquant] = 0;
-
- for (i = 0; i < patch_size*patch_size; i++)
- {
- b_eob = false;
- temp = patch[i];
- if (!temp)
- {
- b_eob = true;
- for (j = i; j < patch_size*patch_size - postquant; j++)
- {
- if (patch[j])
- {
- b_eob = false;
- break;
- }
- }
- if (b_eob)
- {
- bitpack.bitPack((U8 *)&ZERO_EOB, 2);
- return;
- }
- else
- {
- bitpack.bitPack((U8 *)&ZERO_CODE, 1);
- }
- }
- else
- {
- if (temp < 0)
- {
- temp *= -1;
- if (temp > (1<<wbits))
- {
- temp = (1<<wbits);
-// printf("patch quatization exceeding allowable bits!");
- }
- bitpack.bitPack((U8 *)&NEGATIVE_VALUE, 3);
- bitpack.bitPack((U8 *)&temp, wbits);
- }
- else
- {
- if (temp > (1<<wbits))
- {
- temp = (1<<wbits);
-// printf("patch quatization exceeding allowable bits!");
- }
- bitpack.bitPack((U8 *)&POSITIVE_VALUE, 3);
- bitpack.bitPack((U8 *)&temp, wbits);
- }
- }
- }
-}
-
-
-void end_patch_coding(LLBitPack &bitpack)
-{
- bitpack.flushBitPack();
-}
-
-void init_patch_decoding(LLBitPack &bitpack)
-{
- bitpack.resetBitPacking();
-}
-
-void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
-{
- U16 retvalu16;
-
- retvalu16 = 0;
-#ifdef LL_BIG_ENDIAN
- U8 *ret = (U8 *)&retvalu16;
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), 8);
-#else
- bitpack.bitUnpack((U8 *)&retvalu16, 16);
-#endif
- gopp->stride = retvalu16;
-
- U8 retvalu8 = 0;
- bitpack.bitUnpack(&retvalu8, 8);
- gopp->patch_size = retvalu8;
-
- retvalu8 = 0;
- bitpack.bitUnpack(&retvalu8, 8);
- gopp->layer_type = retvalu8;
-
- gPatchSize = gopp->patch_size;
-}
-
-void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph)
-{
- U8 retvalu8;
-
- retvalu8 = 0;
- bitpack.bitUnpack(&retvalu8, 8);
- ph->quant_wbits = retvalu8;
-
- if (END_OF_PATCHES == ph->quant_wbits)
- {
- // End of data, blitz the rest.
- ph->dc_offset = 0;
- ph->range = 0;
- ph->patchids = 0;
- return;
- }
-
- U32 retvalu32 = 0;
-#ifdef LL_BIG_ENDIAN
- U8 *ret = (U8 *)&retvalu32;
- bitpack.bitUnpack(&(ret[3]), 8);
- bitpack.bitUnpack(&(ret[2]), 8);
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), 8);
-#else
- bitpack.bitUnpack((U8 *)&retvalu32, 32);
-#endif
- ph->dc_offset = *(F32 *)&retvalu32;
-
- U16 retvalu16 = 0;
-#ifdef LL_BIG_ENDIAN
- ret = (U8 *)&retvalu16;
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), 8);
-#else
- bitpack.bitUnpack((U8 *)&retvalu16, 16);
-#endif
- ph->range = retvalu16;
-
- retvalu16 = 0;
-#ifdef LL_BIG_ENDIAN
- ret = (U8 *)&retvalu16;
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), 2);
-#else
- bitpack.bitUnpack((U8 *)&retvalu16, 10);
-#endif
- ph->patchids = retvalu16;
-
- gWordBits = (ph->quant_wbits & 0xf) + 2;
-}
-
-void decode_patch(LLBitPack &bitpack, S32 *patches)
-{
-#ifdef LL_BIG_ENDIAN
- S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
- U8 tempu8;
- U16 tempu16;
- U32 tempu32;
- for (i = 0; i < patch_size*patch_size; i++)
- {
- bitpack.bitUnpack((U8 *)&tempu8, 1);
- if (tempu8)
- {
- // either 0 EOB or Value
- bitpack.bitUnpack((U8 *)&tempu8, 1);
- if (tempu8)
- {
- // value
- bitpack.bitUnpack((U8 *)&tempu8, 1);
- if (tempu8)
- {
- // negative
- patches[i] = -1;
- }
- else
- {
- // positive
- patches[i] = 1;
- }
- if (wbits <= 8)
- {
- bitpack.bitUnpack((U8 *)&tempu8, wbits);
- patches[i] *= tempu8;
- }
- else if (wbits <= 16)
- {
- tempu16 = 0;
- U8 *ret = (U8 *)&tempu16;
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), wbits - 8);
- patches[i] *= tempu16;
- }
- else if (wbits <= 24)
- {
- tempu32 = 0;
- U8 *ret = (U8 *)&tempu32;
- bitpack.bitUnpack(&(ret[2]), 8);
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), wbits - 16);
- patches[i] *= tempu32;
- }
- else if (wbits <= 32)
- {
- tempu32 = 0;
- U8 *ret = (U8 *)&tempu32;
- bitpack.bitUnpack(&(ret[3]), 8);
- bitpack.bitUnpack(&(ret[2]), 8);
- bitpack.bitUnpack(&(ret[1]), 8);
- bitpack.bitUnpack(&(ret[0]), wbits - 24);
- patches[i] *= tempu32;
- }
- }
- else
- {
- for (j = i; j < patch_size*patch_size; j++)
- {
- patches[j] = 0;
- }
- return;
- }
- }
- else
- {
- patches[i] = 0;
- }
- }
-#else
- S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
- U32 temp;
- for (i = 0; i < patch_size*patch_size; i++)
- {
- temp = 0;
- bitpack.bitUnpack((U8 *)&temp, 1);
- if (temp)
- {
- // either 0 EOB or Value
- temp = 0;
- bitpack.bitUnpack((U8 *)&temp, 1);
- if (temp)
- {
- // value
- temp = 0;
- bitpack.bitUnpack((U8 *)&temp, 1);
- if (temp)
- {
- // negative
- temp = 0;
- bitpack.bitUnpack((U8 *)&temp, wbits);
- patches[i] = temp;
- patches[i] *= -1;
- }
- else
- {
- // positive
- temp = 0;
- bitpack.bitUnpack((U8 *)&temp, wbits);
- patches[i] = temp;
- }
- }
- else
- {
- for (j = i; j < patch_size*patch_size; j++)
- {
- patches[j] = 0;
- }
- return;
- }
- }
- else
- {
- patches[i] = 0;
- }
- }
-#endif
-}
-
+/**
+ * @file patch_code.cpp
+ * @brief Encode patch DCT data into bitcode.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmath.h"
+//#include "vmath.h"
+#include "v3math.h"
+#include "patch_dct.h"
+#include "patch_code.h"
+#include "llbitpack.h"
+
+U32 gPatchSize, gWordBits;
+
+void init_patch_coding(LLBitPack &bitpack)
+{
+ bitpack.resetBitPacking();
+}
+
+void code_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
+{
+#ifdef LL_BIG_ENDIAN
+ U8 *stride = (U8 *)&gopp->stride;
+ bitpack.bitPack(&(stride[1]), 8);
+ bitpack.bitPack(&(stride[0]), 8);
+#else
+ bitpack.bitPack((U8 *)&gopp->stride, 16);
+#endif
+ bitpack.bitPack((U8 *)&gopp->patch_size, 8);
+ bitpack.bitPack((U8 *)&gopp->layer_type, 8);
+
+ gPatchSize = gopp->patch_size;
+}
+
+void code_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, S32 *patch)
+{
+ S32 i, j, temp, patch_size = gPatchSize, wbits = (ph->quant_wbits & 0xf) + 2;
+ U32 max_wbits = wbits + 5, min_wbits = wbits>>1;
+
+ wbits = min_wbits;
+
+ for (i = 0; i < (int) patch_size*patch_size; i++)
+ {
+ temp = patch[i];
+ if (temp)
+ {
+ if (temp < 0)
+ temp *= -1;
+ for (j = max_wbits; j > (int) min_wbits; j--)
+ {
+ if (temp & (1<<j))
+ {
+ if (j > wbits)
+ wbits = j;
+ break;
+ }
+ }
+ }
+ }
+
+ wbits += 1;
+
+ ph->quant_wbits &= 0xf0;
+
+ if ( (wbits > 17)
+ ||(wbits < 2))
+ {
+ LL_ERRS() << "Bits needed per word in code_patch_header out of legal range. Adjust compression quatization." << LL_ENDL;
+ }
+
+ ph->quant_wbits |= (wbits - 2);
+
+ bitpack.bitPack((U8 *)&ph->quant_wbits, 8);
+#ifdef LL_BIG_ENDIAN
+ U8 *offset = (U8 *)&ph->dc_offset;
+ bitpack.bitPack(&(offset[3]), 8);
+ bitpack.bitPack(&(offset[2]), 8);
+ bitpack.bitPack(&(offset[1]), 8);
+ bitpack.bitPack(&(offset[0]), 8);
+#else
+ bitpack.bitPack((U8 *)&ph->dc_offset, 32);
+#endif
+#ifdef LL_BIG_ENDIAN
+ U8 *range = (U8 *)&ph->range;
+ bitpack.bitPack(&(range[1]), 8);
+ bitpack.bitPack(&(range[0]), 8);
+#else
+ bitpack.bitPack((U8 *)&ph->range, 16);
+#endif
+#ifdef LL_BIG_ENDIAN
+ U8 *ids = (U8 *)&ph->patchids;
+ bitpack.bitPack(&(ids[1]), 8);
+ bitpack.bitPack(&(ids[0]), 2);
+#else
+ bitpack.bitPack((U8 *)&ph->patchids, 10);
+#endif
+
+ gWordBits = wbits;
+}
+
+void code_end_of_data(LLBitPack &bitpack)
+{
+ bitpack.bitPack((U8 *)&END_OF_PATCHES, 8);
+}
+
+void code_patch(LLBitPack &bitpack, S32 *patch, S32 postquant)
+{
+ S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
+ S32 temp;
+ bool b_eob;
+
+ if ( (postquant > patch_size*patch_size)
+ ||(postquant < 0))
+ {
+ LL_ERRS() << "Bad postquant in code_patch!" << LL_ENDL;
+ }
+
+ if (postquant)
+ patch[patch_size*patch_size - postquant] = 0;
+
+ for (i = 0; i < patch_size*patch_size; i++)
+ {
+ b_eob = false;
+ temp = patch[i];
+ if (!temp)
+ {
+ b_eob = true;
+ for (j = i; j < patch_size*patch_size - postquant; j++)
+ {
+ if (patch[j])
+ {
+ b_eob = false;
+ break;
+ }
+ }
+ if (b_eob)
+ {
+ bitpack.bitPack((U8 *)&ZERO_EOB, 2);
+ return;
+ }
+ else
+ {
+ bitpack.bitPack((U8 *)&ZERO_CODE, 1);
+ }
+ }
+ else
+ {
+ if (temp < 0)
+ {
+ temp *= -1;
+ if (temp > (1<<wbits))
+ {
+ temp = (1<<wbits);
+// printf("patch quatization exceeding allowable bits!");
+ }
+ bitpack.bitPack((U8 *)&NEGATIVE_VALUE, 3);
+ bitpack.bitPack((U8 *)&temp, wbits);
+ }
+ else
+ {
+ if (temp > (1<<wbits))
+ {
+ temp = (1<<wbits);
+// printf("patch quatization exceeding allowable bits!");
+ }
+ bitpack.bitPack((U8 *)&POSITIVE_VALUE, 3);
+ bitpack.bitPack((U8 *)&temp, wbits);
+ }
+ }
+ }
+}
+
+
+void end_patch_coding(LLBitPack &bitpack)
+{
+ bitpack.flushBitPack();
+}
+
+void init_patch_decoding(LLBitPack &bitpack)
+{
+ bitpack.resetBitPacking();
+}
+
+void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp)
+{
+ U16 retvalu16;
+
+ retvalu16 = 0;
+#ifdef LL_BIG_ENDIAN
+ U8 *ret = (U8 *)&retvalu16;
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), 8);
+#else
+ bitpack.bitUnpack((U8 *)&retvalu16, 16);
+#endif
+ gopp->stride = retvalu16;
+
+ U8 retvalu8 = 0;
+ bitpack.bitUnpack(&retvalu8, 8);
+ gopp->patch_size = retvalu8;
+
+ retvalu8 = 0;
+ bitpack.bitUnpack(&retvalu8, 8);
+ gopp->layer_type = retvalu8;
+
+ gPatchSize = gopp->patch_size;
+}
+
+void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph)
+{
+ U8 retvalu8;
+
+ retvalu8 = 0;
+ bitpack.bitUnpack(&retvalu8, 8);
+ ph->quant_wbits = retvalu8;
+
+ if (END_OF_PATCHES == ph->quant_wbits)
+ {
+ // End of data, blitz the rest.
+ ph->dc_offset = 0;
+ ph->range = 0;
+ ph->patchids = 0;
+ return;
+ }
+
+ U32 retvalu32 = 0;
+#ifdef LL_BIG_ENDIAN
+ U8 *ret = (U8 *)&retvalu32;
+ bitpack.bitUnpack(&(ret[3]), 8);
+ bitpack.bitUnpack(&(ret[2]), 8);
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), 8);
+#else
+ bitpack.bitUnpack((U8 *)&retvalu32, 32);
+#endif
+ ph->dc_offset = *(F32 *)&retvalu32;
+
+ U16 retvalu16 = 0;
+#ifdef LL_BIG_ENDIAN
+ ret = (U8 *)&retvalu16;
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), 8);
+#else
+ bitpack.bitUnpack((U8 *)&retvalu16, 16);
+#endif
+ ph->range = retvalu16;
+
+ retvalu16 = 0;
+#ifdef LL_BIG_ENDIAN
+ ret = (U8 *)&retvalu16;
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), 2);
+#else
+ bitpack.bitUnpack((U8 *)&retvalu16, 10);
+#endif
+ ph->patchids = retvalu16;
+
+ gWordBits = (ph->quant_wbits & 0xf) + 2;
+}
+
+void decode_patch(LLBitPack &bitpack, S32 *patches)
+{
+#ifdef LL_BIG_ENDIAN
+ S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
+ U8 tempu8;
+ U16 tempu16;
+ U32 tempu32;
+ for (i = 0; i < patch_size*patch_size; i++)
+ {
+ bitpack.bitUnpack((U8 *)&tempu8, 1);
+ if (tempu8)
+ {
+ // either 0 EOB or Value
+ bitpack.bitUnpack((U8 *)&tempu8, 1);
+ if (tempu8)
+ {
+ // value
+ bitpack.bitUnpack((U8 *)&tempu8, 1);
+ if (tempu8)
+ {
+ // negative
+ patches[i] = -1;
+ }
+ else
+ {
+ // positive
+ patches[i] = 1;
+ }
+ if (wbits <= 8)
+ {
+ bitpack.bitUnpack((U8 *)&tempu8, wbits);
+ patches[i] *= tempu8;
+ }
+ else if (wbits <= 16)
+ {
+ tempu16 = 0;
+ U8 *ret = (U8 *)&tempu16;
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), wbits - 8);
+ patches[i] *= tempu16;
+ }
+ else if (wbits <= 24)
+ {
+ tempu32 = 0;
+ U8 *ret = (U8 *)&tempu32;
+ bitpack.bitUnpack(&(ret[2]), 8);
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), wbits - 16);
+ patches[i] *= tempu32;
+ }
+ else if (wbits <= 32)
+ {
+ tempu32 = 0;
+ U8 *ret = (U8 *)&tempu32;
+ bitpack.bitUnpack(&(ret[3]), 8);
+ bitpack.bitUnpack(&(ret[2]), 8);
+ bitpack.bitUnpack(&(ret[1]), 8);
+ bitpack.bitUnpack(&(ret[0]), wbits - 24);
+ patches[i] *= tempu32;
+ }
+ }
+ else
+ {
+ for (j = i; j < patch_size*patch_size; j++)
+ {
+ patches[j] = 0;
+ }
+ return;
+ }
+ }
+ else
+ {
+ patches[i] = 0;
+ }
+ }
+#else
+ S32 i, j, patch_size = gPatchSize, wbits = gWordBits;
+ U32 temp;
+ for (i = 0; i < patch_size*patch_size; i++)
+ {
+ temp = 0;
+ bitpack.bitUnpack((U8 *)&temp, 1);
+ if (temp)
+ {
+ // either 0 EOB or Value
+ temp = 0;
+ bitpack.bitUnpack((U8 *)&temp, 1);
+ if (temp)
+ {
+ // value
+ temp = 0;
+ bitpack.bitUnpack((U8 *)&temp, 1);
+ if (temp)
+ {
+ // negative
+ temp = 0;
+ bitpack.bitUnpack((U8 *)&temp, wbits);
+ patches[i] = temp;
+ patches[i] *= -1;
+ }
+ else
+ {
+ // positive
+ temp = 0;
+ bitpack.bitUnpack((U8 *)&temp, wbits);
+ patches[i] = temp;
+ }
+ }
+ else
+ {
+ for (j = i; j < patch_size*patch_size; j++)
+ {
+ patches[j] = 0;
+ }
+ return;
+ }
+ }
+ else
+ {
+ patches[i] = 0;
+ }
+ }
+#endif
+}
+
diff --git a/indra/llmessage/patch_code.h b/indra/llmessage/patch_code.h
index 4c87c9808a..ee8bd58844 100644
--- a/indra/llmessage/patch_code.h
+++ b/indra/llmessage/patch_code.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file patch_code.h
* @brief Function declarations for encoding and decoding patches.
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -31,16 +31,16 @@ class LLBitPack;
class LLGroupHeader;
class LLPatchHeader;
-void init_patch_coding(LLBitPack &bitpack);
-void code_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp);
-void code_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, S32 *patch);
-void code_end_of_data(LLBitPack &bitpack);
-void code_patch(LLBitPack &bitpack, S32 *patch, S32 postquant);
-void end_patch_coding(LLBitPack &bitpack);
+void init_patch_coding(LLBitPack &bitpack);
+void code_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp);
+void code_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, S32 *patch);
+void code_end_of_data(LLBitPack &bitpack);
+void code_patch(LLBitPack &bitpack, S32 *patch, S32 postquant);
+void end_patch_coding(LLBitPack &bitpack);
-void init_patch_decoding(LLBitPack &bitpack);
-void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp);
-void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph);
-void decode_patch(LLBitPack &bitpack, S32 *patches);
+void init_patch_decoding(LLBitPack &bitpack);
+void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp);
+void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph);
+void decode_patch(LLBitPack &bitpack, S32 *patches);
#endif
diff --git a/indra/llmessage/patch_dct.cpp b/indra/llmessage/patch_dct.cpp
index 2144b4e712..10b3e5dd77 100644
--- a/indra/llmessage/patch_dct.cpp
+++ b/indra/llmessage/patch_dct.cpp
@@ -1,769 +1,769 @@
-/**
- * @file patch_dct.cpp
- * @brief DCT patch.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llmath.h"
-//#include "vmath.h"
-#include "v3math.h"
-#include "patch_dct.h"
-
-typedef struct s_patch_compress_global_data
-{
- S32 patch_size;
- S32 patch_stride;
- U32 charptr;
- S32 layer_type;
-} PCGD;
-
-PCGD gPatchCompressGlobalData;
-
-void reset_patch_compressor(void)
-{
- PCGD *pcp = &gPatchCompressGlobalData;
-
- pcp->charptr = 0;
-}
-
-S32 gCurrentSize = 0;
-
-F32 gPatchQuantizeTable[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-void build_patch_quantize_table(S32 size)
-{
- S32 i, j;
- for (j = 0; j < size; j++)
- {
- for (i = 0; i < size; i++)
- {
- gPatchQuantizeTable[j*size + i] = 1.f/(1.f + 2.f*(i+j));
- }
- }
-}
-
-F32 gPatchCosines[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-void setup_patch_cosines(S32 size)
-{
- S32 n, u;
- F32 oosob = F_PI*0.5f/size;
-
- for (u = 0; u < size; u++)
- {
- for (n = 0; n < size; n++)
- {
- gPatchCosines[u*size+n] = cosf((2.f*n+1.f)*u*oosob);
- }
- }
-}
-
-S32 gCopyMatrix[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-void build_copy_matrix(S32 size)
-{
- S32 i, j, count;
- bool b_diag = false;
- bool b_right = true;
-
- i = 0;
- j = 0;
- count = 0;
-
- while ( (i < size)
- &&(j < size))
- {
- gCopyMatrix[j*size + i] = count;
-
- count++;
-
- if (!b_diag)
- {
- if (b_right)
- {
- if (i < size - 1)
- i++;
- else
- j++;
- b_right = false;
- b_diag = true;
- }
- else
- {
- if (j < size - 1)
- j++;
- else
- i++;
- b_right = true;
- b_diag = true;
- }
- }
- else
- {
- if (b_right)
- {
- i++;
- j--;
- if ( (i == size - 1)
- ||(j == 0))
- {
- b_diag = false;
- }
- }
- else
- {
- i--;
- j++;
- if ( (i == 0)
- ||(j == size - 1))
- {
- b_diag = false;
- }
- }
- }
- }
-}
-
-
-void init_patch_compressor(S32 patch_size, S32 patch_stride, S32 layer_type)
-{
- PCGD *pcp = &gPatchCompressGlobalData;
-
- pcp->charptr = 0;
-
- pcp->patch_size = patch_size;
- pcp->patch_stride = patch_stride;
- pcp->layer_type = layer_type;
-
- if (patch_size != gCurrentSize)
- {
- gCurrentSize = patch_size;
- build_patch_quantize_table(patch_size);
- setup_patch_cosines(patch_size);
- build_copy_matrix(patch_size);
- }
-}
-
-void prescan_patch(F32 *patch, LLPatchHeader *php, F32 &zmax, F32 &zmin)
-{
- S32 i, j;
- PCGD *pcp = &gPatchCompressGlobalData;
- S32 stride = pcp->patch_stride;
- S32 size = pcp->patch_size;
- S32 jstride;
-
- zmax = -99999999.f;
- zmin = 99999999.f;
-
- for (j = 0; j < size; j++)
- {
- jstride = j*stride;
- for (i = 0; i < size; i++)
- {
- if (*(patch + jstride + i) > zmax)
- {
- zmax = *(patch + jstride + i);
- }
- if (*(patch + jstride + i) < zmin)
- {
- zmin = *(patch + jstride + i);
- }
- }
- }
-
- php->dc_offset = zmin;
- php->range = (U16) ((zmax - zmin) + 1.f);
-}
-
-void dct_line(F32 *linein, F32 *lineout, S32 line)
-{
- S32 u;
- F32 total;
- F32 *pcp = gPatchCosines;
- S32 line_size = line*NORMAL_PATCH_SIZE;
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- F32 *tlinein, *tpcp;
-
- tlinein = linein + line_size;
-
- total = *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein);
-
- *(lineout + line_size) = OO_SQRT2*total;
-
- for (u = 1; u < NORMAL_PATCH_SIZE; u++)
- {
- tlinein = linein + line_size;
- tpcp = pcp + (u<<4);
-
- total = *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein)*(*tpcp);
-
- *(lineout + line_size + u) = total;
- }
-#else
- S32 n;
- S32 size = gPatchCompressGlobalData.patch_size;
- total = 0.f;
- for (n = 0; n < size; n++)
- {
- total += linein[line_size + n];
- }
- lineout[line_size] = OO_SQRT2*total;
-
- for (u = 1; u < size; u++)
- {
- total = 0.f;
- for (n = 0; n < size; n++)
- {
- total += linein[line_size + n]*pcp[u*size+n];
- }
- lineout[line_size + u] = total;
- }
-#endif
-}
-
-void dct_line_large(F32 *linein, F32 *lineout, S32 line)
-{
- S32 u;
- F32 total;
- F32 *pcp = gPatchCosines;
- S32 line_size = line*LARGE_PATCH_SIZE;
-
- F32 *tlinein, *tpcp;
-
- tlinein = linein + line_size;
-
- total = *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
-
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein++);
- total += *(tlinein);
-
- *(lineout + line_size) = OO_SQRT2*total;
-
- for (u = 1; u < LARGE_PATCH_SIZE; u++)
- {
- tlinein = linein + line_size;
- tpcp = pcp + (u<<5);
-
- total = *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
-
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein++)*(*(tpcp++));
- total += *(tlinein)*(*tpcp);
-
- *(lineout + line_size + u) = total;
- }
-}
-
-inline void dct_column(F32 *linein, S32 *lineout, S32 column)
-{
- S32 u;
- F32 total;
- F32 oosob = 2.f/16.f;
- F32 *pcp = gPatchCosines;
- S32 *copy_matrix = gCopyMatrix;
- F32 *qt = gPatchQuantizeTable;
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- F32 *tlinein, *tpcp;
- S32 sizeu;
-
- tlinein = linein + column;
-
- total = *(tlinein);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
-
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
-
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
-
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
- total += *(tlinein += NORMAL_PATCH_SIZE);
-
- *(lineout + *(copy_matrix + column)) = (S32)(OO_SQRT2*total*oosob*(*(qt + column)));
-
- for (u = 1; u < NORMAL_PATCH_SIZE; u++)
- {
- tlinein = linein + column;
- tpcp = pcp + (u<<4);
-
- total = *(tlinein)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp));
-
- sizeu = NORMAL_PATCH_SIZE*u + column;
-
- *(lineout + *(copy_matrix + sizeu)) = (S32)(total*oosob*(*(qt+sizeu)));
- }
-#else
- S32 size = gPatchCompressGlobalData.patch_size;
- F32 oosob = 2.f/size;
- S32 n;
- total = 0.f;
- for (n = 0; n < size; n++)
- {
- total += linein[size*n + column];
- }
- lineout[copy_matrix[column]] = OO_SQRT2*total*oosob*qt[column];
-
- for (u = 1; u < size; u++)
- {
- total = 0.f;
- for (n = 0; n < size; n++)
- {
- total += linein[size*n + column]*pcp[u*size+n];
- }
- lineout[copy_matrix[size*u + column]] = total*oosob*qt[size*u + column];
- }
-#endif
-}
-
-inline void dct_column_large(F32 *linein, S32 *lineout, S32 column)
-{
- S32 u;
- F32 total;
- F32 oosob = 2.f/32.f;
- F32 *pcp = gPatchCosines;
- S32 *copy_matrix = gCopyMatrix;
- F32 *qt = gPatchQuantizeTable;
-
- F32 *tlinein, *tpcp;
- S32 sizeu;
-
- tlinein = linein + column;
-
- total = *(tlinein);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
- total += *(tlinein += LARGE_PATCH_SIZE);
-
- *(lineout + *(copy_matrix + column)) = (S32)(OO_SQRT2*total*oosob*(*(qt + column)));
-
- for (u = 1; u < LARGE_PATCH_SIZE; u++)
- {
- tlinein = linein + column;
- tpcp = pcp + (u<<5);
-
- total = *(tlinein)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp));
-
- sizeu = LARGE_PATCH_SIZE*u + column;
-
- *(lineout + *(copy_matrix + sizeu)) = (S32)(total*oosob*(*(qt+sizeu)));
- }
-}
-
-inline void dct_patch(F32 *block, S32 *cpatch)
-{
- F32 temp[NORMAL_PATCH_SIZE*NORMAL_PATCH_SIZE];
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- dct_line(block, temp, 0);
- dct_line(block, temp, 1);
- dct_line(block, temp, 2);
- dct_line(block, temp, 3);
-
- dct_line(block, temp, 4);
- dct_line(block, temp, 5);
- dct_line(block, temp, 6);
- dct_line(block, temp, 7);
-
- dct_line(block, temp, 8);
- dct_line(block, temp, 9);
- dct_line(block, temp, 10);
- dct_line(block, temp, 11);
-
- dct_line(block, temp, 12);
- dct_line(block, temp, 13);
- dct_line(block, temp, 14);
- dct_line(block, temp, 15);
-
- dct_column(temp, cpatch, 0);
- dct_column(temp, cpatch, 1);
- dct_column(temp, cpatch, 2);
- dct_column(temp, cpatch, 3);
-
- dct_column(temp, cpatch, 4);
- dct_column(temp, cpatch, 5);
- dct_column(temp, cpatch, 6);
- dct_column(temp, cpatch, 7);
-
- dct_column(temp, cpatch, 8);
- dct_column(temp, cpatch, 9);
- dct_column(temp, cpatch, 10);
- dct_column(temp, cpatch, 11);
-
- dct_column(temp, cpatch, 12);
- dct_column(temp, cpatch, 13);
- dct_column(temp, cpatch, 14);
- dct_column(temp, cpatch, 15);
-#else
- S32 i;
- S32 size = gPatchCompressGlobalData.patch_size;
- for (i = 0; i < size; i++)
- {
- dct_line(block, temp, i);
- }
- for (i = 0; i < size; i++)
- {
- dct_column(temp, cpatch, i);
- }
-#endif
-}
-
-inline void dct_patch_large(F32 *block, S32 *cpatch)
-{
- F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
- dct_line_large(block, temp, 0);
- dct_line_large(block, temp, 1);
- dct_line_large(block, temp, 2);
- dct_line_large(block, temp, 3);
-
- dct_line_large(block, temp, 4);
- dct_line_large(block, temp, 5);
- dct_line_large(block, temp, 6);
- dct_line_large(block, temp, 7);
-
- dct_line_large(block, temp, 8);
- dct_line_large(block, temp, 9);
- dct_line_large(block, temp, 10);
- dct_line_large(block, temp, 11);
-
- dct_line_large(block, temp, 12);
- dct_line_large(block, temp, 13);
- dct_line_large(block, temp, 14);
- dct_line_large(block, temp, 15);
-
- dct_line_large(block, temp, 16);
- dct_line_large(block, temp, 17);
- dct_line_large(block, temp, 18);
- dct_line_large(block, temp, 19);
-
- dct_line_large(block, temp, 20);
- dct_line_large(block, temp, 21);
- dct_line_large(block, temp, 22);
- dct_line_large(block, temp, 23);
-
- dct_line_large(block, temp, 24);
- dct_line_large(block, temp, 25);
- dct_line_large(block, temp, 26);
- dct_line_large(block, temp, 27);
-
- dct_line_large(block, temp, 28);
- dct_line_large(block, temp, 29);
- dct_line_large(block, temp, 30);
- dct_line_large(block, temp, 31);
-
- dct_column_large(temp, cpatch, 0);
- dct_column_large(temp, cpatch, 1);
- dct_column_large(temp, cpatch, 2);
- dct_column_large(temp, cpatch, 3);
-
- dct_column_large(temp, cpatch, 4);
- dct_column_large(temp, cpatch, 5);
- dct_column_large(temp, cpatch, 6);
- dct_column_large(temp, cpatch, 7);
-
- dct_column_large(temp, cpatch, 8);
- dct_column_large(temp, cpatch, 9);
- dct_column_large(temp, cpatch, 10);
- dct_column_large(temp, cpatch, 11);
-
- dct_column_large(temp, cpatch, 12);
- dct_column_large(temp, cpatch, 13);
- dct_column_large(temp, cpatch, 14);
- dct_column_large(temp, cpatch, 15);
-
- dct_column_large(temp, cpatch, 16);
- dct_column_large(temp, cpatch, 17);
- dct_column_large(temp, cpatch, 18);
- dct_column_large(temp, cpatch, 19);
-
- dct_column_large(temp, cpatch, 20);
- dct_column_large(temp, cpatch, 21);
- dct_column_large(temp, cpatch, 22);
- dct_column_large(temp, cpatch, 23);
-
- dct_column_large(temp, cpatch, 24);
- dct_column_large(temp, cpatch, 25);
- dct_column_large(temp, cpatch, 26);
- dct_column_large(temp, cpatch, 27);
-
- dct_column_large(temp, cpatch, 28);
- dct_column_large(temp, cpatch, 29);
- dct_column_large(temp, cpatch, 30);
- dct_column_large(temp, cpatch, 31);
-}
-
-void compress_patch(F32 *patch, S32 *cpatch, LLPatchHeader *php, S32 prequant)
-{
- S32 i, j;
- PCGD *pcp = &gPatchCompressGlobalData;
- S32 stride = pcp->patch_stride;
- S32 size = pcp->patch_size;
- F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock;
- F32 *tpatch;
-
- S32 wordsize = prequant;
- F32 oozrange = 1.f/php->range;
-
- F32 dc = php->dc_offset;
-
- S32 range = (1<<prequant);
- F32 premult = oozrange*range;
-// F32 sub = (F32)(1<<(prequant - 1));
- F32 sub = (F32)(1<<(prequant - 1)) + dc*premult;
-
- php->quant_wbits = wordsize - 2;
- php->quant_wbits |= (prequant - 2)<<4;
-
- for (j = 0; j < size; j++)
- {
- tblock = block + j*size;
- tpatch = patch + j*stride;
- for (i = 0; i < size; i++)
- {
-// block[j*size + i] = (patch[j*stride + i] - dc)*premult - sub;
- *(tblock++) = *(tpatch++)*premult - sub;
- }
- }
-
- if (size == 16)
- dct_patch(block, cpatch);
- else
- dct_patch_large(block, cpatch);
-}
-
-void get_patch_group_header(LLGroupHeader *gopp)
-{
- PCGD *pcp = &gPatchCompressGlobalData;
- gopp->stride = pcp->patch_stride;
- gopp->patch_size = pcp->patch_size;
- gopp->layer_type = pcp->layer_type;
-}
+/**
+ * @file patch_dct.cpp
+ * @brief DCT patch.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmath.h"
+//#include "vmath.h"
+#include "v3math.h"
+#include "patch_dct.h"
+
+typedef struct s_patch_compress_global_data
+{
+ S32 patch_size;
+ S32 patch_stride;
+ U32 charptr;
+ S32 layer_type;
+} PCGD;
+
+PCGD gPatchCompressGlobalData;
+
+void reset_patch_compressor(void)
+{
+ PCGD *pcp = &gPatchCompressGlobalData;
+
+ pcp->charptr = 0;
+}
+
+S32 gCurrentSize = 0;
+
+F32 gPatchQuantizeTable[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+void build_patch_quantize_table(S32 size)
+{
+ S32 i, j;
+ for (j = 0; j < size; j++)
+ {
+ for (i = 0; i < size; i++)
+ {
+ gPatchQuantizeTable[j*size + i] = 1.f/(1.f + 2.f*(i+j));
+ }
+ }
+}
+
+F32 gPatchCosines[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+void setup_patch_cosines(S32 size)
+{
+ S32 n, u;
+ F32 oosob = F_PI*0.5f/size;
+
+ for (u = 0; u < size; u++)
+ {
+ for (n = 0; n < size; n++)
+ {
+ gPatchCosines[u*size+n] = cosf((2.f*n+1.f)*u*oosob);
+ }
+ }
+}
+
+S32 gCopyMatrix[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+void build_copy_matrix(S32 size)
+{
+ S32 i, j, count;
+ bool b_diag = false;
+ bool b_right = true;
+
+ i = 0;
+ j = 0;
+ count = 0;
+
+ while ( (i < size)
+ &&(j < size))
+ {
+ gCopyMatrix[j*size + i] = count;
+
+ count++;
+
+ if (!b_diag)
+ {
+ if (b_right)
+ {
+ if (i < size - 1)
+ i++;
+ else
+ j++;
+ b_right = false;
+ b_diag = true;
+ }
+ else
+ {
+ if (j < size - 1)
+ j++;
+ else
+ i++;
+ b_right = true;
+ b_diag = true;
+ }
+ }
+ else
+ {
+ if (b_right)
+ {
+ i++;
+ j--;
+ if ( (i == size - 1)
+ ||(j == 0))
+ {
+ b_diag = false;
+ }
+ }
+ else
+ {
+ i--;
+ j++;
+ if ( (i == 0)
+ ||(j == size - 1))
+ {
+ b_diag = false;
+ }
+ }
+ }
+ }
+}
+
+
+void init_patch_compressor(S32 patch_size, S32 patch_stride, S32 layer_type)
+{
+ PCGD *pcp = &gPatchCompressGlobalData;
+
+ pcp->charptr = 0;
+
+ pcp->patch_size = patch_size;
+ pcp->patch_stride = patch_stride;
+ pcp->layer_type = layer_type;
+
+ if (patch_size != gCurrentSize)
+ {
+ gCurrentSize = patch_size;
+ build_patch_quantize_table(patch_size);
+ setup_patch_cosines(patch_size);
+ build_copy_matrix(patch_size);
+ }
+}
+
+void prescan_patch(F32 *patch, LLPatchHeader *php, F32 &zmax, F32 &zmin)
+{
+ S32 i, j;
+ PCGD *pcp = &gPatchCompressGlobalData;
+ S32 stride = pcp->patch_stride;
+ S32 size = pcp->patch_size;
+ S32 jstride;
+
+ zmax = -99999999.f;
+ zmin = 99999999.f;
+
+ for (j = 0; j < size; j++)
+ {
+ jstride = j*stride;
+ for (i = 0; i < size; i++)
+ {
+ if (*(patch + jstride + i) > zmax)
+ {
+ zmax = *(patch + jstride + i);
+ }
+ if (*(patch + jstride + i) < zmin)
+ {
+ zmin = *(patch + jstride + i);
+ }
+ }
+ }
+
+ php->dc_offset = zmin;
+ php->range = (U16) ((zmax - zmin) + 1.f);
+}
+
+void dct_line(F32 *linein, F32 *lineout, S32 line)
+{
+ S32 u;
+ F32 total;
+ F32 *pcp = gPatchCosines;
+ S32 line_size = line*NORMAL_PATCH_SIZE;
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ F32 *tlinein, *tpcp;
+
+ tlinein = linein + line_size;
+
+ total = *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein);
+
+ *(lineout + line_size) = OO_SQRT2*total;
+
+ for (u = 1; u < NORMAL_PATCH_SIZE; u++)
+ {
+ tlinein = linein + line_size;
+ tpcp = pcp + (u<<4);
+
+ total = *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein)*(*tpcp);
+
+ *(lineout + line_size + u) = total;
+ }
+#else
+ S32 n;
+ S32 size = gPatchCompressGlobalData.patch_size;
+ total = 0.f;
+ for (n = 0; n < size; n++)
+ {
+ total += linein[line_size + n];
+ }
+ lineout[line_size] = OO_SQRT2*total;
+
+ for (u = 1; u < size; u++)
+ {
+ total = 0.f;
+ for (n = 0; n < size; n++)
+ {
+ total += linein[line_size + n]*pcp[u*size+n];
+ }
+ lineout[line_size + u] = total;
+ }
+#endif
+}
+
+void dct_line_large(F32 *linein, F32 *lineout, S32 line)
+{
+ S32 u;
+ F32 total;
+ F32 *pcp = gPatchCosines;
+ S32 line_size = line*LARGE_PATCH_SIZE;
+
+ F32 *tlinein, *tpcp;
+
+ tlinein = linein + line_size;
+
+ total = *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein++);
+ total += *(tlinein);
+
+ *(lineout + line_size) = OO_SQRT2*total;
+
+ for (u = 1; u < LARGE_PATCH_SIZE; u++)
+ {
+ tlinein = linein + line_size;
+ tpcp = pcp + (u<<5);
+
+ total = *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein++)*(*(tpcp++));
+ total += *(tlinein)*(*tpcp);
+
+ *(lineout + line_size + u) = total;
+ }
+}
+
+inline void dct_column(F32 *linein, S32 *lineout, S32 column)
+{
+ S32 u;
+ F32 total;
+ F32 oosob = 2.f/16.f;
+ F32 *pcp = gPatchCosines;
+ S32 *copy_matrix = gCopyMatrix;
+ F32 *qt = gPatchQuantizeTable;
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ F32 *tlinein, *tpcp;
+ S32 sizeu;
+
+ tlinein = linein + column;
+
+ total = *(tlinein);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+ total += *(tlinein += NORMAL_PATCH_SIZE);
+
+ *(lineout + *(copy_matrix + column)) = (S32)(OO_SQRT2*total*oosob*(*(qt + column)));
+
+ for (u = 1; u < NORMAL_PATCH_SIZE; u++)
+ {
+ tlinein = linein + column;
+ tpcp = pcp + (u<<4);
+
+ total = *(tlinein)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp));
+
+ sizeu = NORMAL_PATCH_SIZE*u + column;
+
+ *(lineout + *(copy_matrix + sizeu)) = (S32)(total*oosob*(*(qt+sizeu)));
+ }
+#else
+ S32 size = gPatchCompressGlobalData.patch_size;
+ F32 oosob = 2.f/size;
+ S32 n;
+ total = 0.f;
+ for (n = 0; n < size; n++)
+ {
+ total += linein[size*n + column];
+ }
+ lineout[copy_matrix[column]] = OO_SQRT2*total*oosob*qt[column];
+
+ for (u = 1; u < size; u++)
+ {
+ total = 0.f;
+ for (n = 0; n < size; n++)
+ {
+ total += linein[size*n + column]*pcp[u*size+n];
+ }
+ lineout[copy_matrix[size*u + column]] = total*oosob*qt[size*u + column];
+ }
+#endif
+}
+
+inline void dct_column_large(F32 *linein, S32 *lineout, S32 column)
+{
+ S32 u;
+ F32 total;
+ F32 oosob = 2.f/32.f;
+ F32 *pcp = gPatchCosines;
+ S32 *copy_matrix = gCopyMatrix;
+ F32 *qt = gPatchQuantizeTable;
+
+ F32 *tlinein, *tpcp;
+ S32 sizeu;
+
+ tlinein = linein + column;
+
+ total = *(tlinein);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+ total += *(tlinein += LARGE_PATCH_SIZE);
+
+ *(lineout + *(copy_matrix + column)) = (S32)(OO_SQRT2*total*oosob*(*(qt + column)));
+
+ for (u = 1; u < LARGE_PATCH_SIZE; u++)
+ {
+ tlinein = linein + column;
+ tpcp = pcp + (u<<5);
+
+ total = *(tlinein)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp++));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp));
+
+ sizeu = LARGE_PATCH_SIZE*u + column;
+
+ *(lineout + *(copy_matrix + sizeu)) = (S32)(total*oosob*(*(qt+sizeu)));
+ }
+}
+
+inline void dct_patch(F32 *block, S32 *cpatch)
+{
+ F32 temp[NORMAL_PATCH_SIZE*NORMAL_PATCH_SIZE];
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ dct_line(block, temp, 0);
+ dct_line(block, temp, 1);
+ dct_line(block, temp, 2);
+ dct_line(block, temp, 3);
+
+ dct_line(block, temp, 4);
+ dct_line(block, temp, 5);
+ dct_line(block, temp, 6);
+ dct_line(block, temp, 7);
+
+ dct_line(block, temp, 8);
+ dct_line(block, temp, 9);
+ dct_line(block, temp, 10);
+ dct_line(block, temp, 11);
+
+ dct_line(block, temp, 12);
+ dct_line(block, temp, 13);
+ dct_line(block, temp, 14);
+ dct_line(block, temp, 15);
+
+ dct_column(temp, cpatch, 0);
+ dct_column(temp, cpatch, 1);
+ dct_column(temp, cpatch, 2);
+ dct_column(temp, cpatch, 3);
+
+ dct_column(temp, cpatch, 4);
+ dct_column(temp, cpatch, 5);
+ dct_column(temp, cpatch, 6);
+ dct_column(temp, cpatch, 7);
+
+ dct_column(temp, cpatch, 8);
+ dct_column(temp, cpatch, 9);
+ dct_column(temp, cpatch, 10);
+ dct_column(temp, cpatch, 11);
+
+ dct_column(temp, cpatch, 12);
+ dct_column(temp, cpatch, 13);
+ dct_column(temp, cpatch, 14);
+ dct_column(temp, cpatch, 15);
+#else
+ S32 i;
+ S32 size = gPatchCompressGlobalData.patch_size;
+ for (i = 0; i < size; i++)
+ {
+ dct_line(block, temp, i);
+ }
+ for (i = 0; i < size; i++)
+ {
+ dct_column(temp, cpatch, i);
+ }
+#endif
+}
+
+inline void dct_patch_large(F32 *block, S32 *cpatch)
+{
+ F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+ dct_line_large(block, temp, 0);
+ dct_line_large(block, temp, 1);
+ dct_line_large(block, temp, 2);
+ dct_line_large(block, temp, 3);
+
+ dct_line_large(block, temp, 4);
+ dct_line_large(block, temp, 5);
+ dct_line_large(block, temp, 6);
+ dct_line_large(block, temp, 7);
+
+ dct_line_large(block, temp, 8);
+ dct_line_large(block, temp, 9);
+ dct_line_large(block, temp, 10);
+ dct_line_large(block, temp, 11);
+
+ dct_line_large(block, temp, 12);
+ dct_line_large(block, temp, 13);
+ dct_line_large(block, temp, 14);
+ dct_line_large(block, temp, 15);
+
+ dct_line_large(block, temp, 16);
+ dct_line_large(block, temp, 17);
+ dct_line_large(block, temp, 18);
+ dct_line_large(block, temp, 19);
+
+ dct_line_large(block, temp, 20);
+ dct_line_large(block, temp, 21);
+ dct_line_large(block, temp, 22);
+ dct_line_large(block, temp, 23);
+
+ dct_line_large(block, temp, 24);
+ dct_line_large(block, temp, 25);
+ dct_line_large(block, temp, 26);
+ dct_line_large(block, temp, 27);
+
+ dct_line_large(block, temp, 28);
+ dct_line_large(block, temp, 29);
+ dct_line_large(block, temp, 30);
+ dct_line_large(block, temp, 31);
+
+ dct_column_large(temp, cpatch, 0);
+ dct_column_large(temp, cpatch, 1);
+ dct_column_large(temp, cpatch, 2);
+ dct_column_large(temp, cpatch, 3);
+
+ dct_column_large(temp, cpatch, 4);
+ dct_column_large(temp, cpatch, 5);
+ dct_column_large(temp, cpatch, 6);
+ dct_column_large(temp, cpatch, 7);
+
+ dct_column_large(temp, cpatch, 8);
+ dct_column_large(temp, cpatch, 9);
+ dct_column_large(temp, cpatch, 10);
+ dct_column_large(temp, cpatch, 11);
+
+ dct_column_large(temp, cpatch, 12);
+ dct_column_large(temp, cpatch, 13);
+ dct_column_large(temp, cpatch, 14);
+ dct_column_large(temp, cpatch, 15);
+
+ dct_column_large(temp, cpatch, 16);
+ dct_column_large(temp, cpatch, 17);
+ dct_column_large(temp, cpatch, 18);
+ dct_column_large(temp, cpatch, 19);
+
+ dct_column_large(temp, cpatch, 20);
+ dct_column_large(temp, cpatch, 21);
+ dct_column_large(temp, cpatch, 22);
+ dct_column_large(temp, cpatch, 23);
+
+ dct_column_large(temp, cpatch, 24);
+ dct_column_large(temp, cpatch, 25);
+ dct_column_large(temp, cpatch, 26);
+ dct_column_large(temp, cpatch, 27);
+
+ dct_column_large(temp, cpatch, 28);
+ dct_column_large(temp, cpatch, 29);
+ dct_column_large(temp, cpatch, 30);
+ dct_column_large(temp, cpatch, 31);
+}
+
+void compress_patch(F32 *patch, S32 *cpatch, LLPatchHeader *php, S32 prequant)
+{
+ S32 i, j;
+ PCGD *pcp = &gPatchCompressGlobalData;
+ S32 stride = pcp->patch_stride;
+ S32 size = pcp->patch_size;
+ F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock;
+ F32 *tpatch;
+
+ S32 wordsize = prequant;
+ F32 oozrange = 1.f/php->range;
+
+ F32 dc = php->dc_offset;
+
+ S32 range = (1<<prequant);
+ F32 premult = oozrange*range;
+// F32 sub = (F32)(1<<(prequant - 1));
+ F32 sub = (F32)(1<<(prequant - 1)) + dc*premult;
+
+ php->quant_wbits = wordsize - 2;
+ php->quant_wbits |= (prequant - 2)<<4;
+
+ for (j = 0; j < size; j++)
+ {
+ tblock = block + j*size;
+ tpatch = patch + j*stride;
+ for (i = 0; i < size; i++)
+ {
+// block[j*size + i] = (patch[j*stride + i] - dc)*premult - sub;
+ *(tblock++) = *(tpatch++)*premult - sub;
+ }
+ }
+
+ if (size == 16)
+ dct_patch(block, cpatch);
+ else
+ dct_patch_large(block, cpatch);
+}
+
+void get_patch_group_header(LLGroupHeader *gopp)
+{
+ PCGD *pcp = &gPatchCompressGlobalData;
+ gopp->stride = pcp->patch_stride;
+ gopp->patch_size = pcp->patch_size;
+ gopp->layer_type = pcp->layer_type;
+}
diff --git a/indra/llmessage/patch_dct.h b/indra/llmessage/patch_dct.h
index 101231ec84..8c270d99bf 100644
--- a/indra/llmessage/patch_dct.h
+++ b/indra/llmessage/patch_dct.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file patch_dct.h
* @brief Function declarations for DCT and IDCT routines
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,12 +30,12 @@
class LLVector3;
// Code Values
-const U8 ZERO_CODE = 0x0;
+const U8 ZERO_CODE = 0x0;
const U8 ZERO_EOB = 0x2;
const U8 POSITIVE_VALUE = 0x6;
const U8 NEGATIVE_VALUE = 0x7;
-const S8 NORMAL_PATCH_SIZE = 16;
+const S8 NORMAL_PATCH_SIZE = 16;
const S8 LARGE_PATCH_SIZE = 32;
const U8 END_OF_PATCHES = 97;
@@ -45,35 +45,35 @@ const U8 END_OF_PATCHES = 97;
// Top level header for group of headers
//typedef struct LL_Group_Header
//{
-// U16 stride; // 2 = 2
-// U8 patch_size; // 1 = 3
-// U8 layer_type; // 1 = 4
+// U16 stride; // 2 = 2
+// U8 patch_size; // 1 = 3
+// U8 layer_type; // 1 = 4
//} LLGroupHeader;
class LLGroupHeader
{
public:
- U16 stride; // 2 = 2
- U8 patch_size; // 1 = 3
- U8 layer_type; // 1 = 4
+ U16 stride; // 2 = 2
+ U8 patch_size; // 1 = 3
+ U8 layer_type; // 1 = 4
};
// Individual patch header
//typedef struct LL_Patch_Header
//{
-// F32 dc_offset; // 4 bytes
-// U16 range; // 2 = 7 ((S16) FP range (breaks if we need > 32K meters in 1 patch)
-// U8 quant_wbits; // 1 = 8 (upper 4 bits is quant - 2, lower 4 bits is word bits - 2)
-// U16 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each)
+// F32 dc_offset; // 4 bytes
+// U16 range; // 2 = 7 ((S16) FP range (breaks if we need > 32K meters in 1 patch)
+// U8 quant_wbits; // 1 = 8 (upper 4 bits is quant - 2, lower 4 bits is word bits - 2)
+// U16 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each)
//} LLPatchHeader;
class LLPatchHeader
{
public:
- F32 dc_offset; // 4 bytes
- U16 range; // 2 = 7 ((S16) FP range (breaks if we need > 32K meters in 1 patch)
- U8 quant_wbits; // 1 = 8 (upper 4 bits is quant - 2, lower 4 bits is word bits - 2)
- U16 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each)
+ F32 dc_offset; // 4 bytes
+ U16 range; // 2 = 7 ((S16) FP range (breaks if we need > 32K meters in 1 patch)
+ U8 quant_wbits; // 1 = 8 (upper 4 bits is quant - 2, lower 4 bits is word bits - 2)
+ U16 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each)
};
// Compression routines
diff --git a/indra/llmessage/patch_idct.cpp b/indra/llmessage/patch_idct.cpp
index 687c1734c5..c5320e22e3 100644
--- a/indra/llmessage/patch_idct.cpp
+++ b/indra/llmessage/patch_idct.cpp
@@ -1,684 +1,684 @@
-/**
- * @file patch_idct.cpp
- * @brief IDCT patch.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llmath.h"
-//#include "vmath.h"
-#include "v3math.h"
-#include "patch_dct.h"
-
-LLGroupHeader *gGOPP;
-
-void set_group_of_patch_header(LLGroupHeader *gopp)
-{
- gGOPP = gopp;
-}
-
-F32 gPatchDequantizeTable[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-void build_patch_dequantize_table(S32 size)
-{
- S32 i, j;
- for (j = 0; j < size; j++)
- {
- for (i = 0; i < size; i++)
- {
- gPatchDequantizeTable[j*size + i] = (1.f + 2.f*(i+j));
- }
- }
-}
-
-S32 gCurrentDeSize = 0;
-
-F32 gPatchICosines[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-void setup_patch_icosines(S32 size)
-{
- S32 n, u;
- F32 oosob = F_PI*0.5f/size;
-
- for (u = 0; u < size; u++)
- {
- for (n = 0; n < size; n++)
- {
- gPatchICosines[u*size+n] = cosf((2.f*n+1.f)*u*oosob);
- }
- }
-}
-
-S32 gDeCopyMatrix[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-void build_decopy_matrix(S32 size)
-{
- S32 i, j, count;
- bool b_diag = false;
- bool b_right = true;
-
- i = 0;
- j = 0;
- count = 0;
-
- while ( (i < size)
- &&(j < size))
- {
- gDeCopyMatrix[j*size + i] = count;
-
- count++;
-
- if (!b_diag)
- {
- if (b_right)
- {
- if (i < size - 1)
- i++;
- else
- j++;
- b_right = false;
- b_diag = true;
- }
- else
- {
- if (j < size - 1)
- j++;
- else
- i++;
- b_right = true;
- b_diag = true;
- }
- }
- else
- {
- if (b_right)
- {
- i++;
- j--;
- if ( (i == size - 1)
- ||(j == 0))
- {
- b_diag = false;
- }
- }
- else
- {
- i--;
- j++;
- if ( (i == 0)
- ||(j == size - 1))
- {
- b_diag = false;
- }
- }
- }
- }
-}
-
-void init_patch_decompressor(S32 size)
-{
- if (size != gCurrentDeSize)
- {
- gCurrentDeSize = size;
- build_patch_dequantize_table(size);
- setup_patch_icosines(size);
- build_decopy_matrix(size);
- }
-}
-
-inline void idct_line(F32 *linein, F32 *lineout, S32 line)
-{
- S32 n;
- F32 total;
- F32 *pcp = gPatchICosines;
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- F32 oosob = 2.f/16.f;
- S32 line_size = line*NORMAL_PATCH_SIZE;
- F32 *tlinein, *tpcp;
-
-
- for (n = 0; n < NORMAL_PATCH_SIZE; n++)
- {
- tpcp = pcp + n;
- tlinein = linein + line_size;
-
- total = OO_SQRT2*(*(tlinein++));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- *(lineout + line_size + n) = total*oosob;
- }
-#else
- F32 oosob = 2.f/size;
- S32 size = gGOPP->patch_size;
- S32 line_size = line*size;
- S32 u;
- for (n = 0; n < size; n++)
- {
- total = OO_SQRT2*linein[line_size];
- for (u = 1; u < size; u++)
- {
- total += linein[line_size + u]*pcp[u*size+n];
- }
- lineout[line_size + n] = total*oosob;
- }
-#endif
-}
-
-inline void idct_line_large_slow(F32 *linein, F32 *lineout, S32 line)
-{
- S32 n;
- F32 total;
- F32 *pcp = gPatchICosines;
-
- F32 oosob = 2.f/32.f;
- S32 line_size = line*LARGE_PATCH_SIZE;
- F32 *tlinein, *tpcp;
-
-
- for (n = 0; n < LARGE_PATCH_SIZE; n++)
- {
- tpcp = pcp + n;
- tlinein = linein + line_size;
-
- total = OO_SQRT2*(*(tlinein++));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein)*(*(tpcp += LARGE_PATCH_SIZE));
-
- *(lineout + line_size + n) = total*oosob;
- }
-}
-
-// Nota Bene: assumes that coefficients beyond 128 are 0!
-
-void idct_line_large(F32 *linein, F32 *lineout, S32 line)
-{
- S32 n;
- F32 total;
- F32 *pcp = gPatchICosines;
-
- F32 oosob = 2.f/32.f;
- S32 line_size = line*LARGE_PATCH_SIZE;
- F32 *tlinein, *tpcp;
- F32 *baselinein = linein + line_size;
- F32 *baselineout = lineout + line_size;
-
-
- for (n = 0; n < LARGE_PATCH_SIZE; n++)
- {
- tpcp = pcp++;
- tlinein = baselinein;
-
- total = OO_SQRT2*(*(tlinein++));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein)*(*(tpcp));
-
- *baselineout++ = total*oosob;
- }
-}
-
-inline void idct_column(F32 *linein, F32 *lineout, S32 column)
-{
- S32 n;
- F32 total;
- F32 *pcp = gPatchICosines;
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- F32 *tlinein, *tpcp;
-
- for (n = 0; n < NORMAL_PATCH_SIZE; n++)
- {
- tpcp = pcp + n;
- tlinein = linein + column;
-
- total = OO_SQRT2*(*tlinein);
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
- total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
-
- *(lineout + (n<<4) + column) = total;
- }
-
-#else
- S32 size = gGOPP->patch_size;
- S32 u;
- S32 u_size;
-
- for (n = 0; n < size; n++)
- {
- total = OO_SQRT2*linein[column];
- for (u = 1; u < size; u++)
- {
- u_size = u*size;
- total += linein[u_size + column]*pcp[u_size+n];
- }
- lineout[size*n + column] = total;
- }
-#endif
-}
-
-inline void idct_column_large_slow(F32 *linein, F32 *lineout, S32 column)
-{
- S32 n;
- F32 total;
- F32 *pcp = gPatchICosines;
-
- F32 *tlinein, *tpcp;
-
- for (n = 0; n < LARGE_PATCH_SIZE; n++)
- {
- tpcp = pcp + n;
- tlinein = linein + column;
-
- total = OO_SQRT2*(*tlinein);
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- *(lineout + (n<<5) + column) = total;
- }
-}
-
-// Nota Bene: assumes that coefficients beyond 128 are 0!
-
-void idct_column_large(F32 *linein, F32 *lineout, S32 column)
-{
- S32 n, m;
- F32 total;
- F32 *pcp = gPatchICosines;
-
- F32 *tlinein, *tpcp;
- F32 *baselinein = linein + column;
- F32 *baselineout = lineout + column;
-
- for (n = 0; n < LARGE_PATCH_SIZE; n++)
- {
- tpcp = pcp++;
- tlinein = baselinein;
-
- total = OO_SQRT2*(*tlinein);
- for (m = 1; m < NORMAL_PATCH_SIZE; m++)
- total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
-
- *(baselineout + (n<<5)) = total;
- }
-}
-
-inline void idct_patch(F32 *block)
-{
- F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
-#ifdef _PATCH_SIZE_16_AND_32_ONLY
- idct_column(block, temp, 0);
- idct_column(block, temp, 1);
- idct_column(block, temp, 2);
- idct_column(block, temp, 3);
-
- idct_column(block, temp, 4);
- idct_column(block, temp, 5);
- idct_column(block, temp, 6);
- idct_column(block, temp, 7);
-
- idct_column(block, temp, 8);
- idct_column(block, temp, 9);
- idct_column(block, temp, 10);
- idct_column(block, temp, 11);
-
- idct_column(block, temp, 12);
- idct_column(block, temp, 13);
- idct_column(block, temp, 14);
- idct_column(block, temp, 15);
-
- idct_line(temp, block, 0);
- idct_line(temp, block, 1);
- idct_line(temp, block, 2);
- idct_line(temp, block, 3);
-
- idct_line(temp, block, 4);
- idct_line(temp, block, 5);
- idct_line(temp, block, 6);
- idct_line(temp, block, 7);
-
- idct_line(temp, block, 8);
- idct_line(temp, block, 9);
- idct_line(temp, block, 10);
- idct_line(temp, block, 11);
-
- idct_line(temp, block, 12);
- idct_line(temp, block, 13);
- idct_line(temp, block, 14);
- idct_line(temp, block, 15);
-#else
- S32 i;
- S32 size = gGOPP->patch_size;
- for (i = 0; i < size; i++)
- {
- idct_column(block, temp, i);
- }
- for (i = 0; i < size; i++)
- {
- idct_line(temp, block, i);
- }
-#endif
-}
-
-inline void idct_patch_large(F32 *block)
-{
- F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
-
- idct_column_large_slow(block, temp, 0);
- idct_column_large_slow(block, temp, 1);
- idct_column_large_slow(block, temp, 2);
- idct_column_large_slow(block, temp, 3);
-
- idct_column_large_slow(block, temp, 4);
- idct_column_large_slow(block, temp, 5);
- idct_column_large_slow(block, temp, 6);
- idct_column_large_slow(block, temp, 7);
-
- idct_column_large_slow(block, temp, 8);
- idct_column_large_slow(block, temp, 9);
- idct_column_large_slow(block, temp, 10);
- idct_column_large_slow(block, temp, 11);
-
- idct_column_large_slow(block, temp, 12);
- idct_column_large_slow(block, temp, 13);
- idct_column_large_slow(block, temp, 14);
- idct_column_large_slow(block, temp, 15);
-
- idct_column_large_slow(block, temp, 16);
- idct_column_large_slow(block, temp, 17);
- idct_column_large_slow(block, temp, 18);
- idct_column_large_slow(block, temp, 19);
-
- idct_column_large_slow(block, temp, 20);
- idct_column_large_slow(block, temp, 21);
- idct_column_large_slow(block, temp, 22);
- idct_column_large_slow(block, temp, 23);
-
- idct_column_large_slow(block, temp, 24);
- idct_column_large_slow(block, temp, 25);
- idct_column_large_slow(block, temp, 26);
- idct_column_large_slow(block, temp, 27);
-
- idct_column_large_slow(block, temp, 28);
- idct_column_large_slow(block, temp, 29);
- idct_column_large_slow(block, temp, 30);
- idct_column_large_slow(block, temp, 31);
-
- idct_line_large_slow(temp, block, 0);
- idct_line_large_slow(temp, block, 1);
- idct_line_large_slow(temp, block, 2);
- idct_line_large_slow(temp, block, 3);
-
- idct_line_large_slow(temp, block, 4);
- idct_line_large_slow(temp, block, 5);
- idct_line_large_slow(temp, block, 6);
- idct_line_large_slow(temp, block, 7);
-
- idct_line_large_slow(temp, block, 8);
- idct_line_large_slow(temp, block, 9);
- idct_line_large_slow(temp, block, 10);
- idct_line_large_slow(temp, block, 11);
-
- idct_line_large_slow(temp, block, 12);
- idct_line_large_slow(temp, block, 13);
- idct_line_large_slow(temp, block, 14);
- idct_line_large_slow(temp, block, 15);
-
- idct_line_large_slow(temp, block, 16);
- idct_line_large_slow(temp, block, 17);
- idct_line_large_slow(temp, block, 18);
- idct_line_large_slow(temp, block, 19);
-
- idct_line_large_slow(temp, block, 20);
- idct_line_large_slow(temp, block, 21);
- idct_line_large_slow(temp, block, 22);
- idct_line_large_slow(temp, block, 23);
-
- idct_line_large_slow(temp, block, 24);
- idct_line_large_slow(temp, block, 25);
- idct_line_large_slow(temp, block, 26);
- idct_line_large_slow(temp, block, 27);
-
- idct_line_large_slow(temp, block, 28);
- idct_line_large_slow(temp, block, 29);
- idct_line_large_slow(temp, block, 30);
- idct_line_large_slow(temp, block, 31);
-}
-
-S32 gDitherNoise = 128;
-
-void decompress_patch(F32 *patch, S32 *cpatch, LLPatchHeader *ph)
-{
- S32 i, j;
-
- F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock = block;
- F32 *tpatch;
-
- LLGroupHeader *gopp = gGOPP;
- S32 size = gopp->patch_size;
- F32 range = ph->range;
- S32 prequant = (ph->quant_wbits >> 4) + 2;
- S32 quantize = 1<<prequant;
- F32 hmin = ph->dc_offset;
- S32 stride = gopp->stride;
-
- F32 ooq = 1.f/(F32)quantize;
- F32 *dq = gPatchDequantizeTable;
- S32 *decopy_matrix = gDeCopyMatrix;
-
- F32 mult = ooq*range;
- F32 addval = mult*(F32)(1<<(prequant - 1))+hmin;
-
- for (i = 0; i < size*size; i++)
- {
- *(tblock++) = *(cpatch + *(decopy_matrix++))*(*dq++);
- }
-
- if (size == 16)
- {
- idct_patch(block);
- }
- else
- {
- idct_patch_large(block);
- }
-
- for (j = 0; j < size; j++)
- {
- tpatch = patch + j*stride;
- tblock = block + j*size;
- for (i = 0; i < size; i++)
- {
- *(tpatch++) = *(tblock++)*mult+addval;
- }
- }
-}
-
-
-void decompress_patchv(LLVector3 *v, S32 *cpatch, LLPatchHeader *ph)
-{
- S32 i, j;
-
- F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock = block;
- LLVector3 *tvec;
-
- LLGroupHeader *gopp = gGOPP;
- S32 size = gopp->patch_size;
- F32 range = ph->range;
- S32 prequant = (ph->quant_wbits >> 4) + 2;
- S32 quantize = 1<<prequant;
- F32 hmin = ph->dc_offset;
- S32 stride = gopp->stride;
-
- F32 ooq = 1.f/(F32)quantize;
- F32 *dq = gPatchDequantizeTable;
- S32 *decopy_matrix = gDeCopyMatrix;
-
- F32 mult = ooq*range;
- F32 addval = mult*(F32)(1<<(prequant - 1))+hmin;
-
-// bool b_diag = false;
-// bool b_right = true;
-
- for (i = 0; i < size*size; i++)
- {
- *(tblock++) = *(cpatch + *(decopy_matrix++))*(*dq++);
- }
-
- if (size == 16)
- idct_patch(block);
- else
- idct_patch_large(block);
-
- for (j = 0; j < size; j++)
- {
- tvec = v + j*stride;
- tblock = block + j*size;
- for (i = 0; i < size; i++)
- {
- (*tvec++).mV[VZ] = *(tblock++)*mult+addval;
- }
- }
-}
-
+/**
+ * @file patch_idct.cpp
+ * @brief IDCT patch.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llmath.h"
+//#include "vmath.h"
+#include "v3math.h"
+#include "patch_dct.h"
+
+LLGroupHeader *gGOPP;
+
+void set_group_of_patch_header(LLGroupHeader *gopp)
+{
+ gGOPP = gopp;
+}
+
+F32 gPatchDequantizeTable[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+void build_patch_dequantize_table(S32 size)
+{
+ S32 i, j;
+ for (j = 0; j < size; j++)
+ {
+ for (i = 0; i < size; i++)
+ {
+ gPatchDequantizeTable[j*size + i] = (1.f + 2.f*(i+j));
+ }
+ }
+}
+
+S32 gCurrentDeSize = 0;
+
+F32 gPatchICosines[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+void setup_patch_icosines(S32 size)
+{
+ S32 n, u;
+ F32 oosob = F_PI*0.5f/size;
+
+ for (u = 0; u < size; u++)
+ {
+ for (n = 0; n < size; n++)
+ {
+ gPatchICosines[u*size+n] = cosf((2.f*n+1.f)*u*oosob);
+ }
+ }
+}
+
+S32 gDeCopyMatrix[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+void build_decopy_matrix(S32 size)
+{
+ S32 i, j, count;
+ bool b_diag = false;
+ bool b_right = true;
+
+ i = 0;
+ j = 0;
+ count = 0;
+
+ while ( (i < size)
+ &&(j < size))
+ {
+ gDeCopyMatrix[j*size + i] = count;
+
+ count++;
+
+ if (!b_diag)
+ {
+ if (b_right)
+ {
+ if (i < size - 1)
+ i++;
+ else
+ j++;
+ b_right = false;
+ b_diag = true;
+ }
+ else
+ {
+ if (j < size - 1)
+ j++;
+ else
+ i++;
+ b_right = true;
+ b_diag = true;
+ }
+ }
+ else
+ {
+ if (b_right)
+ {
+ i++;
+ j--;
+ if ( (i == size - 1)
+ ||(j == 0))
+ {
+ b_diag = false;
+ }
+ }
+ else
+ {
+ i--;
+ j++;
+ if ( (i == 0)
+ ||(j == size - 1))
+ {
+ b_diag = false;
+ }
+ }
+ }
+ }
+}
+
+void init_patch_decompressor(S32 size)
+{
+ if (size != gCurrentDeSize)
+ {
+ gCurrentDeSize = size;
+ build_patch_dequantize_table(size);
+ setup_patch_icosines(size);
+ build_decopy_matrix(size);
+ }
+}
+
+inline void idct_line(F32 *linein, F32 *lineout, S32 line)
+{
+ S32 n;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ F32 oosob = 2.f/16.f;
+ S32 line_size = line*NORMAL_PATCH_SIZE;
+ F32 *tlinein, *tpcp;
+
+
+ for (n = 0; n < NORMAL_PATCH_SIZE; n++)
+ {
+ tpcp = pcp + n;
+ tlinein = linein + line_size;
+
+ total = OO_SQRT2*(*(tlinein++));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ *(lineout + line_size + n) = total*oosob;
+ }
+#else
+ F32 oosob = 2.f/size;
+ S32 size = gGOPP->patch_size;
+ S32 line_size = line*size;
+ S32 u;
+ for (n = 0; n < size; n++)
+ {
+ total = OO_SQRT2*linein[line_size];
+ for (u = 1; u < size; u++)
+ {
+ total += linein[line_size + u]*pcp[u*size+n];
+ }
+ lineout[line_size + n] = total*oosob;
+ }
+#endif
+}
+
+inline void idct_line_large_slow(F32 *linein, F32 *lineout, S32 line)
+{
+ S32 n;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+ F32 oosob = 2.f/32.f;
+ S32 line_size = line*LARGE_PATCH_SIZE;
+ F32 *tlinein, *tpcp;
+
+
+ for (n = 0; n < LARGE_PATCH_SIZE; n++)
+ {
+ tpcp = pcp + n;
+ tlinein = linein + line_size;
+
+ total = OO_SQRT2*(*(tlinein++));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ *(lineout + line_size + n) = total*oosob;
+ }
+}
+
+// Nota Bene: assumes that coefficients beyond 128 are 0!
+
+void idct_line_large(F32 *linein, F32 *lineout, S32 line)
+{
+ S32 n;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+ F32 oosob = 2.f/32.f;
+ S32 line_size = line*LARGE_PATCH_SIZE;
+ F32 *tlinein, *tpcp;
+ F32 *baselinein = linein + line_size;
+ F32 *baselineout = lineout + line_size;
+
+
+ for (n = 0; n < LARGE_PATCH_SIZE; n++)
+ {
+ tpcp = pcp++;
+ tlinein = baselinein;
+
+ total = OO_SQRT2*(*(tlinein++));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein++)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein)*(*(tpcp));
+
+ *baselineout++ = total*oosob;
+ }
+}
+
+inline void idct_column(F32 *linein, F32 *lineout, S32 column)
+{
+ S32 n;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ F32 *tlinein, *tpcp;
+
+ for (n = 0; n < NORMAL_PATCH_SIZE; n++)
+ {
+ tpcp = pcp + n;
+ tlinein = linein + column;
+
+ total = OO_SQRT2*(*tlinein);
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+ total += *(tlinein += NORMAL_PATCH_SIZE)*(*(tpcp += NORMAL_PATCH_SIZE));
+
+ *(lineout + (n<<4) + column) = total;
+ }
+
+#else
+ S32 size = gGOPP->patch_size;
+ S32 u;
+ S32 u_size;
+
+ for (n = 0; n < size; n++)
+ {
+ total = OO_SQRT2*linein[column];
+ for (u = 1; u < size; u++)
+ {
+ u_size = u*size;
+ total += linein[u_size + column]*pcp[u_size+n];
+ }
+ lineout[size*n + column] = total;
+ }
+#endif
+}
+
+inline void idct_column_large_slow(F32 *linein, F32 *lineout, S32 column)
+{
+ S32 n;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+ F32 *tlinein, *tpcp;
+
+ for (n = 0; n < LARGE_PATCH_SIZE; n++)
+ {
+ tpcp = pcp + n;
+ tlinein = linein + column;
+
+ total = OO_SQRT2*(*tlinein);
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ *(lineout + (n<<5) + column) = total;
+ }
+}
+
+// Nota Bene: assumes that coefficients beyond 128 are 0!
+
+void idct_column_large(F32 *linein, F32 *lineout, S32 column)
+{
+ S32 n, m;
+ F32 total;
+ F32 *pcp = gPatchICosines;
+
+ F32 *tlinein, *tpcp;
+ F32 *baselinein = linein + column;
+ F32 *baselineout = lineout + column;
+
+ for (n = 0; n < LARGE_PATCH_SIZE; n++)
+ {
+ tpcp = pcp++;
+ tlinein = baselinein;
+
+ total = OO_SQRT2*(*tlinein);
+ for (m = 1; m < NORMAL_PATCH_SIZE; m++)
+ total += *(tlinein += LARGE_PATCH_SIZE)*(*(tpcp += LARGE_PATCH_SIZE));
+
+ *(baselineout + (n<<5)) = total;
+ }
+}
+
+inline void idct_patch(F32 *block)
+{
+ F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+#ifdef _PATCH_SIZE_16_AND_32_ONLY
+ idct_column(block, temp, 0);
+ idct_column(block, temp, 1);
+ idct_column(block, temp, 2);
+ idct_column(block, temp, 3);
+
+ idct_column(block, temp, 4);
+ idct_column(block, temp, 5);
+ idct_column(block, temp, 6);
+ idct_column(block, temp, 7);
+
+ idct_column(block, temp, 8);
+ idct_column(block, temp, 9);
+ idct_column(block, temp, 10);
+ idct_column(block, temp, 11);
+
+ idct_column(block, temp, 12);
+ idct_column(block, temp, 13);
+ idct_column(block, temp, 14);
+ idct_column(block, temp, 15);
+
+ idct_line(temp, block, 0);
+ idct_line(temp, block, 1);
+ idct_line(temp, block, 2);
+ idct_line(temp, block, 3);
+
+ idct_line(temp, block, 4);
+ idct_line(temp, block, 5);
+ idct_line(temp, block, 6);
+ idct_line(temp, block, 7);
+
+ idct_line(temp, block, 8);
+ idct_line(temp, block, 9);
+ idct_line(temp, block, 10);
+ idct_line(temp, block, 11);
+
+ idct_line(temp, block, 12);
+ idct_line(temp, block, 13);
+ idct_line(temp, block, 14);
+ idct_line(temp, block, 15);
+#else
+ S32 i;
+ S32 size = gGOPP->patch_size;
+ for (i = 0; i < size; i++)
+ {
+ idct_column(block, temp, i);
+ }
+ for (i = 0; i < size; i++)
+ {
+ idct_line(temp, block, i);
+ }
+#endif
+}
+
+inline void idct_patch_large(F32 *block)
+{
+ F32 temp[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE];
+
+ idct_column_large_slow(block, temp, 0);
+ idct_column_large_slow(block, temp, 1);
+ idct_column_large_slow(block, temp, 2);
+ idct_column_large_slow(block, temp, 3);
+
+ idct_column_large_slow(block, temp, 4);
+ idct_column_large_slow(block, temp, 5);
+ idct_column_large_slow(block, temp, 6);
+ idct_column_large_slow(block, temp, 7);
+
+ idct_column_large_slow(block, temp, 8);
+ idct_column_large_slow(block, temp, 9);
+ idct_column_large_slow(block, temp, 10);
+ idct_column_large_slow(block, temp, 11);
+
+ idct_column_large_slow(block, temp, 12);
+ idct_column_large_slow(block, temp, 13);
+ idct_column_large_slow(block, temp, 14);
+ idct_column_large_slow(block, temp, 15);
+
+ idct_column_large_slow(block, temp, 16);
+ idct_column_large_slow(block, temp, 17);
+ idct_column_large_slow(block, temp, 18);
+ idct_column_large_slow(block, temp, 19);
+
+ idct_column_large_slow(block, temp, 20);
+ idct_column_large_slow(block, temp, 21);
+ idct_column_large_slow(block, temp, 22);
+ idct_column_large_slow(block, temp, 23);
+
+ idct_column_large_slow(block, temp, 24);
+ idct_column_large_slow(block, temp, 25);
+ idct_column_large_slow(block, temp, 26);
+ idct_column_large_slow(block, temp, 27);
+
+ idct_column_large_slow(block, temp, 28);
+ idct_column_large_slow(block, temp, 29);
+ idct_column_large_slow(block, temp, 30);
+ idct_column_large_slow(block, temp, 31);
+
+ idct_line_large_slow(temp, block, 0);
+ idct_line_large_slow(temp, block, 1);
+ idct_line_large_slow(temp, block, 2);
+ idct_line_large_slow(temp, block, 3);
+
+ idct_line_large_slow(temp, block, 4);
+ idct_line_large_slow(temp, block, 5);
+ idct_line_large_slow(temp, block, 6);
+ idct_line_large_slow(temp, block, 7);
+
+ idct_line_large_slow(temp, block, 8);
+ idct_line_large_slow(temp, block, 9);
+ idct_line_large_slow(temp, block, 10);
+ idct_line_large_slow(temp, block, 11);
+
+ idct_line_large_slow(temp, block, 12);
+ idct_line_large_slow(temp, block, 13);
+ idct_line_large_slow(temp, block, 14);
+ idct_line_large_slow(temp, block, 15);
+
+ idct_line_large_slow(temp, block, 16);
+ idct_line_large_slow(temp, block, 17);
+ idct_line_large_slow(temp, block, 18);
+ idct_line_large_slow(temp, block, 19);
+
+ idct_line_large_slow(temp, block, 20);
+ idct_line_large_slow(temp, block, 21);
+ idct_line_large_slow(temp, block, 22);
+ idct_line_large_slow(temp, block, 23);
+
+ idct_line_large_slow(temp, block, 24);
+ idct_line_large_slow(temp, block, 25);
+ idct_line_large_slow(temp, block, 26);
+ idct_line_large_slow(temp, block, 27);
+
+ idct_line_large_slow(temp, block, 28);
+ idct_line_large_slow(temp, block, 29);
+ idct_line_large_slow(temp, block, 30);
+ idct_line_large_slow(temp, block, 31);
+}
+
+S32 gDitherNoise = 128;
+
+void decompress_patch(F32 *patch, S32 *cpatch, LLPatchHeader *ph)
+{
+ S32 i, j;
+
+ F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock = block;
+ F32 *tpatch;
+
+ LLGroupHeader *gopp = gGOPP;
+ S32 size = gopp->patch_size;
+ F32 range = ph->range;
+ S32 prequant = (ph->quant_wbits >> 4) + 2;
+ S32 quantize = 1<<prequant;
+ F32 hmin = ph->dc_offset;
+ S32 stride = gopp->stride;
+
+ F32 ooq = 1.f/(F32)quantize;
+ F32 *dq = gPatchDequantizeTable;
+ S32 *decopy_matrix = gDeCopyMatrix;
+
+ F32 mult = ooq*range;
+ F32 addval = mult*(F32)(1<<(prequant - 1))+hmin;
+
+ for (i = 0; i < size*size; i++)
+ {
+ *(tblock++) = *(cpatch + *(decopy_matrix++))*(*dq++);
+ }
+
+ if (size == 16)
+ {
+ idct_patch(block);
+ }
+ else
+ {
+ idct_patch_large(block);
+ }
+
+ for (j = 0; j < size; j++)
+ {
+ tpatch = patch + j*stride;
+ tblock = block + j*size;
+ for (i = 0; i < size; i++)
+ {
+ *(tpatch++) = *(tblock++)*mult+addval;
+ }
+ }
+}
+
+
+void decompress_patchv(LLVector3 *v, S32 *cpatch, LLPatchHeader *ph)
+{
+ S32 i, j;
+
+ F32 block[LARGE_PATCH_SIZE*LARGE_PATCH_SIZE], *tblock = block;
+ LLVector3 *tvec;
+
+ LLGroupHeader *gopp = gGOPP;
+ S32 size = gopp->patch_size;
+ F32 range = ph->range;
+ S32 prequant = (ph->quant_wbits >> 4) + 2;
+ S32 quantize = 1<<prequant;
+ F32 hmin = ph->dc_offset;
+ S32 stride = gopp->stride;
+
+ F32 ooq = 1.f/(F32)quantize;
+ F32 *dq = gPatchDequantizeTable;
+ S32 *decopy_matrix = gDeCopyMatrix;
+
+ F32 mult = ooq*range;
+ F32 addval = mult*(F32)(1<<(prequant - 1))+hmin;
+
+// bool b_diag = false;
+// bool b_right = true;
+
+ for (i = 0; i < size*size; i++)
+ {
+ *(tblock++) = *(cpatch + *(decopy_matrix++))*(*dq++);
+ }
+
+ if (size == 16)
+ idct_patch(block);
+ else
+ idct_patch_large(block);
+
+ for (j = 0; j < size; j++)
+ {
+ tvec = v + j*stride;
+ tblock = block + j*size;
+ for (i = 0; i < size; i++)
+ {
+ (*tvec++).mV[VZ] = *(tblock++)*mult+addval;
+ }
+ }
+}
+
diff --git a/indra/llmessage/sound_ids.cpp b/indra/llmessage/sound_ids.cpp
index 2b8a0807c6..17575dc687 100644
--- a/indra/llmessage/sound_ids.cpp
+++ b/indra/llmessage/sound_ids.cpp
@@ -1,24 +1,24 @@
-/**
+/**
* @file sound_ids.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,48 +29,48 @@
#include "lluuid.h"
const LLUUID SND_NULL = LLUUID::null;
-const LLUUID SND_RIDE ("00000000-0000-0000-0000-000000000100");
-const LLUUID SND_SHOT ("00000000-0000-0000-0000-000000000101");
-const LLUUID SND_MORTAR ("00000000-0000-0000-0000-000000000102");
-const LLUUID SND_HIT ("00000000-0000-0000-0000-000000000103");
-const LLUUID SND_EXPLOSION ("00000000-0000-0000-0000-000000000104");
-const LLUUID SND_BOING ("00000000-0000-0000-0000-000000000105");
+const LLUUID SND_RIDE ("00000000-0000-0000-0000-000000000100");
+const LLUUID SND_SHOT ("00000000-0000-0000-0000-000000000101");
+const LLUUID SND_MORTAR ("00000000-0000-0000-0000-000000000102");
+const LLUUID SND_HIT ("00000000-0000-0000-0000-000000000103");
+const LLUUID SND_EXPLOSION ("00000000-0000-0000-0000-000000000104");
+const LLUUID SND_BOING ("00000000-0000-0000-0000-000000000105");
const LLUUID SND_OBJECT_CREATE ("9f1bc096-3592-411e-9b0b-c447a9ff054c");
//
-// Different bird sounds for different states
+// Different bird sounds for different states
//
-const LLUUID SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp
-const LLUUID SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user
-const LLUUID SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object
-const LLUUID SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird
-const LLUUID SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp
-const LLUUID SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead!
+const LLUUID SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp
+const LLUUID SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user
+const LLUUID SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object
+const LLUUID SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird
+const LLUUID SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp
+const LLUUID SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead!
-const LLUUID SND_MUNCH ("00000000-0000-0000-0000-000000000107");
-const LLUUID SND_PUNCH ("00000000-0000-0000-0000-000000000108");
-const LLUUID SND_SPLASH ("00000000-0000-0000-0000-000000000109");
-const LLUUID SND_CLICK ("00000000-0000-0000-0000-000000000110");
-const LLUUID SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb");
+const LLUUID SND_MUNCH ("00000000-0000-0000-0000-000000000107");
+const LLUUID SND_PUNCH ("00000000-0000-0000-0000-000000000108");
+const LLUUID SND_SPLASH ("00000000-0000-0000-0000-000000000109");
+const LLUUID SND_CLICK ("00000000-0000-0000-0000-000000000110");
+const LLUUID SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb");
const LLUUID SND_TYPING ("5e191c7b-8996-9ced-a177-b2ac32bfea06");
-const LLUUID SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111");
-const LLUUID SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112");
-const LLUUID SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113");
-const LLUUID SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0");
+const LLUUID SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111");
+const LLUUID SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112");
+const LLUUID SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113");
+const LLUUID SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0");
-const LLUUID SND_SILENCE ("00000000-0000-0000-0000-000000000114");
-const LLUUID SND_BUBBLES ("00000000-0000-0000-0000-000000000115");
-const LLUUID SND_WELCOME ("00000000-0000-0000-0000-000000000116");
-const LLUUID SND_SQUISH ("00000000-0000-0000-0000-000000000117");
-const LLUUID SND_SUBPOD ("00000000-0000-0000-0000-000000000118");
+const LLUUID SND_SILENCE ("00000000-0000-0000-0000-000000000114");
+const LLUUID SND_BUBBLES ("00000000-0000-0000-0000-000000000115");
+const LLUUID SND_WELCOME ("00000000-0000-0000-0000-000000000116");
+const LLUUID SND_SQUISH ("00000000-0000-0000-0000-000000000117");
+const LLUUID SND_SUBPOD ("00000000-0000-0000-0000-000000000118");
const LLUUID SND_FOOTSTEPS ("00000000-0000-0000-0000-000000000119");
const LLUUID SND_STEP_LEFT ("00000000-0000-0000-0000-000000000124");
const LLUUID SND_STEP_RIGHT ("00000000-0000-0000-0000-000000000125");
-const LLUUID SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120");
+const LLUUID SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120");
const LLUUID SND_OOOH_SCARE_ME ("00000000-0000-0000-0000-000000000121");
const LLUUID SND_PAYBACK_TIME ("00000000-0000-0000-0000-000000000122");
@@ -275,15 +275,15 @@ const LLUUID SND_ROLL_WOOD_WOOD_07 ("0c6aa481-b5bc-4573-ae83-8e16ff27e750");
const LLUUID SND_ROLL_WOOD_WOOD_08 ("214ab2c7-871a-451b-b0db-4c5677199011");
const LLUUID SND_ROLL_WOOD_WOOD_09 ("0086e4db-3ac6-4545-b414-6f359bedd9a5");
-const LLUUID SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d");
+const LLUUID SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d");
-const LLUUID SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2");
-const LLUUID SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed");
-const LLUUID SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357");
-const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b");
+const LLUUID SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2");
+const LLUUID SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed");
+const LLUUID SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357");
+const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b");
-const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78");
-const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9");
+const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78");
+const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9");
diff --git a/indra/llmessage/sound_ids.h b/indra/llmessage/sound_ids.h
index 6a2e343ad3..d212ca322f 100644
--- a/indra/llmessage/sound_ids.h
+++ b/indra/llmessage/sound_ids.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file sound_ids.h
* @brief Temporary holder for sound IDs.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,13 +41,13 @@ extern const LLUUID SND_EXPLOSION;
extern const LLUUID SND_BOING;
extern const LLUUID SND_OBJECT_CREATE;
-// Different bird sounds for different states
-extern const LLUUID SND_CHIRP; // Flying random chirp
-extern const LLUUID SND_CHIRP2; // Spooked by user
-extern const LLUUID SND_CHIRP3; // Spooked by object
-extern const LLUUID SND_CHIRP4; // Chasing other bird
-extern const LLUUID SND_CHIRP5; // Hopping random chirp
-extern const LLUUID SND_CHIRPDEAD; // Hit by grenade - dead!
+// Different bird sounds for different states
+extern const LLUUID SND_CHIRP; // Flying random chirp
+extern const LLUUID SND_CHIRP2; // Spooked by user
+extern const LLUUID SND_CHIRP3; // Spooked by object
+extern const LLUUID SND_CHIRP4; // Chasing other bird
+extern const LLUUID SND_CHIRP5; // Hopping random chirp
+extern const LLUUID SND_CHIRPDEAD; // Hit by grenade - dead!
extern const LLUUID SND_MUNCH;
diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h
index 0359eba803..cc72242e66 100644
--- a/indra/llmessage/tests/commtest.h
+++ b/indra/llmessage/tests/commtest.h
@@ -2,26 +2,26 @@
* @file commtest.h
* @author Nat Goodspeed
* @date 2009-01-09
- * @brief
- *
+ * @brief
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llmessage/tests/llareslistener_test.cpp b/indra/llmessage/tests/llareslistener_test.cpp
index 254185cbd0..f4a9e501ec 100644
--- a/indra/llmessage/tests/llareslistener_test.cpp
+++ b/indra/llmessage/tests/llareslistener_test.cpp
@@ -3,25 +3,25 @@
* @author Mark Palange
* @date 2009-02-26
* @brief Tests of llareslistener.h.
- *
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -57,14 +57,14 @@ LLAres::LLAres():
{}
LLAres::~LLAres() {}
void LLAres::rewriteURI(const std::string &uri,
- LLAres::UriRewriteResponder *resp)
+ LLAres::UriRewriteResponder *resp)
{
- // This is the only LLAres method I chose to implement.
- // The effect is that LLAres returns immediately with
- // a result that is equal to the input uri.
- std::vector<std::string> result;
- result.push_back(uri);
- resp->rewriteResult(result);
+ // This is the only LLAres method I chose to implement.
+ // The effect is that LLAres returns immediately with
+ // a result that is equal to the input uri.
+ std::vector<std::string> result;
+ result.push_back(uri);
+ resp->rewriteResult(result);
}
LLAres::QueryResponder::~QueryResponder() {}
@@ -90,11 +90,11 @@ namespace tut
typedef llareslistener_group::object object;
llareslistener_group llareslistenergrp("llareslistener");
- struct ResponseCallback
- {
- std::vector<std::string> mURIs;
- bool operator()(const LLSD& response)
- {
+ struct ResponseCallback
+ {
+ std::vector<std::string> mURIs;
+ bool operator()(const LLSD& response)
+ {
mURIs.clear();
for (LLSD::array_const_iterator ri(response.beginArray()), rend(response.endArray());
ri != rend; ++ri)
@@ -102,16 +102,16 @@ namespace tut
mURIs.push_back(*ri);
}
return false;
- }
- };
+ }
+ };
template<> template<>
void object::test<1>()
{
set_test_name("test event");
- // Tests the success and failure cases, since they both use
- // the same code paths in the LLAres responder.
- ResponseCallback response;
+ // Tests the success and failure cases, since they both use
+ // the same code paths in the LLAres responder.
+ ResponseCallback response;
std::string pumpname("trigger");
// Since we're asking LLEventPumps to obtain() the pump by the desired
// name, it will persist beyond the current scope, so ensure we
@@ -121,15 +121,15 @@ namespace tut
boost::bind(&ResponseCallback::operator(), &response, _1)));
// Now build an LLSD request that will direct its response events to
// that pump.
- const std::string testURI("login.bar.com");
+ const std::string testURI("login.bar.com");
LLSD request;
request["op"] = "rewriteURI";
request["uri"] = testURI;
request["reply"] = pumpname;
LLEventPumps::instance().obtain("LLAres").post(request);
- ensure_equals(response.mURIs.size(), 1);
- ensure_equals(response.mURIs.front(), testURI);
- }
+ ensure_equals(response.mURIs.size(), 1);
+ ensure_equals(response.mURIs.front(), testURI);
+ }
template<> template<>
void object::test<2>()
diff --git a/indra/llmessage/tests/llavatarnamecache_test.cpp b/indra/llmessage/tests/llavatarnamecache_test.cpp
index ec6b65d483..3735f42c47 100644
--- a/indra/llmessage/tests/llavatarnamecache_test.cpp
+++ b/indra/llmessage/tests/llavatarnamecache_test.cpp
@@ -6,25 +6,25 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
#include "linden_common.h"
#include "../llavatarnamecache.h"
@@ -33,70 +33,70 @@
namespace tut
{
- struct avatarnamecache_data
- {
- };
- typedef test_group<avatarnamecache_data> avatarnamecache_test;
- typedef avatarnamecache_test::object avatarnamecache_object;
- tut::avatarnamecache_test avatarnamecache_testcase("LLAvatarNameCache");
-
- template<> template<>
- void avatarnamecache_object::test<1>()
- {
- bool valid = false;
- S32 max_age = 0;
-
- valid = max_age_from_cache_control("max-age=3600", &max_age);
- ensure("typical input valid", valid);
- ensure_equals("typical input parsed", max_age, 3600);
-
- valid = max_age_from_cache_control(
- " max-age=600 , no-cache,private=\"stuff\" ", &max_age);
- ensure("complex input valid", valid);
- ensure_equals("complex input parsed", max_age, 600);
-
- valid = max_age_from_cache_control(
- "no-cache, max-age = 123 ", &max_age);
- ensure("complex input 2 valid", valid);
- ensure_equals("complex input 2 parsed", max_age, 123);
- }
-
- template<> template<>
- void avatarnamecache_object::test<2>()
- {
- bool valid = false;
- S32 max_age = -1;
-
- valid = max_age_from_cache_control("", &max_age);
- ensure("empty input returns invalid", !valid);
- ensure_equals("empty input doesn't change val", max_age, -1);
-
- valid = max_age_from_cache_control("no-cache", &max_age);
- ensure("no max-age field returns invalid", !valid);
-
- valid = max_age_from_cache_control("max", &max_age);
- ensure("just 'max' returns invalid", !valid);
-
- valid = max_age_from_cache_control("max-age", &max_age);
- ensure("partial max-age is invalid", !valid);
-
- valid = max_age_from_cache_control("max-age=", &max_age);
- ensure("longer partial max-age is invalid", !valid);
-
- valid = max_age_from_cache_control("max-age=FOO", &max_age);
- ensure("invalid integer max-age is invalid", !valid);
-
- valid = max_age_from_cache_control("max-age 234", &max_age);
- ensure("space separated max-age is invalid", !valid);
-
- valid = max_age_from_cache_control("max-age=0", &max_age);
- ensure("zero max-age is valid", valid);
-
- // *TODO: Handle "0000" as zero
- //valid = max_age_from_cache_control("max-age=0000", &max_age);
- //ensure("multi-zero max-age is valid", valid);
-
- valid = max_age_from_cache_control("max-age=-123", &max_age);
- ensure("less than zero max-age is invalid", !valid);
- }
+ struct avatarnamecache_data
+ {
+ };
+ typedef test_group<avatarnamecache_data> avatarnamecache_test;
+ typedef avatarnamecache_test::object avatarnamecache_object;
+ tut::avatarnamecache_test avatarnamecache_testcase("LLAvatarNameCache");
+
+ template<> template<>
+ void avatarnamecache_object::test<1>()
+ {
+ bool valid = false;
+ S32 max_age = 0;
+
+ valid = max_age_from_cache_control("max-age=3600", &max_age);
+ ensure("typical input valid", valid);
+ ensure_equals("typical input parsed", max_age, 3600);
+
+ valid = max_age_from_cache_control(
+ " max-age=600 , no-cache,private=\"stuff\" ", &max_age);
+ ensure("complex input valid", valid);
+ ensure_equals("complex input parsed", max_age, 600);
+
+ valid = max_age_from_cache_control(
+ "no-cache, max-age = 123 ", &max_age);
+ ensure("complex input 2 valid", valid);
+ ensure_equals("complex input 2 parsed", max_age, 123);
+ }
+
+ template<> template<>
+ void avatarnamecache_object::test<2>()
+ {
+ bool valid = false;
+ S32 max_age = -1;
+
+ valid = max_age_from_cache_control("", &max_age);
+ ensure("empty input returns invalid", !valid);
+ ensure_equals("empty input doesn't change val", max_age, -1);
+
+ valid = max_age_from_cache_control("no-cache", &max_age);
+ ensure("no max-age field returns invalid", !valid);
+
+ valid = max_age_from_cache_control("max", &max_age);
+ ensure("just 'max' returns invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age", &max_age);
+ ensure("partial max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=", &max_age);
+ ensure("longer partial max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=FOO", &max_age);
+ ensure("invalid integer max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age 234", &max_age);
+ ensure("space separated max-age is invalid", !valid);
+
+ valid = max_age_from_cache_control("max-age=0", &max_age);
+ ensure("zero max-age is valid", valid);
+
+ // *TODO: Handle "0000" as zero
+ //valid = max_age_from_cache_control("max-age=0000", &max_age);
+ //ensure("multi-zero max-age is valid", valid);
+
+ valid = max_age_from_cache_control("max-age=-123", &max_age);
+ ensure("less than zero max-age is invalid", !valid);
+ }
}
diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp
index d6481d4eea..4caae5f082 100644
--- a/indra/llmessage/tests/llcoproceduremanager_test.cpp
+++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llcoproceduremanager_test.cpp
* @author Brad
* @date 2019-02
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -100,7 +100,7 @@ namespace tut
sync.yield();
ensure_equals("coprocedure failed to update foo", foo, 1);
-
+
LLCoprocedureManager::instance().close("PoolName");
}
diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp
index 1c571a74da..78c195580c 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,18 +38,18 @@ LLCurl::Responder::Responder()
void LLCurl::Responder::httpCompleted()
{
- if (isGoodStatus())
- {
- httpSuccess();
- }
- else
- {
- httpFailure();
- }
+ if (isGoodStatus())
+ {
+ httpSuccess();
+ }
+ else
+ {
+ httpFailure();
+ }
}
void LLCurl::Responder::completedRaw(LLChannelDescriptors const&,
- std::shared_ptr<LLBufferArray> const&)
+ std::shared_ptr<LLBufferArray> const&)
{
}
@@ -67,33 +67,33 @@ void LLCurl::Responder::httpSuccess()
std::string LLCurl::Responder::dumpResponse() const
{
- return "dumpResponse()";
+ return "dumpResponse()";
}
void LLCurl::Responder::successResult(const LLSD& content)
{
- setResult(HTTP_OK, "", content);
- httpSuccess();
+ setResult(HTTP_OK, "", content);
+ httpSuccess();
}
void LLCurl::Responder::failureResult(S32 status, const std::string& reason, const LLSD& content)
{
- setResult(status, reason, content);
- httpFailure();
+ setResult(status, reason, content);
+ httpFailure();
}
void LLCurl::Responder::completeResult(S32 status, const std::string& reason, const LLSD& content)
{
- setResult(status, reason, content);
- httpCompleted();
+ setResult(status, reason, content);
+ httpCompleted();
}
void LLCurl::Responder::setResult(S32 status, const std::string& reason, const LLSD& content /* = LLSD() */)
{
- mStatus = status;
- mReason = reason;
- mContent = content;
+ mStatus = status;
+ mReason = reason;
+ mContent = content;
}
#endif
diff --git a/indra/llmessage/tests/llhost_test.cpp b/indra/llmessage/tests/llhost_test.cpp
index efca1bbfca..a66655ad6c 100644
--- a/indra/llmessage/tests/llhost_test.cpp
+++ b/indra/llmessage/tests/llhost_test.cpp
@@ -7,25 +7,25 @@
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
+
#include "linden_common.h"
#include "../llhost.h"
@@ -34,238 +34,238 @@
namespace tut
{
- struct host_data
- {
- };
- typedef test_group<host_data> host_test;
- typedef host_test::object host_object;
- tut::host_test host_testcase("LLHost");
-
-
- template<> template<>
- void host_object::test<1>()
- {
- LLHost host;
- ensure("IP address is not NULL", (0 == host.getAddress()) && (0 == host.getPort()) && !host.isOk());
- }
- template<> template<>
- void host_object::test<2>()
- {
- U32 ip_addr = 0xc098017d;
- U32 port = 8080;
- LLHost host(ip_addr, port);
- ensure("IP address is invalid", ip_addr == host.getAddress());
- ensure("Port Number is invalid", port == host.getPort());
- ensure("IP address and port number both should be ok", host.isOk());
- }
-
- template<> template<>
- void host_object::test<3>()
- {
- const char* str = "192.168.1.1";
- U32 port = 8080;
- LLHost host(str, port);
- ensure("IP address could not be processed", (host.getAddress() == ip_string_to_u32(str)));
- ensure("Port Number is invalid", (port == host.getPort()));
- }
-
- template<> template<>
- void host_object::test<4>()
- {
- U32 ip = ip_string_to_u32("192.168.1.1");
- U32 port = 22;
- U64 ip_port = (((U64) ip) << 32) | port;
- LLHost host(ip_port);
- ensure("IP address is invalid", ip == host.getAddress());
- ensure("Port Number is invalid", port == host.getPort());
- }
-
- template<> template<>
- void host_object::test<5>()
- {
- std::string ip_port_string = "192.168.1.1:8080";
- U32 ip = ip_string_to_u32("192.168.1.1");
- U32 port = 8080;
-
- LLHost host(ip_port_string);
- ensure("IP address from IP:port is invalid", ip == host.getAddress());
- ensure("Port Number from from IP:port is invalid", port == host.getPort());
- }
-
- template<> template<>
- void host_object::test<6>()
- {
- U32 ip = 0xc098017d, port = 8080;
- LLHost host;
- host.set(ip,port);
- ensure("IP address is invalid", (ip == host.getAddress()));
- ensure("Port Number is invalid", (port == host.getPort()));
- }
-
- template<> template<>
- void host_object::test<7>()
- {
- const char* str = "192.168.1.1";
- U32 port = 8080, ip;
- LLHost host;
- host.set(str,port);
- ip = ip_string_to_u32(str);
- ensure("IP address is invalid", (ip == host.getAddress()));
- ensure("Port Number is invalid", (port == host.getPort()));
-
- str = "64.233.187.99";
- ip = ip_string_to_u32(str);
- host.setAddress(str);
- ensure("IP address is invalid", (ip == host.getAddress()));
-
- ip = 0xc098017b;
- host.setAddress(ip);
- ensure("IP address is invalid", (ip == host.getAddress()));
- // should still use the old port
- ensure("Port Number is invalid", (port == host.getPort()));
-
- port = 8084;
- host.setPort(port);
- ensure("Port Number is invalid", (port == host.getPort()));
- // should still use the old address
- ensure("IP address is invalid", (ip == host.getAddress()));
- }
-
- template<> template<>
- void host_object::test<8>()
- {
- const std::string str("192.168.1.1");
- U32 port = 8080;
- LLHost host;
- host.set(str,port);
-
- std::string ip_string = host.getIPString();
- ensure("Function Failed", (ip_string == str));
-
- std::string ip_string_port = host.getIPandPort();
- ensure("Function Failed", (ip_string_port == "192.168.1.1:8080"));
- }
-
-
-// getHostName() and setHostByName
- template<> template<>
- void host_object::test<9>()
- {
- skip("this test is irreparably flaky");
-// skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\"");
- // nat: is it reasonable to expect LLHost::getHostName() to echo
- // back something resembling the string passed to setHostByName()?
- //
- // If that's not even reasonable, would a round trip in the /other/
- // direction make more sense? (Call getHostName() for something with
- // known IP address; call setHostByName(); verify IP address)
- //
- // Failing that... is there a plausible way to test getHostName() and
- // setHostByName()? Hopefully without putting up a dummy local DNS
- // server?
-
- // monty: If you don't control the DNS server or the DNS configuration
- // for the test point then, no, none of these will necessarily be
- // reliable and may start to fail at any time. Forward translation
- // is subject to CNAME records and round-robin address assignment.
- // Reverse lookup is 1-to-many and is more and more likely to have
- // nothing to do with the forward translation.
- //
- // So the test is increasingly meaningless on a real network.
-
- std::string hostStr = "lindenlab.com";
- LLHost host;
- host.setHostByName(hostStr);
-
- // reverse DNS will likely result in appending of some
- // sub-domain to the main hostname. so look for
- // the main domain name and not do the exact compare
-
- std::string hostname = host.getHostName();
- try
- {
- ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
- }
- catch (const std::exception&)
- {
- std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl;
- throw;
- }
- }
-
-// setHostByName for dotted IP
- template<> template<>
- void host_object::test<10>()
- {
- std::string hostStr = "64.233.167.99";
- LLHost host;
- host.setHostByName(hostStr);
- ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str()));
- }
-
- template<> template<>
- void host_object::test<11>()
- {
- LLHost host1(0xc098017d, 8080);
- LLHost host2 = host1;
- ensure("Both IP addresses are not same", (host1.getAddress() == host2.getAddress()));
- ensure("Both port numbers are not same", (host1.getPort() == host2.getPort()));
- }
-
- template<> template<>
- void host_object::test<12>()
- {
- LLHost host1("192.168.1.1", 8080);
- std::string str1 = "192.168.1.1:8080";
- std::ostringstream stream;
- stream << host1;
- ensure("Operator << failed", ( stream.str()== str1));
-
- // There is no istream >> llhost operator.
- //std::istringstream is(stream.str());
- //LLHost host2;
- //is >> host2;
- //ensure("Operator >> failed. Not compatible with <<", host1 == host2);
- }
-
- // operators ==, !=, <
- template<> template<>
- void host_object::test<13>()
- {
- U32 ip_addr = 0xc098017d;
- U32 port = 8080;
- LLHost host1(ip_addr, port);
- LLHost host2(ip_addr, port);
- ensure("operator== failed", host1 == host2);
-
- // change port
- host2.setPort(7070);
- ensure("operator!= failed", host1 != host2);
-
- // set port back to 8080 and change IP address now
- host2.setPort(8080);
- host2.setAddress(ip_addr+10);
- ensure("operator!= failed", host1 != host2);
-
- ensure("operator< failed", host1 < host2);
-
- // set IP address back to same value and change port
- host2.setAddress(ip_addr);
- host2.setPort(host1.getPort() + 10);
- ensure("operator< failed", host1 < host2);
- }
-
- // invalid ip address string
- template<> template<>
- void host_object::test<14>()
- {
- LLHost host1("10.0.1.2", 6143);
- ensure("10.0.1.2 should be a valid address", host1.isOk());
-
- LLHost host2("booger-brains", 6143);
- ensure("booger-brains should be an invalid ip addess", !host2.isOk());
-
- LLHost host3("255.255.255.255", 6143);
- ensure("255.255.255.255 should be valid broadcast address", host3.isOk());
- }
+ struct host_data
+ {
+ };
+ typedef test_group<host_data> host_test;
+ typedef host_test::object host_object;
+ tut::host_test host_testcase("LLHost");
+
+
+ template<> template<>
+ void host_object::test<1>()
+ {
+ LLHost host;
+ ensure("IP address is not NULL", (0 == host.getAddress()) && (0 == host.getPort()) && !host.isOk());
+ }
+ template<> template<>
+ void host_object::test<2>()
+ {
+ U32 ip_addr = 0xc098017d;
+ U32 port = 8080;
+ LLHost host(ip_addr, port);
+ ensure("IP address is invalid", ip_addr == host.getAddress());
+ ensure("Port Number is invalid", port == host.getPort());
+ ensure("IP address and port number both should be ok", host.isOk());
+ }
+
+ template<> template<>
+ void host_object::test<3>()
+ {
+ const char* str = "192.168.1.1";
+ U32 port = 8080;
+ LLHost host(str, port);
+ ensure("IP address could not be processed", (host.getAddress() == ip_string_to_u32(str)));
+ ensure("Port Number is invalid", (port == host.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<4>()
+ {
+ U32 ip = ip_string_to_u32("192.168.1.1");
+ U32 port = 22;
+ U64 ip_port = (((U64) ip) << 32) | port;
+ LLHost host(ip_port);
+ ensure("IP address is invalid", ip == host.getAddress());
+ ensure("Port Number is invalid", port == host.getPort());
+ }
+
+ template<> template<>
+ void host_object::test<5>()
+ {
+ std::string ip_port_string = "192.168.1.1:8080";
+ U32 ip = ip_string_to_u32("192.168.1.1");
+ U32 port = 8080;
+
+ LLHost host(ip_port_string);
+ ensure("IP address from IP:port is invalid", ip == host.getAddress());
+ ensure("Port Number from from IP:port is invalid", port == host.getPort());
+ }
+
+ template<> template<>
+ void host_object::test<6>()
+ {
+ U32 ip = 0xc098017d, port = 8080;
+ LLHost host;
+ host.set(ip,port);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ ensure("Port Number is invalid", (port == host.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<7>()
+ {
+ const char* str = "192.168.1.1";
+ U32 port = 8080, ip;
+ LLHost host;
+ host.set(str,port);
+ ip = ip_string_to_u32(str);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ ensure("Port Number is invalid", (port == host.getPort()));
+
+ str = "64.233.187.99";
+ ip = ip_string_to_u32(str);
+ host.setAddress(str);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+
+ ip = 0xc098017b;
+ host.setAddress(ip);
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ // should still use the old port
+ ensure("Port Number is invalid", (port == host.getPort()));
+
+ port = 8084;
+ host.setPort(port);
+ ensure("Port Number is invalid", (port == host.getPort()));
+ // should still use the old address
+ ensure("IP address is invalid", (ip == host.getAddress()));
+ }
+
+ template<> template<>
+ void host_object::test<8>()
+ {
+ const std::string str("192.168.1.1");
+ U32 port = 8080;
+ LLHost host;
+ host.set(str,port);
+
+ std::string ip_string = host.getIPString();
+ ensure("Function Failed", (ip_string == str));
+
+ std::string ip_string_port = host.getIPandPort();
+ ensure("Function Failed", (ip_string_port == "192.168.1.1:8080"));
+ }
+
+
+// getHostName() and setHostByName
+ template<> template<>
+ void host_object::test<9>()
+ {
+ skip("this test is irreparably flaky");
+// skip("setHostByName(\"google.com\"); getHostName() -> (e.g.) \"yx-in-f100.1e100.net\"");
+ // nat: is it reasonable to expect LLHost::getHostName() to echo
+ // back something resembling the string passed to setHostByName()?
+ //
+ // If that's not even reasonable, would a round trip in the /other/
+ // direction make more sense? (Call getHostName() for something with
+ // known IP address; call setHostByName(); verify IP address)
+ //
+ // Failing that... is there a plausible way to test getHostName() and
+ // setHostByName()? Hopefully without putting up a dummy local DNS
+ // server?
+
+ // monty: If you don't control the DNS server or the DNS configuration
+ // for the test point then, no, none of these will necessarily be
+ // reliable and may start to fail at any time. Forward translation
+ // is subject to CNAME records and round-robin address assignment.
+ // Reverse lookup is 1-to-many and is more and more likely to have
+ // nothing to do with the forward translation.
+ //
+ // So the test is increasingly meaningless on a real network.
+
+ std::string hostStr = "lindenlab.com";
+ LLHost host;
+ host.setHostByName(hostStr);
+
+ // reverse DNS will likely result in appending of some
+ // sub-domain to the main hostname. so look for
+ // the main domain name and not do the exact compare
+
+ std::string hostname = host.getHostName();
+ try
+ {
+ ensure("getHostName failed", hostname.find(hostStr) != std::string::npos);
+ }
+ catch (const std::exception&)
+ {
+ std::cerr << "set '" << hostStr << "'; reported '" << hostname << "'" << std::endl;
+ throw;
+ }
+ }
+
+// setHostByName for dotted IP
+ template<> template<>
+ void host_object::test<10>()
+ {
+ std::string hostStr = "64.233.167.99";
+ LLHost host;
+ host.setHostByName(hostStr);
+ ensure("SetHostByName for dotted IP Address failed", host.getAddress() == ip_string_to_u32(hostStr.c_str()));
+ }
+
+ template<> template<>
+ void host_object::test<11>()
+ {
+ LLHost host1(0xc098017d, 8080);
+ LLHost host2 = host1;
+ ensure("Both IP addresses are not same", (host1.getAddress() == host2.getAddress()));
+ ensure("Both port numbers are not same", (host1.getPort() == host2.getPort()));
+ }
+
+ template<> template<>
+ void host_object::test<12>()
+ {
+ LLHost host1("192.168.1.1", 8080);
+ std::string str1 = "192.168.1.1:8080";
+ std::ostringstream stream;
+ stream << host1;
+ ensure("Operator << failed", ( stream.str()== str1));
+
+ // There is no istream >> llhost operator.
+ //std::istringstream is(stream.str());
+ //LLHost host2;
+ //is >> host2;
+ //ensure("Operator >> failed. Not compatible with <<", host1 == host2);
+ }
+
+ // operators ==, !=, <
+ template<> template<>
+ void host_object::test<13>()
+ {
+ U32 ip_addr = 0xc098017d;
+ U32 port = 8080;
+ LLHost host1(ip_addr, port);
+ LLHost host2(ip_addr, port);
+ ensure("operator== failed", host1 == host2);
+
+ // change port
+ host2.setPort(7070);
+ ensure("operator!= failed", host1 != host2);
+
+ // set port back to 8080 and change IP address now
+ host2.setPort(8080);
+ host2.setAddress(ip_addr+10);
+ ensure("operator!= failed", host1 != host2);
+
+ ensure("operator< failed", host1 < host2);
+
+ // set IP address back to same value and change port
+ host2.setAddress(ip_addr);
+ host2.setPort(host1.getPort() + 10);
+ ensure("operator< failed", host1 < host2);
+ }
+
+ // invalid ip address string
+ template<> template<>
+ void host_object::test<14>()
+ {
+ LLHost host1("10.0.1.2", 6143);
+ ensure("10.0.1.2 should be a valid address", host1.isOk());
+
+ LLHost host2("booger-brains", 6143);
+ ensure("booger-brains should be an invalid ip addess", !host2.isOk());
+
+ LLHost host3("255.255.255.255", 6143);
+ ensure("255.255.255.255 should be valid broadcast address", host3.isOk());
+ }
}
diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp
index 78faa66a0d..1881144d3e 100644
--- a/indra/llmessage/tests/llhttpclient_test.cpp
+++ b/indra/llmessage/tests/llhttpclient_test.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llhttpclient_test.cpp
* @brief Testing the HTTP client classes.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,265 +47,265 @@
namespace tut
{
- struct HTTPClientTestData
- {
- public:
- HTTPClientTestData():
- PORT(LLStringUtil::getenv("PORT")),
- // Turning NULL PORT into empty string doesn't make things work;
- // that's just to keep this initializer from blowing up. We test
- // PORT separately in the constructor body.
- local_server(STRINGIZE("http://127.0.0.1:" << PORT << "/"))
- {
- ensure("Set environment variable PORT to local test server port", !PORT.empty());
- apr_pool_create(&mPool, NULL);
- LLCurl::initClass(false);
- mClientPump = new LLPumpIO(mPool);
-
- LLHTTPClient::setPump(*mClientPump);
- }
-
- ~HTTPClientTestData()
- {
- delete mClientPump;
- SUBSYSTEM_CLEANUP(LLProxy);
- apr_pool_destroy(mPool);
- }
-
- void runThePump(float timeout = 100.0f)
- {
- LLTimer timer;
- timer.setTimerExpirySec(timeout);
-
- while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired())
- {
- LLFrameTimer::updateFrameTime();
- if (mClientPump)
- {
- mClientPump->pump();
- mClientPump->callback();
- }
- }
- }
-
- const std::string PORT;
- const std::string local_server;
-
- private:
- apr_pool_t* mPool;
- LLPumpIO* mClientPump;
-
- protected:
- void ensureStatusOK()
- {
- if (mSawError)
- {
- std::string msg =
- llformat("httpFailure() called when not expected, status %d",
- mStatus);
- fail(msg);
- }
- }
-
- void ensureStatusError()
- {
- if (!mSawError)
- {
- fail("httpFailure() wasn't called");
- }
- }
-
- LLSD getResult()
- {
- return mResult;
- }
- LLSD getHeader()
- {
- return mHeader;
- }
-
- protected:
- bool mSawError;
- U32 mStatus;
- std::string mReason;
- bool mSawCompleted;
- bool mSawCompletedHeader;
- LLSD mResult;
- LLSD mHeader;
- bool mResultDeleted;
-
- class Result : public LLHTTPClient::Responder
- {
- protected:
- Result(HTTPClientTestData& client)
- : mClient(client)
- {
- }
-
- public:
- static Result* build(HTTPClientTestData& client)
- {
- return new Result(client);
- }
-
- ~Result()
- {
- mClient.mResultDeleted = true;
- }
-
- protected:
- virtual void httpFailure()
- {
- mClient.mSawError = true;
- mClient.mStatus = getStatus();
- mClient.mReason = getReason();
- }
-
- virtual void httpSuccess()
- {
- mClient.mResult = getContent();
- }
-
- virtual void httpCompleted()
- {
- LLHTTPClient::Responder::httpCompleted();
-
- mClient.mSawCompleted = true;
- mClient.mSawCompletedHeader = true;
- mClient.mHeader = getResponseHeaders();
- }
-
- private:
- HTTPClientTestData& mClient;
- };
-
- friend class Result;
-
- protected:
- LLHTTPClient::ResponderPtr newResult()
- {
- mSawError = false;
- mStatus = 0;
- mSawCompleted = false;
- mSawCompletedHeader = false;
- mResult.clear();
- mHeader.clear();
- mResultDeleted = false;
-
- return Result::build(*this);
- }
- };
-
-
- typedef test_group<HTTPClientTestData> HTTPClientTestGroup;
- typedef HTTPClientTestGroup::object HTTPClientTestObject;
- HTTPClientTestGroup httpClientTestGroup("http_client");
-
- template<> template<>
- void HTTPClientTestObject::test<1>()
- {
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- ensure("result object wasn't destroyed", mResultDeleted);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<2>()
- {
- // Please nobody listen on this particular port...
- LLHTTPClient::get("http://127.0.0.1:7950", newResult());
- runThePump();
- ensureStatusError();
- }
-
- template<> template<>
- void HTTPClientTestObject::test<3>()
- {
- LLSD sd;
-
- sd["list"][0]["one"] = 1;
- sd["list"][0]["two"] = 2;
- sd["list"][1]["three"] = 3;
- sd["list"][1]["four"] = 4;
-
- LLHTTPClient::post(local_server + "web/echo", sd, newResult());
- runThePump();
- ensureStatusOK();
- ensure_equals("echoed result matches", getResult(), sd);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<4>()
- {
- LLSD sd;
-
- sd["message"] = "This is my test message.";
-
- LLHTTPClient::put(local_server + "test/storage", sd, newResult());
- runThePump();
- ensureStatusOK();
-
- LLHTTPClient::get(local_server + "test/storage", newResult());
- runThePump();
- ensureStatusOK();
- ensure_equals("echoed result matches", getResult(), sd);
-
- }
-
- template<> template<>
- void HTTPClientTestObject::test<5>()
- {
- LLSD sd;
- sd["status"] = 543;
- sd["reason"] = "error for testing";
-
- LLHTTPClient::post(local_server + "test/error", sd, newResult());
- runThePump();
- ensureStatusError();
- ensure_contains("reason", mReason, sd["reason"]);
- }
-
- template<> template<>
- void HTTPClientTestObject::test<6>()
- {
- const F32 timeout = 1.0f;
- LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout);
- runThePump(timeout * 5.0f);
- ensureStatusError();
- ensure_equals("reason", mReason, "STATUS_EXPIRED");
- }
-
- template<> template<>
- void HTTPClientTestObject::test<7>()
- {
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- LLSD expected = getResult();
-
- LLSD result;
- result = LLHTTPClient::blockingGet(local_server);
- LLSD body = result["body"];
- ensure_equals("echoed result matches", body.size(), expected.size());
- }
- template<> template<>
- void HTTPClientTestObject::test<8>()
- {
- // This is testing for the presence of the Header in the returned results
- // from an HTTP::get call.
- LLHTTPClient::get(local_server, newResult());
- runThePump();
- ensureStatusOK();
- LLSD header = getHeader();
- ensure("got a header", ! header.emptyMap().asBoolean());
- }
- template<> template<>
- void HTTPClientTestObject::test<9>()
- {
- LLHTTPClient::head(local_server, newResult());
- runThePump();
- ensureStatusOK();
- ensure("result object wasn't destroyed", mResultDeleted);
- }
+ struct HTTPClientTestData
+ {
+ public:
+ HTTPClientTestData():
+ PORT(LLStringUtil::getenv("PORT")),
+ // Turning NULL PORT into empty string doesn't make things work;
+ // that's just to keep this initializer from blowing up. We test
+ // PORT separately in the constructor body.
+ local_server(STRINGIZE("http://127.0.0.1:" << PORT << "/"))
+ {
+ ensure("Set environment variable PORT to local test server port", !PORT.empty());
+ apr_pool_create(&mPool, NULL);
+ LLCurl::initClass(false);
+ mClientPump = new LLPumpIO(mPool);
+
+ LLHTTPClient::setPump(*mClientPump);
+ }
+
+ ~HTTPClientTestData()
+ {
+ delete mClientPump;
+ SUBSYSTEM_CLEANUP(LLProxy);
+ apr_pool_destroy(mPool);
+ }
+
+ void runThePump(float timeout = 100.0f)
+ {
+ LLTimer timer;
+ timer.setTimerExpirySec(timeout);
+
+ while(!mSawCompleted && !mSawCompletedHeader && !timer.hasExpired())
+ {
+ LLFrameTimer::updateFrameTime();
+ if (mClientPump)
+ {
+ mClientPump->pump();
+ mClientPump->callback();
+ }
+ }
+ }
+
+ const std::string PORT;
+ const std::string local_server;
+
+ private:
+ apr_pool_t* mPool;
+ LLPumpIO* mClientPump;
+
+ protected:
+ void ensureStatusOK()
+ {
+ if (mSawError)
+ {
+ std::string msg =
+ llformat("httpFailure() called when not expected, status %d",
+ mStatus);
+ fail(msg);
+ }
+ }
+
+ void ensureStatusError()
+ {
+ if (!mSawError)
+ {
+ fail("httpFailure() wasn't called");
+ }
+ }
+
+ LLSD getResult()
+ {
+ return mResult;
+ }
+ LLSD getHeader()
+ {
+ return mHeader;
+ }
+
+ protected:
+ bool mSawError;
+ U32 mStatus;
+ std::string mReason;
+ bool mSawCompleted;
+ bool mSawCompletedHeader;
+ LLSD mResult;
+ LLSD mHeader;
+ bool mResultDeleted;
+
+ class Result : public LLHTTPClient::Responder
+ {
+ protected:
+ Result(HTTPClientTestData& client)
+ : mClient(client)
+ {
+ }
+
+ public:
+ static Result* build(HTTPClientTestData& client)
+ {
+ return new Result(client);
+ }
+
+ ~Result()
+ {
+ mClient.mResultDeleted = true;
+ }
+
+ protected:
+ virtual void httpFailure()
+ {
+ mClient.mSawError = true;
+ mClient.mStatus = getStatus();
+ mClient.mReason = getReason();
+ }
+
+ virtual void httpSuccess()
+ {
+ mClient.mResult = getContent();
+ }
+
+ virtual void httpCompleted()
+ {
+ LLHTTPClient::Responder::httpCompleted();
+
+ mClient.mSawCompleted = true;
+ mClient.mSawCompletedHeader = true;
+ mClient.mHeader = getResponseHeaders();
+ }
+
+ private:
+ HTTPClientTestData& mClient;
+ };
+
+ friend class Result;
+
+ protected:
+ LLHTTPClient::ResponderPtr newResult()
+ {
+ mSawError = false;
+ mStatus = 0;
+ mSawCompleted = false;
+ mSawCompletedHeader = false;
+ mResult.clear();
+ mHeader.clear();
+ mResultDeleted = false;
+
+ return Result::build(*this);
+ }
+ };
+
+
+ typedef test_group<HTTPClientTestData> HTTPClientTestGroup;
+ typedef HTTPClientTestGroup::object HTTPClientTestObject;
+ HTTPClientTestGroup httpClientTestGroup("http_client");
+
+ template<> template<>
+ void HTTPClientTestObject::test<1>()
+ {
+ LLHTTPClient::get(local_server, newResult());
+ runThePump();
+ ensureStatusOK();
+ ensure("result object wasn't destroyed", mResultDeleted);
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<2>()
+ {
+ // Please nobody listen on this particular port...
+ LLHTTPClient::get("http://127.0.0.1:7950", newResult());
+ runThePump();
+ ensureStatusError();
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<3>()
+ {
+ LLSD sd;
+
+ sd["list"][0]["one"] = 1;
+ sd["list"][0]["two"] = 2;
+ sd["list"][1]["three"] = 3;
+ sd["list"][1]["four"] = 4;
+
+ LLHTTPClient::post(local_server + "web/echo", sd, newResult());
+ runThePump();
+ ensureStatusOK();
+ ensure_equals("echoed result matches", getResult(), sd);
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<4>()
+ {
+ LLSD sd;
+
+ sd["message"] = "This is my test message.";
+
+ LLHTTPClient::put(local_server + "test/storage", sd, newResult());
+ runThePump();
+ ensureStatusOK();
+
+ LLHTTPClient::get(local_server + "test/storage", newResult());
+ runThePump();
+ ensureStatusOK();
+ ensure_equals("echoed result matches", getResult(), sd);
+
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<5>()
+ {
+ LLSD sd;
+ sd["status"] = 543;
+ sd["reason"] = "error for testing";
+
+ LLHTTPClient::post(local_server + "test/error", sd, newResult());
+ runThePump();
+ ensureStatusError();
+ ensure_contains("reason", mReason, sd["reason"]);
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<6>()
+ {
+ const F32 timeout = 1.0f;
+ LLHTTPClient::get(local_server + "test/timeout", newResult(), LLSD(), timeout);
+ runThePump(timeout * 5.0f);
+ ensureStatusError();
+ ensure_equals("reason", mReason, "STATUS_EXPIRED");
+ }
+
+ template<> template<>
+ void HTTPClientTestObject::test<7>()
+ {
+ LLHTTPClient::get(local_server, newResult());
+ runThePump();
+ ensureStatusOK();
+ LLSD expected = getResult();
+
+ LLSD result;
+ result = LLHTTPClient::blockingGet(local_server);
+ LLSD body = result["body"];
+ ensure_equals("echoed result matches", body.size(), expected.size());
+ }
+ template<> template<>
+ void HTTPClientTestObject::test<8>()
+ {
+ // This is testing for the presence of the Header in the returned results
+ // from an HTTP::get call.
+ LLHTTPClient::get(local_server, newResult());
+ runThePump();
+ ensureStatusOK();
+ LLSD header = getHeader();
+ ensure("got a header", ! header.emptyMap().asBoolean());
+ }
+ template<> template<>
+ void HTTPClientTestObject::test<9>()
+ {
+ LLHTTPClient::head(local_server, newResult());
+ runThePump();
+ ensureStatusOK();
+ ensure("result object wasn't destroyed", mResultDeleted);
+ }
}
diff --git a/indra/llmessage/tests/llhttpnode_stub.cpp b/indra/llmessage/tests/llhttpnode_stub.cpp
index 479a256bdd..d896084021 100644
--- a/indra/llmessage/tests/llhttpnode_stub.cpp
+++ b/indra/llmessage/tests/llhttpnode_stub.cpp
@@ -1,26 +1,26 @@
-/**
+/**
* @file llhttpnode_stub.cpp
* @brief STUB Implementation of classes for generic HTTP/LSL/REST handling.
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
- *
+ *
* Second Life Viewer Source Code
* Copyright (c) 2006-2009, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -69,28 +69,28 @@ const LLHTTPNode* LLHTTPNode::findNode(const std::string& name) const { return N
LLHTTPNode::Response::~Response(){}
void LLHTTPNode::Response::notFound(const std::string& message)
{
- status(404, message);
+ status(404, message);
}
void LLHTTPNode::Response::notFound()
{
- status(404, "Not Found");
+ status(404, "Not Found");
}
void LLHTTPNode::Response::methodNotAllowed()
{
- status(405, "Method Not Allowed");
+ status(405, "Method Not Allowed");
}
void LLHTTPNode::Response::statusUnknownError(S32 code)
{
- status(code, "Unknown Error");
+ status(code, "Unknown Error");
}
void LLHTTPNode::Response::status(S32 code, const std::string& message)
{
}
-void LLHTTPNode::Response::addHeader(const std::string& name,const std::string& value)
+void LLHTTPNode::Response::addHeader(const std::string& name,const std::string& value)
{
- mHeaders[name] = value;
+ mHeaders[name] = value;
}
void LLHTTPNode::describe(Description& desc) const { }
diff --git a/indra/llmessage/tests/llnamevalue_test.cpp b/indra/llmessage/tests/llnamevalue_test.cpp
index 8902fdd2e8..f77cd102f4 100644
--- a/indra/llmessage/tests/llnamevalue_test.cpp
+++ b/indra/llmessage/tests/llnamevalue_test.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llnamevalue_test.cpp
* @author Adroit
* @date 2007-02
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,366 +41,366 @@
namespace tut
{
- struct namevalue_test
- {
- namevalue_test()
- {
- }
- };
- typedef test_group<namevalue_test> namevalue_t;
- typedef namevalue_t::object namevalue_object_t;
- tut::namevalue_t tut_namevalue("LLNameValue");
-
-
- template<> template<>
- void namevalue_object_t::test<1>()
- {
- // LLNameValue()
- LLNameValue nValue;
- ensure("mName should have been NULL", nValue.mName == NULL);
- ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL);
- ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL);
- ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL);
-
- LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343");
-
- }
-
- // LLNameValue(const char* data);
- // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto,
- // TNameValueCallback nvcb = NULL, void** user_data = NULL);
- template<> template<>
- void namevalue_object_t::test<2>()
- {
- LLNameValue nValue(" SecondLife ASSET RW S 232324343");
- ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
- ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
- ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
- ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
- ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
- ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer());
-
- LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343");
- ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1")));
- ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
- ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
- ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
- ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
- ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer());
-
- LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS");
- ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
- ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
- ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM);
- ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
- ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer());
-
- LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE");
- ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
- ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
- ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM);
- ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
- ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
-
- LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
- LLVector3 llvec4(1.0, 2.0, 3.0);
- ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
- ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
- ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
- ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
- ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
-
- LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
- LLVector3 llvec5(-1.0f, 2.4f, 3);
- ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
- ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
- ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
- ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
- ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
-
- LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
- ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
- ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
- ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
- ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
- ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
-
- LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
- U64 u64_7 = U64L(89764323323232);
- ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
- ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
- ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
- ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
- ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
- }
-
- // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass,
- // TNameValueCallback nvcb = NULL, void** user_data = NULL);
- template<> template<>
- void namevalue_object_t::test<3>()
- {
- LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE");
- ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
- ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
- ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
- ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
- ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
-
- LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE");
- ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
- ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
- ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
- ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
- ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
-
- LLNameValue nValue2("SecondLife", "23.5", "F32", "R");
- ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
- ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
- ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
- ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
-
- LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY");
- ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
- ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
- ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
- ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
-
- LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
- LLVector3 llvec4(1.0, 2.0, 3.0);
- ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
- ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
- ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
- ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
-
- LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
- LLVector3 llvec5(-1.0f, 2.4f, 3);
- ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
- ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
- ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
- ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
-
- LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
- ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
- ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
- ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
- ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
-
- LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
- U64 u64_7 = U64L(89764323323232);
- ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
- ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
- ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
- ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
- }
-
- // LLNameValue(const char* name, const char* type, const char* nvclass,
- // TNameValueCallback nvcb = NULL, void** user_data = NULL);
- template<> template<>
- void namevalue_object_t::test<4>()
- {
- LLNameValue nValue("SecondLife", "STRING", "READ_WRITE");
- ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
- ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING);
- ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
- ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue1("SecondLife", "ASSET", "READ_WRITE");
- ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
- ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET);
- ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE);
- ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue2("SecondLife", "F32", "READ_ONLY");
- ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
- ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
- ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue3("SecondLife", "S32", "READ_ONLY");
- ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
- ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
- ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
- ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
- ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
- ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
- ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
- ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
- ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
-
- LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
- ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
- ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
- ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
- }
-
- template<> template<>
- void namevalue_object_t::test<5>()
- {
- LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
-
- ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
- }
-
- template<> template<>
- void namevalue_object_t::test<6>()
- {
- LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
- ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
- }
-
- template<> template<>
- void namevalue_object_t::test<7>()
- {
- LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
-
- ensure("getF32 failed",*nValue.getF32() == 555555.f);
- }
-
- template<> template<>
- void namevalue_object_t::test<8>()
- {
- LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
-
- ensure("getS32 failed", *nValue.getS32() == -5555);
-
- S32 sVal = 0x7FFFFFFF;
- nValue.setS32(sVal);
- ensure("getS32 failed", *nValue.getS32() == sVal);
-
- sVal = -0x7FFFFFFF;
- nValue.setS32(sVal);
- ensure("getS32 failed", *nValue.getS32() == sVal);
-
- sVal = 0;
- nValue.setS32(sVal);
- ensure("getS32 failed", *nValue.getS32() == sVal);
- }
-
- template<> template<>
- void namevalue_object_t::test<9>()
- {
- LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
- LLVector3 vecExpected(-3, 2, 1);
- LLVector3 vec;
- nValue.getVec3(vec);
- ensure("getVec3 failed", vec == vecExpected);
- }
-
- template<> template<>
- void namevalue_object_t::test<10>()
- {
- LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
-
- ensure("getU32 failed",*nValue.getU32() == 12345678);
-
- U32 val = 0xFFFFFFFF;
- nValue.setU32(val);
- ensure("U32 max", *nValue.getU32() == val);
-
- val = 0;
- nValue.setU32(val);
- ensure("U32 min", *nValue.getU32() == val);
- }
-
- template<> template<>
- void namevalue_object_t::test<11>()
- {
- //skip_fail("incomplete support for U64.");
- LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
-
- ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
-
- // there is no LLNameValue::setU64()
- }
-
-
- template<> template<>
- void namevalue_object_t::test<12>()
- {
- //skip_fail("incomplete support for U64.");
- LLNameValue nValue("SecondLife U64 RW DSV 44444444444");
- std::string ret_str = nValue.printNameValue();
-
- ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
-
- LLNameValue nValue1(ret_str.c_str());
- ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());
- }
-
- template<> template<>
- void namevalue_object_t::test<13>()
- {
- LLNameValue nValue("SecondLife STRING RW DSV 44444444444");
- std::string ret_str = nValue.printData();
- ensure_equals("1:printData failed",ret_str,"44444444444");
-
- LLNameValue nValue1("SecondLife S32 RW DSV 44444");
- ret_str = nValue1.printData();
- ensure_equals("2:printData failed",ret_str,"44444");
- }
-
- template<> template<>
- void namevalue_object_t::test<14>()
- {
- LLNameValue nValue("SecodLife STRING RW SIM 22222");
- std::ostringstream stream1,stream2,stream3, stream4, stream5;
- stream1 << nValue;
- ensure_equals("STRING << failed",stream1.str(),"22222");
-
- LLNameValue nValue1("SecodLife F32 RW SIM 22222");
- stream2 << nValue1;
- ensure_equals("F32 << failed",stream2.str(),"22222");
-
- LLNameValue nValue2("SecodLife S32 RW SIM 22222");
- stream3<< nValue2;
- ensure_equals("S32 << failed",stream3.str(),"22222");
-
- LLNameValue nValue3("SecodLife U32 RW SIM 122222");
- stream4<< nValue3;
- ensure_equals("U32 << failed",stream4.str(),"122222");
-
- // I don't think we use U64 name value pairs. JC
- //skip_fail("incomplete support for U64.");
- //LLNameValue nValue4("SecodLife U64 RW SIM 22222");
- //stream5<< nValue4;
- //ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
- }
-
- template<> template<>
- void namevalue_object_t::test<15>()
- {
- LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
-
- ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
- // this should not have updated as it is read only.
- nValue.setAsset("New Value should not be updated");
- ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
-
- LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
- // this should not have updated as it is read only.
- nValue1.setU32(4567);
- ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
-
- LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
- // this should not have updated as it is read only.
- nValue2.setS32(4567);
- ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
-
- LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
- // this should not have updated as it is read only.
- nValue3.setF32(4567);
- ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
-
- LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
- // this should not have updated as it is read only.
- LLVector3 vec(4,5,6);
- nValue3.setVec3(vec);
- LLVector3 vec1(1,2,3);
- ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1);
-
- // cant test for U64 as no set64 exists nor any operators support U64 type
- }
+ struct namevalue_test
+ {
+ namevalue_test()
+ {
+ }
+ };
+ typedef test_group<namevalue_test> namevalue_t;
+ typedef namevalue_t::object namevalue_object_t;
+ tut::namevalue_t tut_namevalue("LLNameValue");
+
+
+ template<> template<>
+ void namevalue_object_t::test<1>()
+ {
+ // LLNameValue()
+ LLNameValue nValue;
+ ensure("mName should have been NULL", nValue.mName == NULL);
+ ensure("getTypeEnum failed",nValue.getTypeEnum() == NVT_NULL);
+ ensure("getClassEnum failed",nValue.getClassEnum() == NVC_NULL);
+ ensure("getSendtoEnum failed",nValue.getSendtoEnum() == NVS_NULL);
+
+ LLNameValue nValue1(" SecondLife ASSET RW SIM 232324343");
+
+ }
+
+ // LLNameValue(const char* data);
+ // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass, const char* nvsendto,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<2>()
+ {
+ LLNameValue nValue(" SecondLife ASSET RW S 232324343");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+ ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+ ensure("sendToData or sendToViewer failed", !nValue.sendToData() && !nValue.sendToViewer());
+
+ LLNameValue nValue1("\n\r SecondLife_1 STRING READ_WRITE SIM 232324343");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife_1")));
+ ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+ ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+ ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+ ensure("1. sendToData or sendToViewer failed", !nValue1.sendToData() && !nValue1.sendToViewer());
+
+ LLNameValue nValue2("SecondLife", "23.5", "F32", "R", "DS");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_DATA_SIM);
+ ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+ ensure("2. sendToData or sendToViewer failed", nValue2.sendToData() && !nValue2.sendToViewer());
+
+ LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY", "SIM_SPACE");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_DATA_SIM);
+ ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+ ensure("sendToData or sendToViewer failed", nValue3.sendToData() && !nValue3.sendToViewer());
+
+ LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW", "SV");
+ LLVector3 llvec4(1.0, 2.0, 3.0);
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM_VIEWER);
+ ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+ ensure("4. sendToData or sendToViewer failed", !nValue4.sendToData() && nValue4.sendToViewer());
+
+ LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW", "SIM_VIEWER");
+ LLVector3 llvec5(-1.0f, 2.4f, 3);
+ ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+ ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+ ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM_VIEWER);
+ ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+ ensure("5. sendToData or sendToViewer failed", !nValue5.sendToData() && nValue5.sendToViewer());
+
+ LLNameValue nValue6("SecondLife", "89764323", "U32", "RW", "DSV");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+ ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+ ensure("6. sendToData or sendToViewer failed", nValue6.sendToData() && nValue6.sendToViewer());
+
+ LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW", "SIM_SPACE_VIEWER");
+ U64 u64_7 = U64L(89764323323232);
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_DATA_SIM_VIEWER);
+ ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+ ensure("7. sendToData or sendToViewer failed", nValue7.sendToData() && nValue7.sendToViewer());
+ }
+
+ // LLNameValue(const char* name, const char* data, const char* type, const char* nvclass,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<3>()
+ {
+ LLNameValue nValue("SecondLife", "232324343", "ASSET", "READ_WRITE");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_ASSET);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+ ensure("getString failed", (0==strcmp(nValue.getAsset(),"232324343")));
+
+ LLNameValue nValue1("SecondLife", "232324343", "STRING", "READ_WRITE");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+ ensure("1. getTypeEnum failed", nValue1.getTypeEnum() == NVT_STRING);
+ ensure("1. getClassEnum failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum failed", nValue1.getSendtoEnum() == NVS_SIM);
+ ensure("1. getString failed", (0==strcmp(nValue1.getString(),"232324343")));
+
+ LLNameValue nValue2("SecondLife", "23.5", "F32", "R");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+ ensure("2. getF32 failed", *nValue2.getF32() == 23.5f);
+
+ LLNameValue nValue3("SecondLife", "-43456787", "S32", "READ_ONLY");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+ ensure("3. getS32 failed", *nValue3.getS32() == -43456787);
+
+ LLNameValue nValue4("SecondLife", "<1.0, 2.0, 3.0>", "VEC3", "RW");
+ LLVector3 llvec4(1.0, 2.0, 3.0);
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+ ensure("4. getVec3 failed", *nValue4.getVec3() == llvec4);
+
+ LLNameValue nValue5("SecondLife", "-1.0, 2.4, 3", "VEC3", "RW");
+ LLVector3 llvec5(-1.0f, 2.4f, 3);
+ ensure("5. getTypeEnum failed", nValue5.getTypeEnum() == NVT_VEC3);
+ ensure("5. getClassEnum failed", nValue5.getClassEnum() == NVC_READ_WRITE);
+ ensure("5. getSendtoEnum failed", nValue5.getSendtoEnum() == NVS_SIM);
+ ensure("5. getVec3 failed", *nValue5.getVec3() == llvec5);
+
+ LLNameValue nValue6("SecondLife", "89764323", "U32", "RW");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+ ensure("6. getU32 failed", *nValue6.getU32() == 89764323);
+
+ LLNameValue nValue7("SecondLife", "89764323323232", "U64", "RW");
+ U64 u64_7 = U64L(89764323323232);
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+ ensure("7. getU32 failed", *nValue7.getU64() == u64_7);
+ }
+
+ // LLNameValue(const char* name, const char* type, const char* nvclass,
+ // TNameValueCallback nvcb = NULL, void** user_data = NULL);
+ template<> template<>
+ void namevalue_object_t::test<4>()
+ {
+ LLNameValue nValue("SecondLife", "STRING", "READ_WRITE");
+ ensure("mName not set correctly", (0 == strcmp(nValue.mName,"SecondLife")));
+ ensure("getTypeEnum failed", nValue.getTypeEnum() == NVT_STRING);
+ ensure("getClassEnum failed", nValue.getClassEnum() == NVC_READ_WRITE);
+ ensure("getSendtoEnum failed", nValue.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue1("SecondLife", "ASSET", "READ_WRITE");
+ ensure("1. mName not set correctly", (0 == strcmp(nValue1.mName,"SecondLife")));
+ ensure("1. getTypeEnum for RW failed", nValue1.getTypeEnum() == NVT_ASSET);
+ ensure("1. getClassEnum for RW failed", nValue1.getClassEnum() == NVC_READ_WRITE);
+ ensure("1. getSendtoEnum for RW failed", nValue1.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue2("SecondLife", "F32", "READ_ONLY");
+ ensure("2. getTypeEnum failed", nValue2.getTypeEnum() == NVT_F32);
+ ensure("2. getClassEnum failed", nValue2.getClassEnum() == NVC_READ_ONLY);
+ ensure("2. getSendtoEnum failed", nValue2.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue3("SecondLife", "S32", "READ_ONLY");
+ ensure("3. getTypeEnum failed", nValue3.getTypeEnum() == NVT_S32);
+ ensure("3. getClassEnum failed", nValue3.getClassEnum() == NVC_READ_ONLY);
+ ensure("3. getSendtoEnum failed", nValue3.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue4("SecondLife", "VEC3", "READ_WRITE");
+ ensure("4. getTypeEnum failed", nValue4.getTypeEnum() == NVT_VEC3);
+ ensure("4. getClassEnum failed", nValue4.getClassEnum() == NVC_READ_WRITE);
+ ensure("4. getSendtoEnum failed", nValue4.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue6("SecondLife", "U32", "READ_WRITE");
+ ensure("6. getTypeEnum failed", nValue6.getTypeEnum() == NVT_U32);
+ ensure("6. getClassEnum failed", nValue6.getClassEnum() == NVC_READ_WRITE);
+ ensure("6. getSendtoEnum failed", nValue6.getSendtoEnum() == NVS_SIM);
+
+ LLNameValue nValue7("SecondLife", "U64", "READ_WRITE");
+ ensure("7. getTypeEnum failed", nValue7.getTypeEnum() == NVT_U64);
+ ensure("7. getClassEnum failed", nValue7.getClassEnum() == NVC_READ_WRITE);
+ ensure("7. getSendtoEnum failed", nValue7.getSendtoEnum() == NVS_SIM);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<5>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "STRING", "RW", "SIM");
+
+ ensure("getString failed", (0 == strcmp(nValue.getString(),"This is a test")));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<6>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "ASSET", "RW", "S");
+ ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<7>()
+ {
+ LLNameValue nValue("SecondLife", "555555", "F32", "RW", "SIM");
+
+ ensure("getF32 failed",*nValue.getF32() == 555555.f);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<8>()
+ {
+ LLNameValue nValue("SecondLife", "-5555", "S32", "RW", "SIM");
+
+ ensure("getS32 failed", *nValue.getS32() == -5555);
+
+ S32 sVal = 0x7FFFFFFF;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+
+ sVal = -0x7FFFFFFF;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+
+ sVal = 0;
+ nValue.setS32(sVal);
+ ensure("getS32 failed", *nValue.getS32() == sVal);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<9>()
+ {
+ LLNameValue nValue("SecondLife", "<-3, 2, 1>", "VEC3", "RW", "SIM");
+ LLVector3 vecExpected(-3, 2, 1);
+ LLVector3 vec;
+ nValue.getVec3(vec);
+ ensure("getVec3 failed", vec == vecExpected);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<10>()
+ {
+ LLNameValue nValue("SecondLife", "12345678", "U32", "RW", "SIM");
+
+ ensure("getU32 failed",*nValue.getU32() == 12345678);
+
+ U32 val = 0xFFFFFFFF;
+ nValue.setU32(val);
+ ensure("U32 max", *nValue.getU32() == val);
+
+ val = 0;
+ nValue.setU32(val);
+ ensure("U32 min", *nValue.getU32() == val);
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<11>()
+ {
+ //skip_fail("incomplete support for U64.");
+ LLNameValue nValue("SecondLife", "44444444444", "U64", "RW", "SIM");
+
+ ensure("getU64 failed",*nValue.getU64() == U64L(44444444444));
+
+ // there is no LLNameValue::setU64()
+ }
+
+
+ template<> template<>
+ void namevalue_object_t::test<12>()
+ {
+ //skip_fail("incomplete support for U64.");
+ LLNameValue nValue("SecondLife U64 RW DSV 44444444444");
+ std::string ret_str = nValue.printNameValue();
+
+ ensure_equals("1:printNameValue failed",ret_str,"SecondLife U64 RW DSV 44444444444");
+
+ LLNameValue nValue1(ret_str.c_str());
+ ensure_equals("Serialization of printNameValue failed", *nValue.getU64(), *nValue1.getU64());
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<13>()
+ {
+ LLNameValue nValue("SecondLife STRING RW DSV 44444444444");
+ std::string ret_str = nValue.printData();
+ ensure_equals("1:printData failed",ret_str,"44444444444");
+
+ LLNameValue nValue1("SecondLife S32 RW DSV 44444");
+ ret_str = nValue1.printData();
+ ensure_equals("2:printData failed",ret_str,"44444");
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<14>()
+ {
+ LLNameValue nValue("SecodLife STRING RW SIM 22222");
+ std::ostringstream stream1,stream2,stream3, stream4, stream5;
+ stream1 << nValue;
+ ensure_equals("STRING << failed",stream1.str(),"22222");
+
+ LLNameValue nValue1("SecodLife F32 RW SIM 22222");
+ stream2 << nValue1;
+ ensure_equals("F32 << failed",stream2.str(),"22222");
+
+ LLNameValue nValue2("SecodLife S32 RW SIM 22222");
+ stream3<< nValue2;
+ ensure_equals("S32 << failed",stream3.str(),"22222");
+
+ LLNameValue nValue3("SecodLife U32 RW SIM 122222");
+ stream4<< nValue3;
+ ensure_equals("U32 << failed",stream4.str(),"122222");
+
+ // I don't think we use U64 name value pairs. JC
+ //skip_fail("incomplete support for U64.");
+ //LLNameValue nValue4("SecodLife U64 RW SIM 22222");
+ //stream5<< nValue4;
+ //ensure("U64 << failed",0 == strcmp((stream5.str()).c_str(),"22222"));
+ }
+
+ template<> template<>
+ void namevalue_object_t::test<15>()
+ {
+ LLNameValue nValue("SecondLife", "This is a test", "ASSET", "R", "S");
+
+ ensure("getAsset failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+ // this should not have updated as it is read only.
+ nValue.setAsset("New Value should not be updated");
+ ensure("setAsset on ReadOnly failed", (0 == strcmp(nValue.getAsset(),"This is a test")));
+
+ LLNameValue nValue1("SecondLife", "1234", "U32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue1.setU32(4567);
+ ensure("setU32 on ReadOnly failed", *nValue1.getU32() == 1234);
+
+ LLNameValue nValue2("SecondLife", "1234", "S32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue2.setS32(4567);
+ ensure("setS32 on ReadOnly failed", *nValue2.getS32() == 1234);
+
+ LLNameValue nValue3("SecondLife", "1234", "F32", "R", "S");
+ // this should not have updated as it is read only.
+ nValue3.setF32(4567);
+ ensure("setF32 on ReadOnly failed", *nValue3.getF32() == 1234);
+
+ LLNameValue nValue4("SecondLife", "<1,2,3>", "VEC3", "R", "S");
+ // this should not have updated as it is read only.
+ LLVector3 vec(4,5,6);
+ nValue3.setVec3(vec);
+ LLVector3 vec1(1,2,3);
+ ensure("setVec3 on ReadOnly failed", *nValue4.getVec3() == vec1);
+
+ // cant test for U64 as no set64 exists nor any operators support U64 type
+ }
}
diff --git a/indra/llmessage/tests/llpartdata_test.cpp b/indra/llmessage/tests/llpartdata_test.cpp
index de81e0bbb2..c517232bcc 100644
--- a/indra/llmessage/tests/llpartdata_test.cpp
+++ b/indra/llmessage/tests/llpartdata_test.cpp
@@ -7,21 +7,21 @@
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,116 +39,116 @@
namespace tut
{
- //bunch of sniffed data that *should* be a valid particle system
- static U8 msg[] = {
- 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80,
- 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66,
- 0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e,
- 0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab,
- 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2,
- 0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0,
- 0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc,
- 0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d,
- 0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
- 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef,
- 0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,
- 0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9,
- 0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55,
- 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab,
- 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- struct partdata_test
- {
- };
+ //bunch of sniffed data that *should* be a valid particle system
+ static U8 msg[] = {
+ 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80,
+ 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66,
+ 0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e,
+ 0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2,
+ 0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0,
+ 0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc,
+ 0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d,
+ 0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef,
+ 0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,
+ 0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9,
+ 0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55,
+ 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab,
+ 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ struct partdata_test
+ {
+ };
+
+ typedef test_group<partdata_test> partdata_test_t;
+ typedef partdata_test_t::object partdata_test_object_t;
+ tut::partdata_test_t tut_partdata_test("LLPartData");
+
+ template<> template<>
+ void partdata_test_object_t::test<1>()
+ {
+ LLPartSysData llpsysdata;
+ LLDataPackerBinaryBuffer dp1(msg, sizeof(msg));
- typedef test_group<partdata_test> partdata_test_t;
- typedef partdata_test_t::object partdata_test_object_t;
- tut::partdata_test_t tut_partdata_test("LLPartData");
+ ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1));
- template<> template<>
- void partdata_test_object_t::test<1>()
- {
- LLPartSysData llpsysdata;
- LLDataPackerBinaryBuffer dp1(msg, sizeof(msg));
- ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1));
+ //mCRC 1 unsigned int
+ ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1);
+ //mFlags 0 unsigned int
+ ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0);
+ //mPattern 1 '' unsigned char
+ ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1);
+ //mInnerAngle 0.00000000 float
+ ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8);
+ //mOuterAngle 0.00000000 float
+ ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8);
+ //mAngularVelocity 0,0,0
+ ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8);
+ ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8);
+ ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8);
+ //mBurstRate 0.097656250 float
+ ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8);
+ //mBurstPartCount 1 '' unsigned char
+ ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1);
+ //mBurstRadius 0.00000000 float
+ ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8);
+ //mBurstSpeedMin 1.0000000 float
+ ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8);
+ //mBurstSpeedMax 1.0000000 float
+ ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8);
+ //mMaxAge 0.00000000 float
+ ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8);
+ //mStartAge 0.00000000 float
+ ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8);
+ //mPartAccel <0,0,0>
+ ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7);
+ ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7);
+ ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7);
-
- //mCRC 1 unsigned int
- ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1);
- //mFlags 0 unsigned int
- ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0);
- //mPattern 1 '' unsigned char
- ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1);
- //mInnerAngle 0.00000000 float
- ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8);
- //mOuterAngle 0.00000000 float
- ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8);
- //mAngularVelocity 0,0,0
- ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8);
- ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8);
- ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8);
- //mBurstRate 0.097656250 float
- ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8);
- //mBurstPartCount 1 '' unsigned char
- ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1);
- //mBurstRadius 0.00000000 float
- ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8);
- //mBurstSpeedMin 1.0000000 float
- ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8);
- //mBurstSpeedMax 1.0000000 float
- ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8);
- //mMaxAge 0.00000000 float
- ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8);
- //mStartAge 0.00000000 float
- ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8);
- //mPartAccel <0,0,0>
- ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7);
- ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7);
- ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7);
+ //mPartData
+ LLPartData& data = llpsysdata.mPartData;
- //mPartData
- LLPartData& data = llpsysdata.mPartData;
+ //mFlags 132354 unsigned int
+ ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354);
+ //mMaxAge 10.000000 float
+ ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8);
+ //mStartColor <1,1,1,1>
+ ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8);
+ ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8);
+ ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8);
+ ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8);
+ //mEndColor <1,1,0,0>
+ ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8);
+ ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8);
+ ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8);
+ ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8);
+ //mStartScale <1,1>
+ ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8);
+ ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8);
+ //mEndScale <0,0>
+ ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8);
+ ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8);
+ //mPosOffset <0,0,0>
+ ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8);
+ ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8);
+ ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8);
+ //mParameter 0.00000000 float
+ ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8);
- //mFlags 132354 unsigned int
- ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354);
- //mMaxAge 10.000000 float
- ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8);
- //mStartColor <1,1,1,1>
- ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8);
- ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8);
- ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8);
- ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8);
- //mEndColor <1,1,0,0>
- ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8);
- ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8);
- ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8);
- ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8);
- //mStartScale <1,1>
- ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8);
- ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8);
- //mEndScale <0,0>
- ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8);
- ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8);
- //mPosOffset <0,0,0>
- ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8);
- ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8);
- ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8);
- //mParameter 0.00000000 float
- ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8);
-
- //mStartGlow 0.00000000 float
- ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8);
- //mEndGlow 0.00000000 float
- ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8);
- //mBlendFuncSource 2 '' unsigned char
- ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2);
- //mBlendFuncDest 1 '' unsigned char
- ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);
- }
+ //mStartGlow 0.00000000 float
+ ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8);
+ //mEndGlow 0.00000000 float
+ ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8);
+ //mBlendFuncSource 2 '' unsigned char
+ ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2);
+ //mBlendFuncDest 1 '' unsigned char
+ ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);
+ }
}
diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
index 3f87a4aff6..d0a34d720a 100644
--- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
+++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp
@@ -1,160 +1,160 @@
-/**
- * @file lltrustedmessageservice_test.cpp
- * @brief LLTrustedMessageService unit tests
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "lltemplatemessagedispatcher.h"
-#include "lltut.h"
-
-#include "llhttpnode.h"
-#include "llhost.h"
-#include "message.h"
-#include "llsd.h"
-#include "llpounceable.h"
-
-#include "llhost.cpp" // Needed for copy operator
-#include "net.cpp" // Needed by LLHost.
-
-LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
-
-// sensor test doubles
-bool gClearRecvWasCalled = false;
-void LLMessageSystem::clearReceiveState(void)
-{
- gClearRecvWasCalled = true;
-}
-
-char gUdpDispatchedData[MAX_BUFFER_SIZE];
-bool gUdpDispatchWasCalled = false;
-bool LLTemplateMessageReader::readMessage(const U8* data,class LLHost const &)
-{
- gUdpDispatchWasCalled = true;
- strcpy(gUdpDispatchedData, reinterpret_cast<const char*>(data));
- return true;
-}
-
-bool gValidateMessage = false;
-bool LLTemplateMessageReader::validateMessage(const U8*, S32 buffer_size, LLHost const &sender, bool trusted)
-{
- return gValidateMessage;
-}
-
-LLHost host;
-const LLHost& LLMessageSystem::getSender() const
-{
- return host;
-}
-
-const char* gBinaryTemplateData = "BINARYTEMPLATEDATA";
-void fillVector(std::vector<U8>& vector_data, const char* data)
-{
- vector_data.resize(strlen(data) + 1);
- strcpy(reinterpret_cast<char*>(&vector_data[0]), data);
-}
-
-namespace tut
-{
- static LLTemplateMessageReader::message_template_number_map_t numberMap;
-
- struct LLTemplateMessageDispatcherData
- {
- LLTemplateMessageDispatcherData()
- {
- mMessageName = "MessageName";
- gUdpDispatchWasCalled = false;
- gClearRecvWasCalled = false;
- gValidateMessage = false;
- mMessage["body"]["binary-template-data"] = std::vector<U8>();
- }
-
- LLSD mMessage;
- LLHTTPNode::ResponsePtr mResponsePtr;
- std::string mMessageName;
- };
-
- typedef test_group<LLTemplateMessageDispatcherData> factory;
- typedef factory::object object;
-}
-
-namespace
-{
- tut::factory tf("LLTemplateMessageDispatcher");
-}
-
-namespace tut
-{
- // does an empty message stop processing?
- template<> template<>
- void object::test<1>()
- {
- LLTemplateMessageReader* pReader = NULL;
- LLTemplateMessageDispatcher t(*pReader);
- t.dispatch(mMessageName, mMessage, mResponsePtr);
- ensure(! gUdpDispatchWasCalled);
- ensure(! gClearRecvWasCalled);
- }
-
- // does the disaptch invoke the udp send method?
- template<> template<>
- void object::test<2>()
- {
- LLTemplateMessageReader* pReader = NULL;
- LLTemplateMessageDispatcher t(*pReader);
- gValidateMessage = true;
- std::vector<U8> vector_data;
- fillVector(vector_data, gBinaryTemplateData);
- mMessage["body"]["binary-template-data"] = vector_data;
- t.dispatch(mMessageName, mMessage, mResponsePtr);
- ensure("udp dispatch was called", gUdpDispatchWasCalled);
- }
-
- // what if the message wasn't valid? We would hope the message gets cleared!
- template<> template<>
- void object::test<3>()
- {
- LLTemplateMessageReader* pReader = NULL;
- LLTemplateMessageDispatcher t(*pReader);
- std::vector<U8> vector_data;
- fillVector(vector_data, gBinaryTemplateData);
- mMessage["body"]["binary-template-data"] = vector_data;
- gValidateMessage = false;
- t.dispatch(mMessageName, mMessage, mResponsePtr);
- ensure("clear received message was called", gClearRecvWasCalled);
- }
-
- // is the binary data passed through correctly?
- template<> template<>
- void object::test<4>()
- {
- LLTemplateMessageReader* pReader = NULL;
- LLTemplateMessageDispatcher t(*pReader);
- gValidateMessage = true;
- std::vector<U8> vector_data;
- fillVector(vector_data, gBinaryTemplateData);
- mMessage["body"]["binary-template-data"] = vector_data;
- t.dispatch(mMessageName, mMessage, mResponsePtr);
- ensure("data couriered correctly", strcmp(gBinaryTemplateData, gUdpDispatchedData) == 0);
- }
-}
-
+/**
+ * @file lltrustedmessageservice_test.cpp
+ * @brief LLTrustedMessageService unit tests
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "lltemplatemessagedispatcher.h"
+#include "lltut.h"
+
+#include "llhttpnode.h"
+#include "llhost.h"
+#include "message.h"
+#include "llsd.h"
+#include "llpounceable.h"
+
+#include "llhost.cpp" // Needed for copy operator
+#include "net.cpp" // Needed by LLHost.
+
+LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
+
+// sensor test doubles
+bool gClearRecvWasCalled = false;
+void LLMessageSystem::clearReceiveState(void)
+{
+ gClearRecvWasCalled = true;
+}
+
+char gUdpDispatchedData[MAX_BUFFER_SIZE];
+bool gUdpDispatchWasCalled = false;
+bool LLTemplateMessageReader::readMessage(const U8* data,class LLHost const &)
+{
+ gUdpDispatchWasCalled = true;
+ strcpy(gUdpDispatchedData, reinterpret_cast<const char*>(data));
+ return true;
+}
+
+bool gValidateMessage = false;
+bool LLTemplateMessageReader::validateMessage(const U8*, S32 buffer_size, LLHost const &sender, bool trusted)
+{
+ return gValidateMessage;
+}
+
+LLHost host;
+const LLHost& LLMessageSystem::getSender() const
+{
+ return host;
+}
+
+const char* gBinaryTemplateData = "BINARYTEMPLATEDATA";
+void fillVector(std::vector<U8>& vector_data, const char* data)
+{
+ vector_data.resize(strlen(data) + 1);
+ strcpy(reinterpret_cast<char*>(&vector_data[0]), data);
+}
+
+namespace tut
+{
+ static LLTemplateMessageReader::message_template_number_map_t numberMap;
+
+ struct LLTemplateMessageDispatcherData
+ {
+ LLTemplateMessageDispatcherData()
+ {
+ mMessageName = "MessageName";
+ gUdpDispatchWasCalled = false;
+ gClearRecvWasCalled = false;
+ gValidateMessage = false;
+ mMessage["body"]["binary-template-data"] = std::vector<U8>();
+ }
+
+ LLSD mMessage;
+ LLHTTPNode::ResponsePtr mResponsePtr;
+ std::string mMessageName;
+ };
+
+ typedef test_group<LLTemplateMessageDispatcherData> factory;
+ typedef factory::object object;
+}
+
+namespace
+{
+ tut::factory tf("LLTemplateMessageDispatcher");
+}
+
+namespace tut
+{
+ // does an empty message stop processing?
+ template<> template<>
+ void object::test<1>()
+ {
+ LLTemplateMessageReader* pReader = NULL;
+ LLTemplateMessageDispatcher t(*pReader);
+ t.dispatch(mMessageName, mMessage, mResponsePtr);
+ ensure(! gUdpDispatchWasCalled);
+ ensure(! gClearRecvWasCalled);
+ }
+
+ // does the disaptch invoke the udp send method?
+ template<> template<>
+ void object::test<2>()
+ {
+ LLTemplateMessageReader* pReader = NULL;
+ LLTemplateMessageDispatcher t(*pReader);
+ gValidateMessage = true;
+ std::vector<U8> vector_data;
+ fillVector(vector_data, gBinaryTemplateData);
+ mMessage["body"]["binary-template-data"] = vector_data;
+ t.dispatch(mMessageName, mMessage, mResponsePtr);
+ ensure("udp dispatch was called", gUdpDispatchWasCalled);
+ }
+
+ // what if the message wasn't valid? We would hope the message gets cleared!
+ template<> template<>
+ void object::test<3>()
+ {
+ LLTemplateMessageReader* pReader = NULL;
+ LLTemplateMessageDispatcher t(*pReader);
+ std::vector<U8> vector_data;
+ fillVector(vector_data, gBinaryTemplateData);
+ mMessage["body"]["binary-template-data"] = vector_data;
+ gValidateMessage = false;
+ t.dispatch(mMessageName, mMessage, mResponsePtr);
+ ensure("clear received message was called", gClearRecvWasCalled);
+ }
+
+ // is the binary data passed through correctly?
+ template<> template<>
+ void object::test<4>()
+ {
+ LLTemplateMessageReader* pReader = NULL;
+ LLTemplateMessageDispatcher t(*pReader);
+ gValidateMessage = true;
+ std::vector<U8> vector_data;
+ fillVector(vector_data, gBinaryTemplateData);
+ mMessage["body"]["binary-template-data"] = vector_data;
+ t.dispatch(mMessageName, mMessage, mResponsePtr);
+ ensure("data couriered correctly", strcmp(gBinaryTemplateData, gUdpDispatchedData) == 0);
+ }
+}
+
diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp
index ee40e0249e..1765a9eccd 100644
--- a/indra/llmessage/tests/lltestmessagesender.cpp
+++ b/indra/llmessage/tests/lltestmessagesender.cpp
@@ -1,25 +1,25 @@
-/**
- * @file
- * @brief
+/**
+ * @file
+ * @brief
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,7 +32,7 @@ LLTestMessageSender::~LLTestMessageSender()
S32 LLTestMessageSender::sendMessage(const LLHost& host, LLStoredMessagePtr message)
{
- mSendHosts.push_back(host);
- mSendMessages.push_back(message);
- return 0;
+ mSendHosts.push_back(host);
+ mSendMessages.push_back(message);
+ return 0;
}
diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h
index bb89289585..e78cfad96e 100644
--- a/indra/llmessage/tests/lltestmessagesender.h
+++ b/indra/llmessage/tests/lltestmessagesender.h
@@ -1,25 +1,25 @@
-/**
- * @file
- * @brief
+/**
+ * @file
+ * @brief
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -38,11 +38,11 @@
class LLTestMessageSender : public LLMessageSenderInterface
{
public:
- virtual ~LLTestMessageSender();
- virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message);
+ virtual ~LLTestMessageSender();
+ virtual S32 sendMessage(const LLHost& host, LLStoredMessagePtr message);
- std::vector<LLHost> mSendHosts;
- std::vector<LLStoredMessagePtr> mSendMessages;
+ std::vector<LLHost> mSendHosts;
+ std::vector<LLStoredMessagePtr> mSendMessages;
};
diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
index 41f982a7e2..cc199141b8 100644
--- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp
+++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp
@@ -5,21 +5,21 @@
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,7 +40,7 @@ LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem;
LLMessageConfig::SenderTrust
LLMessageConfig::getSenderTrustedness(const std::string& msg_name)
{
- return LLMessageConfig::NOT_SET;
+ return LLMessageConfig::NOT_SET;
}
void LLMessageSystem::receivedMessageFromTrustedSender()
@@ -49,12 +49,12 @@ void LLMessageSystem::receivedMessageFromTrustedSender()
bool LLMessageSystem::isTrustedSender(const LLHost& host) const
{
- return false;
+ return false;
}
bool LLMessageSystem::isTrustedMessage(const std::string& name) const
{
- return false;
+ return false;
}
bool messageDispatched = false;
@@ -63,80 +63,80 @@ LLSD lastLLSD;
std::string lastMessageName;
void LLMessageSystem::dispatch(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
{
- messageDispatched = true;
- lastLLSD = message;
- lastMessageName = msg_name;
+ messageDispatched = true;
+ lastLLSD = message;
+ lastMessageName = msg_name;
}
void LLMessageSystem::dispatchTemplate(const std::string& msg_name,
- const LLSD& message,
- LLHTTPNode::ResponsePtr responsep)
+ const LLSD& message,
+ LLHTTPNode::ResponsePtr responsep)
{
- lastLLSD = message;
- lastMessageName = msg_name;
- messageDispatchedAsBinary = true;
+ lastLLSD = message;
+ lastMessageName = msg_name;
+ messageDispatchedAsBinary = true;
}
namespace tut
{
- struct LLTrustedMessageServiceData
- {
- LLTrustedMessageServiceData()
- {
- LLSD emptyLLSD;
- lastLLSD = emptyLLSD;
- lastMessageName = "uninitialised message name";
- messageDispatched = false;
- messageDispatchedAsBinary = false;
- }
- };
-
- typedef test_group<LLTrustedMessageServiceData> factory;
- typedef factory::object object;
+ struct LLTrustedMessageServiceData
+ {
+ LLTrustedMessageServiceData()
+ {
+ LLSD emptyLLSD;
+ lastLLSD = emptyLLSD;
+ lastMessageName = "uninitialised message name";
+ messageDispatched = false;
+ messageDispatchedAsBinary = false;
+ }
+ };
+
+ typedef test_group<LLTrustedMessageServiceData> factory;
+ typedef factory::object object;
}
namespace
{
- tut::factory tf("LLTrustedMessageServiceData");
+ tut::factory tf("LLTrustedMessageServiceData");
}
namespace tut
{
- // characterisation tests
-
- // 1) test that messages get forwarded with names etc. as current behaviour (something like LLMessageSystem::dispatch(name, data...)
-
- // test llsd messages are sent as normal using LLMessageSystem::dispatch() (eventually)
- template<> template<>
- void object::test<1>()
- {
- LLHTTPNode::ResponsePtr response;
- LLSD input;
- LLSD context;
- LLTrustedMessageService adapter;
- adapter.post(response, context, input);
- // test original ting got called wit nowt, ya get me blood?
- ensure_equals(messageDispatched, true);
- ensure(lastLLSD.has("body"));
- }
-
- // test that llsd wrapped binary-template-data messages are
- // sent via LLMessageSystem::binaryDispatch() or similar
- template<> template<>
- void object::test<2>()
- {
- LLHTTPNode::ResponsePtr response;
- LLSD input;
- input["binary-template-data"] = "10001010110"; //make me a message here.
- LLSD context;
- LLTrustedMessageService adapter;
-
- adapter.post(response, context, input);
- ensure("check template-binary-data message was dispatched as binary", messageDispatchedAsBinary);
- ensure_equals(lastLLSD["body"]["binary-template-data"].asString(), "10001010110");
- // test somit got called with "10001010110" (something like LLMessageSystem::dispatchTemplate(blah))
- }
+ // characterisation tests
+
+ // 1) test that messages get forwarded with names etc. as current behaviour (something like LLMessageSystem::dispatch(name, data...)
+
+ // test llsd messages are sent as normal using LLMessageSystem::dispatch() (eventually)
+ template<> template<>
+ void object::test<1>()
+ {
+ LLHTTPNode::ResponsePtr response;
+ LLSD input;
+ LLSD context;
+ LLTrustedMessageService adapter;
+ adapter.post(response, context, input);
+ // test original ting got called wit nowt, ya get me blood?
+ ensure_equals(messageDispatched, true);
+ ensure(lastLLSD.has("body"));
+ }
+
+ // test that llsd wrapped binary-template-data messages are
+ // sent via LLMessageSystem::binaryDispatch() or similar
+ template<> template<>
+ void object::test<2>()
+ {
+ LLHTTPNode::ResponsePtr response;
+ LLSD input;
+ input["binary-template-data"] = "10001010110"; //make me a message here.
+ LLSD context;
+ LLTrustedMessageService adapter;
+
+ adapter.post(response, context, input);
+ ensure("check template-binary-data message was dispatched as binary", messageDispatchedAsBinary);
+ ensure_equals(lastLLSD["body"]["binary-template-data"].asString(), "10001010110");
+ // test somit got called with "10001010110" (something like LLMessageSystem::dispatchTemplate(blah))
+ }
}
diff --git a/indra/llmessage/tests/llxfer_file_test.cpp b/indra/llmessage/tests/llxfer_file_test.cpp
index cf95d2627c..6a2e0566df 100644
--- a/indra/llmessage/tests/llxfer_file_test.cpp
+++ b/indra/llmessage/tests/llxfer_file_test.cpp
@@ -1,58 +1,58 @@
-/**
- * @file llxfer_test.cpp
- * @author Moss
- * @date 2007-04-17
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "../llxfer_file.h"
-
-#include "../test/lltut.h"
-
-namespace tut
-{
- struct llxfer_data
- {
- };
- typedef test_group<llxfer_data> llxfer_test;
- typedef llxfer_test::object llxfer_object;
- tut::llxfer_test llxfer("LLXferFile");
-
- template<> template<>
- void llxfer_object::test<1>()
- {
- // test that we handle an oversized filename correctly.
- std::string oversized_filename;
- U32 i;
- for (i=0; i<LL_MAX_PATH*2; ++i) // create oversized filename
- {
- oversized_filename += 'X';
- }
-
- LLXfer_File xff(oversized_filename, false, 1);
- ensure("oversized local_filename nul-terminated",
- xff.getFileName().length() < LL_MAX_PATH);
- }
-}
+/**
+ * @file llxfer_test.cpp
+ * @author Moss
+ * @date 2007-04-17
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "../llxfer_file.h"
+
+#include "../test/lltut.h"
+
+namespace tut
+{
+ struct llxfer_data
+ {
+ };
+ typedef test_group<llxfer_data> llxfer_test;
+ typedef llxfer_test::object llxfer_object;
+ tut::llxfer_test llxfer("LLXferFile");
+
+ template<> template<>
+ void llxfer_object::test<1>()
+ {
+ // test that we handle an oversized filename correctly.
+ std::string oversized_filename;
+ U32 i;
+ for (i=0; i<LL_MAX_PATH*2; ++i) // create oversized filename
+ {
+ oversized_filename += 'X';
+ }
+
+ LLXfer_File xff(oversized_filename, false, 1);
+ ensure("oversized local_filename nul-terminated",
+ xff.getFileName().length() < LL_MAX_PATH);
+ }
+}
diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h
index 5986524342..a88c4ec596 100644
--- a/indra/llmessage/tests/networkio.h
+++ b/indra/llmessage/tests/networkio.h
@@ -2,26 +2,26 @@
* @file networkio.h
* @author Nat Goodspeed
* @date 2009-01-09
- * @brief
- *
+ * @brief
+ *
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/