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
|
/**
* @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;
class LLVFS;
#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
{
private:
LLVFS *mVFS;
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;
private:
protected:
// implementation methods
virtual void startPendingDownloads();
virtual void addToList(LLXfer* xferp, xfer_list_t & 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
public:
LLXferManager(LLVFS *vfs);
virtual ~LLXferManager();
virtual void init(LLVFS *vfs);
virtual void cleanup();
void setUseAckThrottling(const BOOL use);
void setAckThrottleBPS(const F32 bps);
// list management routines
virtual LLXfer *findXfer(U64 id, xfer_list_t & xfer_list);
virtual void removeXfer (LLXfer *delp, xfer_list_t & xfer_list);
LLHostStatus * findHostStatus(const LLHost &host);
virtual U32 numActiveListEntries(LLXfer *list_head);
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, LLVFS* vfs,
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);
/*
// xfer request (may be memory or file)
// .. to file
virtual void requestXfer(const char *local_filename, U64 xfer_id,
BOOL delete_remote_on_completion,
const LLHost &remote_host, void (*callback)(void **,S32),void **user_data);
// .. to memory
virtual void requestXfer(U64 xfer_id,
const LLHost &remote_host,
BOOL delete_remote_on_completion,
void (*callback)(void *, S32, void **, S32),void **user_data);
*/
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(LLVFS *vfs);
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
|