00001
00002
00003
00004
00005 #include "stdafx.h"
00006 #include "vmsBtSessionImpl.h"
00007 #include "vmsBtFileImpl.h"
00008 #include <libtorrent/alert_types.hpp>
00009 #include <libtorrent/extensions/ut_pex.hpp>
00010
00011 __declspec(dllexport) vmsBtSession* WINAPI vmsBt_getSession ()
00012 {
00013 return vmsBtSessionImpl::Instance ();
00014 }
00015
00016 __declspec(dllexport) void WINAPI vmsBt_Shutdown ()
00017 {
00018 delete vmsBtSessionImpl::Instance ();
00019 }
00020
00021 vmsBtSessionImpl::vmsBtSessionImpl(void)
00022 {
00023 m_bDHTstarted = FALSE;
00024 m_session.set_severity_level (alert::info);
00025 m_session.add_extension (libtorrent::create_ut_pex_plugin);
00026 m_session.set_max_half_open_connections (5);
00027 m_bThreadRunning = true;
00028 m_bNeedStop = false;
00029 m_pfnEvHandler = NULL;
00030 InitializeCriticalSection (&m_csRestoreTorrentHandle);
00031 InitializeCriticalSection (&m_csDeleteDownload);
00032 DWORD dw;
00033 CloseHandle (
00034 CreateThread (NULL, 0, _threadSession, this, 0, &dw));
00035 }
00036
00037 vmsBtSessionImpl::~vmsBtSessionImpl(void)
00038 {
00039 m_bNeedStop = true;
00040 while (m_bThreadRunning)
00041 Sleep (10);
00042 DeleteCriticalSection (&m_csRestoreTorrentHandle);
00043 DeleteCriticalSection (&m_csDeleteDownload);
00044 }
00045
00046 vmsBtDownload* vmsBtSessionImpl::CreateDownload (vmsBtFile *torrent, LPCSTR pszOutputPath, LPBYTE pbFastResumeData, DWORD dwFRDataSize, BOOL bCompactMode)
00047 {
00048 char szPath [10000];
00049 strcpy (szPath, pszOutputPath);
00050 LPSTR psz = szPath;
00051 while (*psz)
00052 {
00053 if (*psz == '\\')
00054 *psz = '/';
00055 psz++;
00056 }
00057
00058 try
00059 {
00060 torrent_handle th;
00061 vmsBtFileImpl *torrentimpl = (vmsBtFileImpl*) torrent;
00062
00063 entry e2 = pbFastResumeData ? bdecode (pbFastResumeData, pbFastResumeData + dwFRDataSize) : entry ();
00064
00065 th = m_session.add_torrent (*torrentimpl->m_torrent, szPath, e2, bCompactMode != 0);
00066 th.set_ratio (1);
00067
00068 vmsBtDownloadImpl *pDld = new vmsBtDownloadImpl;
00069 pDld->m_handle = th;
00070 pDld->m_pTorrent = torrentimpl; torrentimpl->AddRef ();
00071 pDld->m_strOutputPath = szPath;
00072
00073 m_vDownloads.push_back (pDld);
00074 return pDld;
00075 }
00076 catch (std::exception&)
00077 {
00078 return NULL;
00079 }
00080 }
00081
00082 void vmsBtSessionImpl::DeleteDownload (vmsBtDownload* pDld)
00083 {
00084 EnterCriticalSection (&m_csDeleteDownload);
00085
00086 vmsBtDownloadImpl *p = dynamic_cast <vmsBtDownloadImpl*> (pDld);
00087 if (p)
00088 {
00089 int nIndex = FindDownloadIndex (p->m_handle);
00090 if (nIndex != -1)
00091 m_vDownloads.erase (m_vDownloads.begin () + nIndex);
00092 try {
00093 m_session.remove_torrent (p->m_handle);
00094 }catch (...) {}
00095 delete p;
00096 }
00097
00098 LeaveCriticalSection (&m_csDeleteDownload);
00099 }
00100
00101 vmsBtSessionImpl* vmsBtSessionImpl::Instance ()
00102 {
00103 static vmsBtSessionImpl* _p = NULL;
00104 if (_p == NULL)
00105 {
00106 try {
00107 _p = new vmsBtSessionImpl;
00108 }
00109 catch (...) {
00110 _p = NULL;
00111 }
00112 }
00113 return _p;
00114 }
00115
00116 void vmsBtSessionImpl::SetDownloadLimit (int limit)
00117 {
00118 m_session.set_download_rate_limit (limit);
00119 }
00120
00121 void vmsBtSessionImpl::SetUploadLimit (int limit)
00122 {
00123 m_session.set_upload_rate_limit (limit);
00124 }
00125
00126 void vmsBtSessionImpl::ListenOn (int portFrom, int portTo)
00127 {
00128 m_session.listen_on (std::make_pair (portFrom, portTo));
00129 }
00130
00131 BOOL vmsBtSessionImpl::IsListening ()
00132 {
00133 return m_session.is_listening ();
00134 }
00135
00136 USHORT vmsBtSessionImpl::get_ListenPort ()
00137 {
00138 return m_session.listen_port ();
00139 }
00140
00141 void vmsBtSessionImpl::SetMaxUploads (int limit)
00142 {
00143 m_session.set_max_uploads (limit);
00144 }
00145
00146 void vmsBtSessionImpl::DHT_start (LPBYTE pbState, DWORD dwStateSize)
00147 {
00148 if (m_bDHTstarted)
00149 return;
00150 m_bDHTstarted = TRUE;
00151 m_session.start_dht (pbState ? bdecode (pbState, pbState + dwStateSize) : entry ());
00152 }
00153
00154 void vmsBtSessionImpl::DHT_stop ()
00155 {
00156 if (m_bDHTstarted == FALSE)
00157 return;
00158 m_session.stop_dht ();
00159 m_bDHTstarted = FALSE;
00160 }
00161
00162 BOOL vmsBtSessionImpl::DHT_getState (LPBYTE pbBuffer, DWORD dwBufferSize, LPDWORD pdwDataSize)
00163 {
00164 std::vector <char> v;
00165 bencode (std::back_inserter (v), m_session.dht_state ());
00166
00167 *pdwDataSize = v.size ();
00168
00169 if (pbBuffer == NULL)
00170 return TRUE;
00171
00172 if (dwBufferSize < v.size ())
00173 return FALSE;
00174
00175 for (size_t i = 0; i < v.size (); i++)
00176 *pbBuffer++ = v [i];
00177
00178 return TRUE;
00179 }
00180
00181 BOOL vmsBtSessionImpl::DHT_isStarted ()
00182 {
00183 return m_bDHTstarted;
00184 }
00185
00186 DWORD vmsBtSessionImpl::_threadSession (LPVOID lp)
00187 {
00188 vmsBtSessionImpl* pthis = (vmsBtSessionImpl*)lp;
00189
00190 while (pthis->m_bNeedStop == false)
00191 {
00192 Sleep (100);
00193
00194
00195 std::auto_ptr <alert> alert = pthis->m_session.pop_alert ();
00196 if (alert.get () == NULL)
00197 continue;
00198
00199 if (pthis->m_pfnEvHandler == NULL)
00200 continue;
00201
00202 vmsBtSessionEvent ev;
00203 ev.pszMsg = alert->msg ().c_str ();
00204
00205
00206 int iDownloadIndex = -1;
00207 std::string strIp;
00208
00209 listen_failed_alert *lfa = dynamic_cast <listen_failed_alert*> (alert.get ());
00210 if (lfa != NULL)
00211 {
00212 ev.enType = BTSET_LISTEN_FAILED;
00213 goto _lRaiseEvent;
00214 }
00215
00216 file_error_alert *fea = dynamic_cast <file_error_alert*> (alert.get ());
00217 if (fea != NULL)
00218 {
00219 ev.enType = BTSET_FILE_ERROR;
00220 iDownloadIndex = pthis->FindDownloadIndex (fea->handle);
00221 goto _lRaiseEvent;
00222 }
00223
00224 tracker_announce_alert *taa = dynamic_cast <tracker_announce_alert*> (alert.get ());
00225 if (taa != NULL)
00226 {
00227 ev.enType = BTSET_TRACKER_ANNOUNCE;
00228 iDownloadIndex = pthis->FindDownloadIndex (taa->handle);
00229 goto _lRaiseEvent;
00230 }
00231
00232 tracker_alert *ta = dynamic_cast <tracker_alert*> (alert.get ());
00233 if (ta != NULL)
00234 {
00235 ev.enType = BTSET_TRACKER;
00236 iDownloadIndex = pthis->FindDownloadIndex (ta->handle);
00237 ev.times_in_row = ta->times_in_row;
00238 ev.status_code = ta->status_code;
00239 goto _lRaiseEvent;
00240 }
00241
00242 tracker_reply_alert *tra = dynamic_cast <tracker_reply_alert*> (alert.get ());
00243 if (tra != NULL)
00244 {
00245 ev.enType = BTSET_TRACKER_REPLY;
00246 iDownloadIndex = pthis->FindDownloadIndex (tra->handle);
00247 goto _lRaiseEvent;
00248 }
00249
00250 tracker_warning_alert *twa = dynamic_cast <tracker_warning_alert*> (alert.get ());
00251 if (twa != NULL)
00252 {
00253 ev.enType = BTSET_TRACKER_WARNING;
00254 iDownloadIndex = pthis->FindDownloadIndex (twa->handle);
00255 goto _lRaiseEvent;
00256 }
00257
00258 url_seed_alert *usa = dynamic_cast <url_seed_alert*> (alert.get ());
00259 if (usa != NULL)
00260 {
00261 ev.enType = BTSET_URL_SEED;
00262 ev.pszUrl = usa->url.c_str ();
00263 goto _lRaiseEvent;
00264 }
00265
00266 hash_failed_alert *hfa = dynamic_cast <hash_failed_alert*> (alert.get ());
00267 if (hfa != NULL)
00268 {
00269 ev.enType = BTSET_HASH_FAILED;
00270 iDownloadIndex = pthis->FindDownloadIndex (hfa->handle);
00271 ev.piece_index = hfa->piece_index;
00272 goto _lRaiseEvent;
00273 }
00274
00275 peer_ban_alert *pba = dynamic_cast <peer_ban_alert*> (alert.get ());
00276 if (pba != NULL)
00277 {
00278 ev.enType = BTSET_PEER_BAN;
00279 iDownloadIndex = pthis->FindDownloadIndex (pba->handle);
00280 strIp = pba->ip.address ().to_string ().c_str ();
00281 ev.pszIp = strIp.c_str ();
00282 goto _lRaiseEvent;
00283 }
00284
00285 peer_error_alert *pea = dynamic_cast <peer_error_alert*> (alert.get ());
00286 if (pea != NULL)
00287 {
00288 ev.enType = BTSET_PEER_ERROR;
00289 strIp = pea->ip.address ().to_string ().c_str ();
00290 ev.pszIp = strIp.c_str ();
00291 goto _lRaiseEvent;
00292 }
00293
00294 torrent_finished_alert *tfa = dynamic_cast <torrent_finished_alert*> (alert.get ());
00295 if (tfa != NULL)
00296 {
00297 ev.enType = BTSET_TORRENT_FINISHED;
00298 goto _lRaiseEvent;
00299 }
00300
00301 continue;
00302
00303 _lRaiseEvent:
00304
00305 if (iDownloadIndex != -1)
00306 ev.pDownload = pthis->m_vDownloads [iDownloadIndex];
00307 else
00308 ev.pDownload = NULL;
00309
00310 pthis->m_pfnEvHandler (pthis, &ev, pthis->m_pEvData);
00311
00312 if (ev.pDownload != NULL &&
00313 (ev.enType == BTSET_TRACKER || ev.enType == BTSET_TRACKER_REPLY || ev.enType == BTSET_TRACKER_WARNING))
00314 ((vmsBtDownloadImpl*)ev.pDownload)->OnTrackerAlert (ev.pszMsg);
00315 }
00316
00317 pthis->m_bThreadRunning = false;
00318 return 0;
00319 }
00320
00321 void vmsBtSessionImpl::set_EventsHandler (fntBtSessionEventsHandler pfn, LPVOID pData)
00322 {
00323 m_pfnEvHandler = pfn;
00324 m_pEvData = pData;
00325 }
00326
00327 int vmsBtSessionImpl::FindDownloadIndex (const torrent_handle &h)
00328 {
00329 for (size_t i = 0; i < m_vDownloads.size (); i++)
00330 {
00331 if (m_vDownloads [i]->m_handle == h)
00332 return i;
00333 }
00334
00335 return -1;
00336 }
00337
00338 void vmsBtSessionImpl::SetProxySettings (LPCSTR pszIp, int nPort, LPCSTR pszUser, LPCSTR pszPwd)
00339 {
00340 session_settings s = m_session.settings ();
00341 s.proxy_ip = pszIp ? pszIp : "";
00342 s.proxy_port = nPort;
00343 s.proxy_login = pszUser ? pszUser : "";
00344 s.proxy_password = pszPwd ? pszPwd : "";
00345 m_session.set_settings (s);
00346 }
00347
00348 void vmsBtSessionImpl::RestoreDownloadHandle (vmsBtDownloadImpl* dld)
00349 {
00350 EnterCriticalSection (&m_csRestoreTorrentHandle);
00351
00352 if (dld->m_handle.is_valid ())
00353 {
00354 LeaveCriticalSection (&m_csRestoreTorrentHandle);
00355 return;
00356 }
00357
00358 try {
00359 dld->m_handle = m_session.add_torrent (*dld->m_pTorrent->m_torrent, dld->m_strOutputPath);
00360 dld->m_handle.pause ();
00361 }
00362 catch (...) {
00363 LeaveCriticalSection (&m_csRestoreTorrentHandle);
00364 return;
00365 }
00366
00367 LeaveCriticalSection (&m_csRestoreTorrentHandle);
00368
00369 if (m_pfnEvHandler)
00370 {
00371 vmsBtSessionEvent ev;
00372 ev.enType = BTSET_BTDLD_WAS_RESET;
00373 ev.pDownload = dld;
00374 ev.pszMsg = NULL;
00375 m_pfnEvHandler (this, &ev, m_pEvData);
00376 }
00377 }
00378
00379 int vmsBtSessionImpl::get_TotalDownloadConnectionCount ()
00380 {
00381 int n = 0;
00382 for (size_t i = 0; i < m_vDownloads.size (); i++)
00383 n += m_vDownloads [i]->get_DownloadConnectionCount ();
00384 return n;
00385 }
00386
00387 int vmsBtSessionImpl::get_DownloadCount ()
00388 {
00389 return m_vDownloads.size ();
00390 }
00391
00392 vmsBtDownload* vmsBtSessionImpl::get_Download (int nIndex)
00393 {
00394 return m_vDownloads [nIndex];
00395 }
00396
00397 int vmsBtSessionImpl::get_TotalDownloadSpeed ()
00398 {
00399 return (int)m_session.status ().payload_download_rate;
00400 }
00401
00402 int vmsBtSessionImpl::get_TotalUploadSpeed ()
00403 {
00404 return (int)m_session.status ().payload_upload_rate;
00405 }
00406
00407 UINT64 vmsBtSessionImpl::get_TotalDownloadedByteCount ()
00408 {
00409 return m_session.status ().total_payload_download;
00410 }
00411
00412 UINT64 vmsBtSessionImpl::get_TotalUploadedByteCount ()
00413 {
00414 return m_session.status ().total_payload_upload;
00415 }
00416
00417 void vmsBtSessionImpl::SetUserAgent (LPCSTR pszUA)
00418 {
00419 session_settings s = m_session.settings ();
00420 s.user_agent = pszUA;
00421 m_session.set_settings (s);
00422 }