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