1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
9 #include "rgw_torrent.h"
11 #include "rgw_sal_rados.h"
12 #include "include/str_list.h"
13 #include "include/rados/librados.hpp"
15 #include "services/svc_sys_obj.h"
17 #define dout_subsys ceph_subsys_rgw
19 using ceph::crypto::MD5
;
20 using namespace librados
;
21 using namespace boost
;
22 using ceph::crypto::SHA1
;
26 seed::info
.piece_length
= 0;
34 seed::info
.sha1_bl
.clear();
40 void seed::init(struct req_state
*p_req
, rgw::sal::RGWRadosStore
*p_store
)
46 int seed::get_torrent_file(rgw::sal::RGWObject
* object
,
48 ceph::bufferlist
&bl_data
,
51 /* add other field if config is set */
52 dencode
.bencode_dict(bl
);
56 dencode
.bencode(COMMENT
, comment
, bl
);
58 if (!create_by
.empty())
60 dencode
.bencode(CREATED_BY
, create_by
, bl
);
62 if (!encoding
.empty())
64 dencode
.bencode(ENCODING
, encoding
, bl
);
68 get_obj_bucket_and_oid_loc(obj
, oid
, key
);
69 ldpp_dout(s
, 20) << "NOTICE: head obj oid= " << oid
<< dendl
;
71 const set
<string
> obj_key
{RGW_OBJ_TORRENT
};
72 map
<string
, bufferlist
> m
;
73 const int r
= object
->omap_get_vals_by_keys(s
, oid
, obj_key
, &m
);
75 ldpp_dout(s
, 0) << "ERROR: omap_get_vals_by_keys failed: " << r
<< dendl
;
79 ldpp_dout(s
, 0) << "ERROR: omap key " RGW_OBJ_TORRENT
" not found" << dendl
;
82 bl
.append(std::move(m
.begin()->second
));
83 dencode
.bencode_end(bl
);
86 total_len
= bl
.length();
95 void seed::update(bufferlist
&bl
)
101 info
.len
+= bl
.length();
102 sha1(&h
, bl
, bl
.length());
105 int seed::complete(optional_yield y
)
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
;
112 /* produce torrent data */
115 /* save torrent data into OMAP */
116 ret
= save_torrent_file(y
);
119 ldpp_dout(s
, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret
<< dendl
;
126 off_t
seed::get_data_len()
131 void seed::set_create_date(ceph::real_time
& value
)
133 utime_t date
= ceph::real_clock::to_timespec(value
);
134 create_date
= date
.sec();
137 void seed::set_info_pieces(char *buff
)
139 info
.sha1_bl
.append(buff
, CEPH_CRYPTO_SHA1_DIGESTSIZE
);
142 void seed::set_info_name(const string
& value
)
147 void seed::sha1(SHA1
*h
, bufferlist
&bl
, off_t bl_len
)
149 off_t num
= bl_len
/info
.piece_length
;
151 remain
= bl_len
%info
.piece_length
;
153 char *pstr
= bl
.c_str();
157 for (off_t i
= 0; i
< num
; i
++)
159 // FIPS zeroization audit 20191116: this memset is not intended to
160 // wipe out a secret after use.
161 memset(sha
, 0x00, sizeof(sha
));
162 h
->Update((unsigned char *)pstr
, info
.piece_length
);
163 h
->Final((unsigned char *)sha
);
164 set_info_pieces(sha
);
165 pstr
+= info
.piece_length
;
171 // FIPS zeroization audit 20191116: this memset is not intended to
172 // wipe out a secret after use.
173 memset(sha
, 0x00, sizeof(sha
));
174 h
->Update((unsigned char *)pstr
, remain
);
175 h
->Final((unsigned char *)sha
);
176 set_info_pieces(sha
);
178 ::ceph::crypto::zeroize_for_security(sha
, sizeof(sha
));
181 int seed::get_params()
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
;
191 /* tracker and tracker list is empty, set announce to origin */
192 if (announce
.empty() && !origin
.empty())
200 void seed::set_announce()
202 list
<string
> announce_list
; // used to get announce list from conf
203 get_str_list(announce
, ",", announce_list
);
205 if (announce_list
.empty())
207 ldpp_dout(s
, 5) << "NOTICE: announce_list is empty " << dendl
;
211 list
<string
>::iterator iter
= announce_list
.begin();
212 dencode
.bencode_key(ANNOUNCE
, bl
);
213 dencode
.bencode_key((*iter
), bl
);
215 dencode
.bencode_key(ANNOUNCE_LIST
, bl
);
216 dencode
.bencode_list(bl
);
217 for (; iter
!= announce_list
.end(); ++iter
)
219 dencode
.bencode_list(bl
);
220 dencode
.bencode_key((*iter
), bl
);
221 dencode
.bencode_end(bl
);
223 dencode
.bencode_end(bl
);
226 void seed::do_encode()
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
);
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
);
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());
244 bl
.append(info
.sha1_bl
.c_str(), sha_len
);
245 dencode
.bencode_end(bl
);
248 int seed::save_torrent_file(optional_yield y
)
251 string key
= RGW_OBJ_TORRENT
;
252 rgw_obj
obj(s
->bucket
->get_key(), s
->object
->get_name());
255 store
->getRados()->obj_to_raw(s
->bucket
->get_info().placement_rule
, obj
, &raw_obj
);
257 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
258 auto sysobj
= obj_ctx
.get_obj(raw_obj
);
260 op_ret
= sysobj
.omap().set(s
, key
, bl
, y
);
263 ldpp_dout(s
, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret
<< dendl
;