6 #include "rgw_torrent.h"
7 #include "include/str_list.h"
8 #include "include/rados/librados.hpp"
10 #define dout_subsys ceph_subsys_rgw
13 using ceph::crypto::MD5
;
14 using namespace librados
;
15 using namespace boost
;
16 using ceph::crypto::SHA1
;
20 seed::info
.piece_length
= 0;
28 seed::info
.sha1_bl
.clear();
34 void seed::init(struct req_state
*p_req
, RGWRados
*p_store
)
40 int seed::get_torrent_file(RGWRados::Object::Read
&read_op
,
42 ceph::bufferlist
&bl_data
,
45 /* add other field if config is set */
46 dencode
.bencode_dict(bl
);
50 dencode
.bencode(COMMENT
, comment
, bl
);
52 if (!create_by
.empty())
54 dencode
.bencode(CREATED_BY
, create_by
, bl
);
56 if (!encoding
.empty())
58 dencode
.bencode(ENCODING
, encoding
, bl
);
62 get_obj_bucket_and_oid_loc(obj
, oid
, key
);
63 ldout(s
->cct
, 20) << "NOTICE: head obj oid= " << oid
<< dendl
;
65 const set
<string
> obj_key
{RGW_OBJ_TORRENT
};
66 map
<string
, bufferlist
> m
;
67 const int r
= read_op
.state
.io_ctx
.omap_get_vals_by_keys(oid
, obj_key
, &m
);
69 ldout(s
->cct
, 0) << "ERROR: omap_get_vals_by_keys failed: " << r
<< dendl
;
73 ldout(s
->cct
, 0) << "ERROR: omap key " RGW_OBJ_TORRENT
" not found" << dendl
;
76 bl
.append(std::move(m
.begin()->second
));
77 dencode
.bencode_end(bl
);
80 total_len
= bl
.length();
89 void seed::update(bufferlist
&bl
)
95 info
.len
+= bl
.length();
96 sha1(&h
, bl
, bl
.length());
101 uint64_t remain
= info
.len
%info
.piece_length
;
102 uint8_t remain_len
= ((remain
> 0)? 1 : 0);
103 sha_len
= (info
.len
/info
.piece_length
+ remain_len
)*CEPH_CRYPTO_SHA1_DIGESTSIZE
;
106 /* produce torrent data */
109 /* save torrent data into OMAP */
110 ret
= save_torrent_file();
113 ldout(s
->cct
, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret
<< dendl
;
120 off_t
seed::get_data_len()
125 void seed::set_create_date(ceph::real_time
& value
)
127 utime_t date
= ceph::real_clock::to_timespec(value
);
128 create_date
= date
.sec();
131 void seed::set_info_pieces(char *buff
)
133 info
.sha1_bl
.append(buff
, CEPH_CRYPTO_SHA1_DIGESTSIZE
);
136 void seed::set_info_name(const string
& value
)
141 void seed::sha1(SHA1
*h
, bufferlist
&bl
, off_t bl_len
)
143 off_t num
= bl_len
/info
.piece_length
;
145 remain
= bl_len
%info
.piece_length
;
147 char *pstr
= bl
.c_str();
151 for (off_t i
= 0; i
< num
; i
++)
153 memset(sha
, 0x00, sizeof(sha
));
154 h
->Update((byte
*)pstr
, info
.piece_length
);
155 h
->Final((byte
*)sha
);
156 set_info_pieces(sha
);
157 pstr
+= info
.piece_length
;
163 memset(sha
, 0x00, sizeof(sha
));
164 h
->Update((byte
*)pstr
, remain
);
165 h
->Final((byte
*)sha
);
166 set_info_pieces(sha
);
170 int seed::get_params()
173 info
.piece_length
= g_conf
->rgw_torrent_sha_unit
;
174 create_by
= g_conf
->rgw_torrent_createby
;
175 encoding
= g_conf
->rgw_torrent_encoding
;
176 origin
= g_conf
->rgw_torrent_origin
;
177 comment
= g_conf
->rgw_torrent_comment
;
178 announce
= g_conf
->rgw_torrent_tracker
;
180 /* tracker and tracker list is empty, set announce to origin */
181 if (announce
.empty() && !origin
.empty())
189 void seed::set_announce()
191 list
<string
> announce_list
; // used to get announce list from conf
192 get_str_list(announce
, ",", announce_list
);
194 if (announce_list
.empty())
196 ldout(s
->cct
, 5) << "NOTICE: announce_list is empty " << dendl
;
200 list
<string
>::iterator iter
= announce_list
.begin();
201 dencode
.bencode_key(ANNOUNCE
, bl
);
202 dencode
.bencode_key((*iter
), bl
);
204 dencode
.bencode_key(ANNOUNCE_LIST
, bl
);
205 dencode
.bencode_list(bl
);
206 for (; iter
!= announce_list
.end(); ++iter
)
208 dencode
.bencode_list(bl
);
209 dencode
.bencode_key((*iter
), bl
);
210 dencode
.bencode_end(bl
);
212 dencode
.bencode_end(bl
);
215 void seed::do_encode()
217 /*Only encode create_date and sha1 info*/
218 /*Other field will be added if confi is set when run get torrent*/
219 dencode
.bencode(CREATION_DATE
, create_date
, bl
);
221 dencode
.bencode_key(INFO_PIECES
, bl
);
222 dencode
.bencode_dict(bl
);
223 dencode
.bencode(LENGTH
, info
.len
, bl
);
224 dencode
.bencode(NAME
, info
.name
, bl
);
225 dencode
.bencode(PIECE_LENGTH
, info
.piece_length
, bl
);
227 char info_sha
[100] = { 0 };
228 sprintf(info_sha
, "%" PRIu64
, sha_len
);
229 string sha_len_str
= info_sha
;
230 dencode
.bencode_key(PIECES
, bl
);
231 bl
.append(sha_len_str
.c_str(), sha_len_str
.length());
233 bl
.append(info
.sha1_bl
.c_str(), sha_len
);
234 dencode
.bencode_end(bl
);
237 int seed::save_torrent_file()
240 string key
= RGW_OBJ_TORRENT
;
241 rgw_obj
obj(s
->bucket
, s
->object
.name
);
244 store
->obj_to_raw(s
->bucket_info
.placement_rule
, obj
, &raw_obj
);
246 op_ret
= store
->omap_set(raw_obj
, key
, bl
);
249 ldout(s
->cct
, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret
<< dendl
;