]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
11fdf7f2 | 3 | |
7c673cae FG |
4 | #include <errno.h> |
5 | #include <stdlib.h> | |
6 | ||
7 | #include <sstream> | |
8 | ||
9 | #include "rgw_torrent.h" | |
9f95a23c | 10 | #include "rgw_sal.h" |
f67539c2 | 11 | #include "rgw_sal_rados.h" |
7c673cae FG |
12 | #include "include/str_list.h" |
13 | #include "include/rados/librados.hpp" | |
14 | ||
11fdf7f2 TL |
15 | #include "services/svc_sys_obj.h" |
16 | ||
7c673cae FG |
17 | #define dout_subsys ceph_subsys_rgw |
18 | ||
20effc67 | 19 | using namespace std; |
7c673cae FG |
20 | using namespace librados; |
21 | using namespace boost; | |
22 | using ceph::crypto::SHA1; | |
23 | ||
24 | seed::seed() | |
25 | { | |
26 | seed::info.piece_length = 0; | |
27 | seed::info.len = 0; | |
28 | sha_len = 0; | |
29 | is_torrent = false; | |
30 | } | |
31 | ||
32 | seed::~seed() | |
33 | { | |
34 | seed::info.sha1_bl.clear(); | |
35 | bl.clear(); | |
7c673cae | 36 | s = NULL; |
1e59de90 | 37 | driver = NULL; |
7c673cae FG |
38 | } |
39 | ||
1e59de90 | 40 | void seed::init(req_state *_req, rgw::sal::Driver* _driver) |
7c673cae | 41 | { |
1e59de90 TL |
42 | s = _req; |
43 | driver = _driver; | |
7c673cae FG |
44 | } |
45 | ||
20effc67 | 46 | int seed::get_torrent_file(rgw::sal::Object* object, |
3efd9988 FG |
47 | uint64_t &total_len, |
48 | ceph::bufferlist &bl_data, | |
49 | rgw_obj &obj) | |
7c673cae FG |
50 | { |
51 | /* add other field if config is set */ | |
52 | dencode.bencode_dict(bl); | |
53 | set_announce(); | |
54 | if (!comment.empty()) | |
55 | { | |
56 | dencode.bencode(COMMENT, comment, bl); | |
57 | } | |
58 | if (!create_by.empty()) | |
59 | { | |
60 | dencode.bencode(CREATED_BY, create_by, bl); | |
61 | } | |
62 | if (!encoding.empty()) | |
63 | { | |
64 | dencode.bencode(ENCODING, encoding, bl); | |
65 | } | |
66 | ||
67 | string oid, key; | |
7c673cae | 68 | get_obj_bucket_and_oid_loc(obj, oid, key); |
b3b6e05e | 69 | ldpp_dout(s, 20) << "NOTICE: head obj oid= " << oid << dendl; |
7c673cae | 70 | |
28e407b8 AA |
71 | const set<string> obj_key{RGW_OBJ_TORRENT}; |
72 | map<string, bufferlist> m; | |
b3b6e05e | 73 | const int r = object->omap_get_vals_by_keys(s, oid, obj_key, &m); |
28e407b8 | 74 | if (r < 0) { |
b3b6e05e | 75 | ldpp_dout(s, 0) << "ERROR: omap_get_vals_by_keys failed: " << r << dendl; |
28e407b8 | 76 | return r; |
7c673cae | 77 | } |
28e407b8 | 78 | if (m.size() != 1) { |
b3b6e05e | 79 | ldpp_dout(s, 0) << "ERROR: omap key " RGW_OBJ_TORRENT " not found" << dendl; |
28e407b8 | 80 | return -EINVAL; |
7c673cae | 81 | } |
28e407b8 | 82 | bl.append(std::move(m.begin()->second)); |
7c673cae FG |
83 | dencode.bencode_end(bl); |
84 | ||
85 | bl_data = bl; | |
86 | total_len = bl.length(); | |
3efd9988 | 87 | return 0; |
7c673cae FG |
88 | } |
89 | ||
90 | bool seed::get_flag() | |
91 | { | |
92 | return is_torrent; | |
93 | } | |
94 | ||
31f18b77 | 95 | void seed::update(bufferlist &bl) |
7c673cae FG |
96 | { |
97 | if (!is_torrent) | |
98 | { | |
99 | return; | |
100 | } | |
7c673cae | 101 | info.len += bl.length(); |
31f18b77 FG |
102 | sha1(&h, bl, bl.length()); |
103 | } | |
104 | ||
f67539c2 | 105 | int seed::complete(optional_yield y) |
31f18b77 FG |
106 | { |
107 | uint64_t remain = info.len%info.piece_length; | |
108 | uint8_t remain_len = ((remain > 0)? 1 : 0); | |
109 | sha_len = (info.len/info.piece_length + remain_len)*CEPH_CRYPTO_SHA1_DIGESTSIZE; | |
110 | ||
111 | int ret = 0; | |
112 | /* produce torrent data */ | |
113 | do_encode(); | |
114 | ||
115 | /* save torrent data into OMAP */ | |
f67539c2 | 116 | ret = save_torrent_file(y); |
31f18b77 FG |
117 | if (0 != ret) |
118 | { | |
b3b6e05e | 119 | ldpp_dout(s, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret << dendl; |
31f18b77 FG |
120 | return ret; |
121 | } | |
122 | ||
123 | return 0; | |
7c673cae FG |
124 | } |
125 | ||
126 | off_t seed::get_data_len() | |
127 | { | |
128 | return info.len; | |
129 | } | |
130 | ||
131 | void seed::set_create_date(ceph::real_time& value) | |
132 | { | |
133 | utime_t date = ceph::real_clock::to_timespec(value); | |
134 | create_date = date.sec(); | |
135 | } | |
136 | ||
137 | void seed::set_info_pieces(char *buff) | |
138 | { | |
139 | info.sha1_bl.append(buff, CEPH_CRYPTO_SHA1_DIGESTSIZE); | |
140 | } | |
141 | ||
142 | void seed::set_info_name(const string& value) | |
143 | { | |
144 | info.name = value; | |
145 | } | |
146 | ||
147 | void seed::sha1(SHA1 *h, bufferlist &bl, off_t bl_len) | |
148 | { | |
149 | off_t num = bl_len/info.piece_length; | |
150 | off_t remain = 0; | |
151 | remain = bl_len%info.piece_length; | |
152 | ||
153 | char *pstr = bl.c_str(); | |
154 | char sha[25]; | |
155 | ||
156 | /* get sha1 */ | |
157 | for (off_t i = 0; i < num; i++) | |
158 | { | |
92f5a8d4 TL |
159 | // FIPS zeroization audit 20191116: this memset is not intended to |
160 | // wipe out a secret after use. | |
7c673cae | 161 | memset(sha, 0x00, sizeof(sha)); |
11fdf7f2 TL |
162 | h->Update((unsigned char *)pstr, info.piece_length); |
163 | h->Final((unsigned char *)sha); | |
7c673cae FG |
164 | set_info_pieces(sha); |
165 | pstr += info.piece_length; | |
166 | } | |
167 | ||
168 | /* process remain */ | |
169 | if (0 != remain) | |
170 | { | |
92f5a8d4 TL |
171 | // FIPS zeroization audit 20191116: this memset is not intended to |
172 | // wipe out a secret after use. | |
7c673cae | 173 | memset(sha, 0x00, sizeof(sha)); |
11fdf7f2 TL |
174 | h->Update((unsigned char *)pstr, remain); |
175 | h->Final((unsigned char *)sha); | |
7c673cae FG |
176 | set_info_pieces(sha); |
177 | } | |
92f5a8d4 | 178 | ::ceph::crypto::zeroize_for_security(sha, sizeof(sha)); |
7c673cae FG |
179 | } |
180 | ||
7c673cae FG |
181 | int seed::get_params() |
182 | { | |
183 | is_torrent = true; | |
11fdf7f2 TL |
184 | info.piece_length = g_conf()->rgw_torrent_sha_unit; |
185 | create_by = g_conf()->rgw_torrent_createby; | |
186 | encoding = g_conf()->rgw_torrent_encoding; | |
187 | origin = g_conf()->rgw_torrent_origin; | |
188 | comment = g_conf()->rgw_torrent_comment; | |
189 | announce = g_conf()->rgw_torrent_tracker; | |
7c673cae FG |
190 | |
191 | /* tracker and tracker list is empty, set announce to origin */ | |
192 | if (announce.empty() && !origin.empty()) | |
193 | { | |
194 | announce = origin; | |
195 | } | |
196 | ||
197 | return 0; | |
198 | } | |
199 | ||
200 | void seed::set_announce() | |
201 | { | |
202 | list<string> announce_list; // used to get announce list from conf | |
203 | get_str_list(announce, ",", announce_list); | |
204 | ||
205 | if (announce_list.empty()) | |
206 | { | |
b3b6e05e | 207 | ldpp_dout(s, 5) << "NOTICE: announce_list is empty " << dendl; |
7c673cae FG |
208 | return; |
209 | } | |
210 | ||
211 | list<string>::iterator iter = announce_list.begin(); | |
212 | dencode.bencode_key(ANNOUNCE, bl); | |
213 | dencode.bencode_key((*iter), bl); | |
214 | ||
215 | dencode.bencode_key(ANNOUNCE_LIST, bl); | |
216 | dencode.bencode_list(bl); | |
217 | for (; iter != announce_list.end(); ++iter) | |
218 | { | |
219 | dencode.bencode_list(bl); | |
220 | dencode.bencode_key((*iter), bl); | |
221 | dencode.bencode_end(bl); | |
222 | } | |
223 | dencode.bencode_end(bl); | |
224 | } | |
225 | ||
226 | void seed::do_encode() | |
227 | { | |
228 | /*Only encode create_date and sha1 info*/ | |
229 | /*Other field will be added if confi is set when run get torrent*/ | |
230 | dencode.bencode(CREATION_DATE, create_date, bl); | |
231 | ||
232 | dencode.bencode_key(INFO_PIECES, bl); | |
233 | dencode.bencode_dict(bl); | |
234 | dencode.bencode(LENGTH, info.len, bl); | |
235 | dencode.bencode(NAME, info.name, bl); | |
236 | dencode.bencode(PIECE_LENGTH, info.piece_length, bl); | |
237 | ||
238 | char info_sha[100] = { 0 }; | |
239 | sprintf(info_sha, "%" PRIu64, sha_len); | |
240 | string sha_len_str = info_sha; | |
241 | dencode.bencode_key(PIECES, bl); | |
242 | bl.append(sha_len_str.c_str(), sha_len_str.length()); | |
243 | bl.append(':'); | |
244 | bl.append(info.sha1_bl.c_str(), sha_len); | |
245 | dencode.bencode_end(bl); | |
246 | } | |
247 | ||
f67539c2 | 248 | int seed::save_torrent_file(optional_yield y) |
7c673cae FG |
249 | { |
250 | int op_ret = 0; | |
251 | string key = RGW_OBJ_TORRENT; | |
7c673cae | 252 | |
20effc67 | 253 | op_ret = s->object->omap_set_val_by_key(s, key, bl, false, y); |
7c673cae FG |
254 | if (op_ret < 0) |
255 | { | |
b3b6e05e | 256 | ldpp_dout(s, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret << dendl; |
7c673cae FG |
257 | return op_ret; |
258 | } | |
259 | ||
260 | return op_ret; | |
261 | } |