PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NzbDrone.Core/Download/Clients/rTorrent/RTorrentProxy.cs

https://github.com/NzbDrone/NzbDrone
C# | 296 lines | 242 code | 54 blank | 0 comment | 21 complexity | d6b658d85c7e3576c3b3610434e8c2f9 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Runtime.InteropServices.ComTypes;
  7. using NLog;
  8. using NzbDrone.Common.Extensions;
  9. using CookComputing.XmlRpc;
  10. namespace NzbDrone.Core.Download.Clients.RTorrent
  11. {
  12. public interface IRTorrentProxy
  13. {
  14. string GetVersion(RTorrentSettings settings);
  15. List<RTorrentTorrent> GetTorrents(RTorrentSettings settings);
  16. void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
  17. void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings);
  18. void RemoveTorrent(string hash, RTorrentSettings settings);
  19. void SetTorrentLabel(string hash, string label, RTorrentSettings settings);
  20. bool HasHashTorrent(string hash, RTorrentSettings settings);
  21. void PushTorrentUniqueView(string hash, string view, RTorrentSettings settings);
  22. }
  23. public interface IRTorrent : IXmlRpcProxy
  24. {
  25. [XmlRpcMethod("d.multicall2")]
  26. object[] TorrentMulticall(params string[] parameters);
  27. [XmlRpcMethod("load.normal")]
  28. int LoadNormal(string target, string data, params string[] commands);
  29. [XmlRpcMethod("load.start")]
  30. int LoadStart(string target, string data, params string[] commands);
  31. [XmlRpcMethod("load.raw")]
  32. int LoadRaw(string target, byte[] data, params string[] commands);
  33. [XmlRpcMethod("load.raw_start")]
  34. int LoadRawStart(string target, byte[] data, params string[] commands);
  35. [XmlRpcMethod("d.erase")]
  36. int Remove(string hash);
  37. [XmlRpcMethod("d.name")]
  38. string GetName(string hash);
  39. [XmlRpcMethod("d.custom1.set")]
  40. string SetLabel(string hash, string label);
  41. [XmlRpcMethod("d.views.push_back_unique")]
  42. int PushUniqueView(string hash, string view);
  43. [XmlRpcMethod("system.client_version")]
  44. string GetVersion();
  45. }
  46. public class RTorrentProxy : IRTorrentProxy
  47. {
  48. private readonly Logger _logger;
  49. public RTorrentProxy(Logger logger)
  50. {
  51. _logger = logger;
  52. }
  53. public string GetVersion(RTorrentSettings settings)
  54. {
  55. _logger.Debug("Executing remote method: system.client_version");
  56. var client = BuildClient(settings);
  57. var version = ExecuteRequest(() => client.GetVersion());
  58. return version;
  59. }
  60. public List<RTorrentTorrent> GetTorrents(RTorrentSettings settings)
  61. {
  62. _logger.Debug("Executing remote method: d.multicall2");
  63. var client = BuildClient(settings);
  64. var ret = ExecuteRequest(() => client.TorrentMulticall("", "",
  65. "d.name=", // string
  66. "d.hash=", // string
  67. "d.base_path=", // string
  68. "d.custom1=", // string (label)
  69. "d.size_bytes=", // long
  70. "d.left_bytes=", // long
  71. "d.down.rate=", // long (in bytes / s)
  72. "d.ratio=", // long
  73. "d.is_open=", // long
  74. "d.is_active=", // long
  75. "d.complete=", // long
  76. "d.timestamp.finished=") // long (unix timestamp)
  77. );
  78. var items = new List<RTorrentTorrent>();
  79. foreach (object[] torrent in ret)
  80. {
  81. var labelDecoded = System.Web.HttpUtility.UrlDecode((string)torrent[3]);
  82. var item = new RTorrentTorrent();
  83. item.Name = (string)torrent[0];
  84. item.Hash = (string)torrent[1];
  85. item.Path = (string)torrent[2];
  86. item.Category = labelDecoded;
  87. item.TotalSize = (long)torrent[4];
  88. item.RemainingSize = (long)torrent[5];
  89. item.DownRate = (long)torrent[6];
  90. item.Ratio = (long)torrent[7];
  91. item.IsOpen = Convert.ToBoolean((long)torrent[8]);
  92. item.IsActive = Convert.ToBoolean((long)torrent[9]);
  93. item.IsFinished = Convert.ToBoolean((long)torrent[10]);
  94. item.FinishedTime = (long)torrent[11];
  95. items.Add(item);
  96. }
  97. return items;
  98. }
  99. public void AddTorrentFromUrl(string torrentUrl, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
  100. {
  101. var client = BuildClient(settings);
  102. var response = ExecuteRequest(() =>
  103. {
  104. if (settings.AddStopped)
  105. {
  106. _logger.Debug("Executing remote method: load.normal");
  107. return client.LoadNormal("", torrentUrl, GetCommands(label, priority, directory));
  108. }
  109. else
  110. {
  111. _logger.Debug("Executing remote method: load.start");
  112. return client.LoadStart("", torrentUrl, GetCommands(label, priority, directory));
  113. }
  114. });
  115. if (response != 0)
  116. {
  117. throw new DownloadClientException("Could not add torrent: {0}.", torrentUrl);
  118. }
  119. }
  120. public void AddTorrentFromFile(string fileName, byte[] fileContent, string label, RTorrentPriority priority, string directory, RTorrentSettings settings)
  121. {
  122. var client = BuildClient(settings);
  123. var response = ExecuteRequest(() =>
  124. {
  125. if (settings.AddStopped)
  126. {
  127. _logger.Debug("Executing remote method: load.raw");
  128. return client.LoadRaw("", fileContent, GetCommands(label, priority, directory));
  129. }
  130. else
  131. {
  132. _logger.Debug("Executing remote method: load.raw_start");
  133. return client.LoadRawStart("", fileContent, GetCommands(label, priority, directory));
  134. }
  135. });
  136. if (response != 0)
  137. {
  138. throw new DownloadClientException("Could not add torrent: {0}.", fileName);
  139. }
  140. }
  141. public void SetTorrentLabel(string hash, string label, RTorrentSettings settings)
  142. {
  143. _logger.Debug("Executing remote method: d.custom1.set");
  144. var client = BuildClient(settings);
  145. var response = ExecuteRequest(() => client.SetLabel(hash, label));
  146. if (response != label)
  147. {
  148. throw new DownloadClientException("Could not set label to {1} for torrent: {0}.", hash, label);
  149. }
  150. }
  151. public void PushTorrentUniqueView(string hash, string view, RTorrentSettings settings)
  152. {
  153. _logger.Debug("Executing remote method: d.views.push_back_unique");
  154. var client = BuildClient(settings);
  155. var response = ExecuteRequest(() => client.PushUniqueView(hash, view));
  156. if (response != 0)
  157. {
  158. throw new DownloadClientException("Could not push unique view {0} for torrent: {1}.", view, hash);
  159. }
  160. }
  161. public void RemoveTorrent(string hash, RTorrentSettings settings)
  162. {
  163. _logger.Debug("Executing remote method: d.erase");
  164. var client = BuildClient(settings);
  165. var response = ExecuteRequest(() => client.Remove(hash));
  166. if (response != 0)
  167. {
  168. throw new DownloadClientException("Could not remove torrent: {0}.", hash);
  169. }
  170. }
  171. public bool HasHashTorrent(string hash, RTorrentSettings settings)
  172. {
  173. _logger.Debug("Executing remote method: d.name");
  174. var client = BuildClient(settings);
  175. try
  176. {
  177. var name = ExecuteRequest(() => client.GetName(hash));
  178. if (name.IsNullOrWhiteSpace())
  179. {
  180. return false;
  181. }
  182. var metaTorrent = name == (hash + ".meta");
  183. return !metaTorrent;
  184. }
  185. catch (Exception)
  186. {
  187. return false;
  188. }
  189. }
  190. private string[] GetCommands(string label, RTorrentPriority priority, string directory)
  191. {
  192. var result = new List<string>();
  193. if (label.IsNotNullOrWhiteSpace())
  194. {
  195. result.Add("d.custom1.set=" + label);
  196. }
  197. if (priority != RTorrentPriority.Normal)
  198. {
  199. result.Add("d.priority.set=" + (int)priority);
  200. }
  201. if (directory.IsNotNullOrWhiteSpace())
  202. {
  203. result.Add("d.directory.set=" + directory);
  204. }
  205. return result.ToArray();
  206. }
  207. private IRTorrent BuildClient(RTorrentSettings settings)
  208. {
  209. var client = XmlRpcProxyGen.Create<IRTorrent>();
  210. client.Url = string.Format(@"{0}://{1}:{2}/{3}",
  211. settings.UseSsl ? "https" : "http",
  212. settings.Host,
  213. settings.Port,
  214. settings.UrlBase);
  215. client.EnableCompression = true;
  216. if (!settings.Username.IsNullOrWhiteSpace())
  217. {
  218. client.Credentials = new NetworkCredential(settings.Username, settings.Password);
  219. }
  220. return client;
  221. }
  222. private T ExecuteRequest<T>(Func<T> task)
  223. {
  224. try
  225. {
  226. return task();
  227. }
  228. catch (XmlRpcServerException ex)
  229. {
  230. throw new DownloadClientException("Unable to connect to rTorrent, please check your settings", ex);
  231. }
  232. catch (WebException ex)
  233. {
  234. if (ex.Status == WebExceptionStatus.TrustFailure)
  235. {
  236. throw new DownloadClientUnavailableException("Unable to connect to rTorrent, certificate validation failed.", ex);
  237. }
  238. throw new DownloadClientUnavailableException("Unable to connect to rTorrent, please check your settings", ex);
  239. }
  240. }
  241. }
  242. }