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 void seed::get_torrent_file(int &op_ret
, RGWRados::Object::Read
&read_op
, uint64_t &total_len
,
41 bufferlist
&bl_data
, rgw_obj
&obj
)
43 /* add other field if config is set */
44 dencode
.bencode_dict(bl
);
48 dencode
.bencode(COMMENT
, comment
, bl
);
50 if (!create_by
.empty())
52 dencode
.bencode(CREATED_BY
, create_by
, bl
);
54 if (!encoding
.empty())
56 dencode
.bencode(ENCODING
, encoding
, bl
);
60 map
<string
, bufferlist
> m
;
62 get_obj_bucket_and_oid_loc(obj
, oid
, key
);
63 ldout(s
->cct
, 0) << "NOTICE: head obj oid= " << oid
<< dendl
;
65 obj_key
.insert(RGW_OBJ_TORRENT
);
66 op_ret
= read_op
.state
.io_ctx
.omap_get_vals_by_keys(oid
, obj_key
, &m
);
69 ldout(s
->cct
, 0) << "ERROR: failed to omap_get_vals_by_keys op_ret = " << op_ret
<< dendl
;
73 map
<string
, bufferlist
>::iterator iter
;
74 for (iter
= m
.begin(); iter
!= m
.end(); ++iter
)
76 bufferlist bl_tmp
= iter
->second
;
77 char *pbuff
= bl_tmp
.c_str();
78 bl
.append(pbuff
, bl_tmp
.length());
80 dencode
.bencode_end(bl
);
83 total_len
= bl
.length();
92 void seed::update(bufferlist
&bl
)
98 info
.len
+= bl
.length();
99 sha1(&h
, bl
, bl
.length());
104 uint64_t remain
= info
.len
%info
.piece_length
;
105 uint8_t remain_len
= ((remain
> 0)? 1 : 0);
106 sha_len
= (info
.len
/info
.piece_length
+ remain_len
)*CEPH_CRYPTO_SHA1_DIGESTSIZE
;
109 /* produce torrent data */
112 /* save torrent data into OMAP */
113 ret
= save_torrent_file();
116 ldout(s
->cct
, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret
<< dendl
;
123 off_t
seed::get_data_len()
128 void seed::set_create_date(ceph::real_time
& value
)
130 utime_t date
= ceph::real_clock::to_timespec(value
);
131 create_date
= date
.sec();
134 void seed::set_info_pieces(char *buff
)
136 info
.sha1_bl
.append(buff
, CEPH_CRYPTO_SHA1_DIGESTSIZE
);
139 void seed::set_info_name(const string
& value
)
144 void seed::sha1(SHA1
*h
, bufferlist
&bl
, off_t bl_len
)
146 off_t num
= bl_len
/info
.piece_length
;
148 remain
= bl_len
%info
.piece_length
;
150 char *pstr
= bl
.c_str();
154 for (off_t i
= 0; i
< num
; i
++)
156 memset(sha
, 0x00, sizeof(sha
));
157 h
->Update((byte
*)pstr
, info
.piece_length
);
158 h
->Final((byte
*)sha
);
159 set_info_pieces(sha
);
160 pstr
+= info
.piece_length
;
166 memset(sha
, 0x00, sizeof(sha
));
167 h
->Update((byte
*)pstr
, remain
);
168 h
->Final((byte
*)sha
);
169 set_info_pieces(sha
);
173 int seed::get_params()
176 info
.piece_length
= g_conf
->rgw_torrent_sha_unit
;
177 create_by
= g_conf
->rgw_torrent_createby
;
178 encoding
= g_conf
->rgw_torrent_encoding
;
179 origin
= g_conf
->rgw_torrent_origin
;
180 comment
= g_conf
->rgw_torrent_comment
;
181 announce
= g_conf
->rgw_torrent_tracker
;
183 /* tracker and tracker list is empty, set announce to origin */
184 if (announce
.empty() && !origin
.empty())
192 void seed::set_announce()
194 list
<string
> announce_list
; // used to get announce list from conf
195 get_str_list(announce
, ",", announce_list
);
197 if (announce_list
.empty())
199 ldout(s
->cct
, 5) << "NOTICE: announce_list is empty " << dendl
;
203 list
<string
>::iterator iter
= announce_list
.begin();
204 dencode
.bencode_key(ANNOUNCE
, bl
);
205 dencode
.bencode_key((*iter
), bl
);
207 dencode
.bencode_key(ANNOUNCE_LIST
, bl
);
208 dencode
.bencode_list(bl
);
209 for (; iter
!= announce_list
.end(); ++iter
)
211 dencode
.bencode_list(bl
);
212 dencode
.bencode_key((*iter
), bl
);
213 dencode
.bencode_end(bl
);
215 dencode
.bencode_end(bl
);
218 void seed::do_encode()
220 /*Only encode create_date and sha1 info*/
221 /*Other field will be added if confi is set when run get torrent*/
222 dencode
.bencode(CREATION_DATE
, create_date
, bl
);
224 dencode
.bencode_key(INFO_PIECES
, bl
);
225 dencode
.bencode_dict(bl
);
226 dencode
.bencode(LENGTH
, info
.len
, bl
);
227 dencode
.bencode(NAME
, info
.name
, bl
);
228 dencode
.bencode(PIECE_LENGTH
, info
.piece_length
, bl
);
230 char info_sha
[100] = { 0 };
231 sprintf(info_sha
, "%" PRIu64
, sha_len
);
232 string sha_len_str
= info_sha
;
233 dencode
.bencode_key(PIECES
, bl
);
234 bl
.append(sha_len_str
.c_str(), sha_len_str
.length());
236 bl
.append(info
.sha1_bl
.c_str(), sha_len
);
237 dencode
.bencode_end(bl
);
240 int seed::save_torrent_file()
243 string key
= RGW_OBJ_TORRENT
;
244 rgw_obj
obj(s
->bucket
, s
->object
.name
);
247 store
->obj_to_raw(s
->bucket_info
.placement_rule
, obj
, &raw_obj
);
249 op_ret
= store
->omap_set(raw_obj
, key
, bl
);
252 ldout(s
->cct
, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret
<< dendl
;