forked from libswift/libswift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlive.cpp
204 lines (155 loc) · 5.31 KB
/
live.cpp
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
/*
* live.cpp
* Subclass of ContentTransfer for live streaming.
*
* Arno: Currently uses ever increasing chunk IDs. The binmap datastructure
* can store this quite efficiently, as long as there are few holes.
* The Storage object will save all chunks. The latter can be modified to wrap
* around, that is, a certain modulo is applied that overwrites earlier chunks.
* This modulo is equivalent to the live discard window (see IETF PPSPP spec).
* This overwriting can be done both at the source and in a client.
*
* Created by Arno Bakker.
* Copyright 2009-2016 TECHNISCHE UNIVERSITEIT DELFT. All rights reserved.
*/
//LIVE
#include "swift.h"
#include <cfloat>
#include "ext/live_picker.cpp" // FIXME FIXME FIXME FIXME
using namespace swift;
/*
* Global Variables
*/
std::vector<LiveTransfer*> LiveTransfer::liveswarms;
/*
* Local Constants
*/
#define TRANSFER_DESCR_LIVE_OFFSET 4000000
// Ric: tmp => changed from size_t to uint32_t to avoid compilation problems (otherwise change the def in swift.h)
LiveTransfer::LiveTransfer(std::string filename, const Sha1Hash& swarm_id,bool amsource,uint32_t chunk_size) :
ContentTransfer(LIVE_TRANSFER), swarm_id_(swarm_id), chunk_size_(chunk_size), am_source_(amsource),
filename_(filename), last_chunkid_(0), offset_(0)
{
GlobalAdd();
picker_ = new SimpleLivePiecePicker(this);
picker_->Randomize(rand()&63);
std::string destdir;
int ret = file_exists_utf8(filename);
if (ret == 2 && swarm_id != Sha1Hash::ZERO) {
// Filename is a directory, download to swarmid-as-hex file there
destdir = filename;
filename = destdir+FILE_SEP+swarm_id.hex();
} else {
destdir = dirname_utf8(filename);
if (destdir == "")
destdir = ".";
}
// MULTIFILE
storage_ = new Storage(filename,destdir,td_);
}
LiveTransfer::~LiveTransfer()
{
delete picker_;
GlobalDel();
}
void LiveTransfer::GlobalAdd() {
int idx = liveswarms.size();
td_ = idx + TRANSFER_DESCR_LIVE_OFFSET;
if (liveswarms.size()<idx+1)
liveswarms.resize(idx+1);
liveswarms[idx] = this;
}
void LiveTransfer::GlobalDel() {
int idx = td_ - TRANSFER_DESCR_LIVE_OFFSET;
liveswarms[idx] = NULL;
}
LiveTransfer *LiveTransfer::FindByTD(int td)
{
int idx = td - TRANSFER_DESCR_LIVE_OFFSET;
return idx<liveswarms.size() ? (LiveTransfer *)liveswarms[idx] : NULL;
}
LiveTransfer* LiveTransfer::FindBySwarmID(const Sha1Hash& swarmid) {
for(int i=0; i<liveswarms.size(); i++)
if (liveswarms[i] && liveswarms[i]->swarm_id()==swarmid)
return liveswarms[i];
return NULL;
}
tdlist_t LiveTransfer::GetTransferDescriptors() {
tdlist_t tds;
for(int i=0; i<liveswarms.size(); i++)
if (liveswarms[i] != NULL)
tds.push_back(i+TRANSFER_DESCR_LIVE_OFFSET);
return tds;
}
uint64_t LiveTransfer::SeqComplete() {
if (am_source_)
{
uint64_t seqc = ack_out_.find_empty().base_offset();
return seqc*chunk_size_;
}
bin_t hpos = ((LivePiecePicker *)picker())->GetHookinPos();
bin_t cpos = ((LivePiecePicker *)picker())->GetCurrentPos();
if (hpos == bin_t::NONE || cpos == bin_t::NONE)
return 0;
else
{
uint64_t seqc = cpos.layer_offset() - hpos.layer_offset();
return seqc*chunk_size_;
}
}
uint64_t LiveTransfer::GetHookinOffset() {
bin_t hpos = ((LivePiecePicker *)picker())->GetHookinPos();
uint64_t seqc = hpos.layer_offset();
return seqc*chunk_size_;
}
int LiveTransfer::AddData(const void *buf, size_t nbyte)
{
//fprintf(stderr,"live: AddData: writing to storage %lu\n", nbyte);
// Save chunk on disk
int ret = storage_->Write(buf,nbyte,offset_);
if (ret < 0) {
print_error("live: create: error writing to storage");
return ret;
}
else
fprintf(stderr,"live: AddData: stored " PRISIZET " bytes\n", nbyte);
uint64_t till = std::max((size_t)1,nbyte/chunk_size_);
for (uint64_t c=0; c<till; c++)
{
// New chunk is here
bin_t chunkbin(0,last_chunkid_);
ack_out_.set(chunkbin);
last_chunkid_++;
offset_ += chunk_size_;
}
fprintf(stderr,"live: AddData: added till chunkid %lli\n", last_chunkid_);
dprintf("%s %%0 live: AddData: added till chunkid %lli\n", tintstr(), last_chunkid_);
// Announce chunks to peers
//fprintf(stderr,"live: AddData: announcing to %d channel\n", mychannels_.size() );
channels_t::iterator iter;
for (iter=mychannels_.begin(); iter!=mychannels_.end(); iter++)
{
Channel *c = *iter;
fprintf(stderr,"live: AddData: announce to channel %d\n", c->id() );
dprintf("%s %%0 live: AddData: announce to channel %d\n", tintstr(), c->id() );
//DDOS
if (c->is_established())
c->LiveSend();
}
return 0;
}
void LiveTransfer::UpdateOperational()
{
}
void Channel::LiveSend()
{
//fprintf(stderr,"live: LiveSend: channel %d\n", id() );
if (evsendlive_ptr_ == NULL)
{
evsendlive_ptr_ = new struct event;
// Arno, 2013-02-01: Don't reassign, causes crashes.
evtimer_assign(evsendlive_ptr_,evbase,&Channel::LibeventSendCallback,this);
}
//fprintf(stderr,"live: LiveSend: next %lld\n", next_send_time_ );
evtimer_add(evsendlive_ptr_,tint2tv(next_send_time_));
}