summaryrefslogtreecommitdiff
path: root/indra/llmessage/lltransfermanager.h
blob: 15097642b4bed132e30b0cfba0236457e2b8f8d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
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