1/****************************************************************************** 2 * $Id: TrackerNode.m 13251 2012-03-13 02:52:11Z livings124 $ 3 * 4 * Copyright (c) 2009-2012 Transmission authors and contributors 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 *****************************************************************************/ 24 25#import "TrackerNode.h" 26#import "NSStringAdditions.h" 27 28@implementation TrackerNode 29 30#warning remove ivars in header when 64-bit only (or it compiles in 32-bit mode) 31@synthesize torrent = fTorrent; 32 33- (id) initWithTrackerStat: (tr_tracker_stat *) stat torrent: (Torrent *) torrent 34{ 35 if ((self = [super init])) 36 { 37 fStat = *stat; 38 fTorrent = torrent; //weak reference 39 } 40 41 return self; 42} 43 44- (NSString *) description 45{ 46 return [@"Tracker: " stringByAppendingString: [self fullAnnounceAddress]]; 47} 48 49- (id) copyWithZone: (NSZone *) zone 50{ 51 //this object is essentially immutable after initial setup 52 return [self retain]; 53} 54 55- (BOOL) isEqual: (id) object 56{ 57 if (self == object) 58 return YES; 59 60 if (![object isKindOfClass: [self class]]) 61 return NO; 62 63 if ([self torrent] != [object torrent]) 64 return NO; 65 66 return [self tier] == [object tier] && [[self fullAnnounceAddress] isEqualToString: [object fullAnnounceAddress]]; 67} 68 69- (NSString *) host 70{ 71 return [NSString stringWithUTF8String: fStat.host]; 72} 73 74- (NSString *) fullAnnounceAddress 75{ 76 return [NSString stringWithUTF8String: fStat.announce]; 77} 78 79- (NSInteger) tier 80{ 81 return fStat.tier; 82} 83 84- (NSUInteger) identifier 85{ 86 return fStat.id; 87} 88 89- (NSInteger) totalSeeders 90{ 91 return fStat.seederCount; 92} 93 94- (NSInteger) totalLeechers 95{ 96 return fStat.leecherCount; 97} 98 99- (NSInteger) totalDownloaded 100{ 101 return fStat.downloadCount; 102} 103 104- (NSString *) lastAnnounceStatusString 105{ 106 NSString * dateString; 107 if (fStat.hasAnnounced) 108 { 109 NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init]; 110 [dateFormatter setDateStyle: NSDateFormatterFullStyle]; 111 [dateFormatter setTimeStyle: NSDateFormatterShortStyle]; 112 [dateFormatter setDoesRelativeDateFormatting: YES]; 113 114 dateString = [dateFormatter stringFromDate: [NSDate dateWithTimeIntervalSince1970: fStat.lastAnnounceTime]]; 115 [dateFormatter release]; 116 } 117 else 118 dateString = NSLocalizedString(@"N/A", "Tracker last announce"); 119 120 NSString * baseString; 121 if (fStat.hasAnnounced && fStat.lastAnnounceTimedOut) 122 baseString = [NSLocalizedString(@"Announce timed out", "Tracker last announce") stringByAppendingFormat: @": %@", dateString]; 123 else if (fStat.hasAnnounced && !fStat.lastAnnounceSucceeded) 124 { 125 baseString = NSLocalizedString(@"Announce error", "Tracker last announce"); 126 127 NSString * errorString = [NSString stringWithUTF8String: fStat.lastAnnounceResult]; 128 if ([errorString isEqualToString: @""]) 129 baseString = [baseString stringByAppendingFormat: @": %@", dateString]; 130 else 131 baseString = [baseString stringByAppendingFormat: @": %@ - %@", errorString, dateString]; 132 } 133 else 134 { 135 baseString = [NSLocalizedString(@"Last Announce", "Tracker last announce") stringByAppendingFormat: @": %@", dateString]; 136 if (fStat.hasAnnounced && fStat.lastAnnounceSucceeded && fStat.lastAnnouncePeerCount > 0) 137 { 138 NSString * peerString; 139 if (fStat.lastAnnouncePeerCount == 1) 140 peerString = NSLocalizedString(@"got 1 peer", "Tracker last announce"); 141 else 142 peerString = [NSString stringWithFormat: NSLocalizedString(@"got %d peers", "Tracker last announce"), 143 fStat.lastAnnouncePeerCount]; 144 baseString = [baseString stringByAppendingFormat: @" (%@)", peerString]; 145 } 146 } 147 148 return baseString; 149} 150 151- (NSString *) nextAnnounceStatusString 152{ 153 switch (fStat.announceState) 154 { 155 case TR_TRACKER_ACTIVE: 156 return [NSLocalizedString(@"Announce in progress", "Tracker next announce") stringByAppendingEllipsis]; 157 158 case TR_TRACKER_WAITING: 159 return [NSString stringWithFormat: NSLocalizedString(@"Next announce in %@", "Tracker next announce"), 160 [NSString timeString: fStat.nextAnnounceTime - [[NSDate date] timeIntervalSince1970] showSeconds: YES]]; 161 162 case TR_TRACKER_QUEUED: 163 return [NSLocalizedString(@"Announce is queued", "Tracker next announce") stringByAppendingEllipsis]; 164 165 case TR_TRACKER_INACTIVE: 166 return fStat.isBackup ? NSLocalizedString(@"Tracker will be used as a backup", "Tracker next announce") 167 : NSLocalizedString(@"Announce not scheduled", "Tracker next announce"); 168 169 default: 170 NSAssert1(NO, @"unknown announce state: %d", fStat.announceState); 171 return nil; 172 } 173} 174 175- (NSString *) lastScrapeStatusString 176{ 177 NSString * dateString; 178 if (fStat.hasScraped) 179 { 180 NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init]; 181 [dateFormatter setDateStyle: NSDateFormatterFullStyle]; 182 [dateFormatter setTimeStyle: NSDateFormatterShortStyle]; 183 [dateFormatter setDoesRelativeDateFormatting: YES]; 184 185 dateString = [dateFormatter stringFromDate: [NSDate dateWithTimeIntervalSince1970: fStat.lastScrapeTime]]; 186 [dateFormatter release]; 187 } 188 else 189 dateString = NSLocalizedString(@"N/A", "Tracker last scrape"); 190 191 NSString * baseString; 192 if (fStat.hasScraped && fStat.lastScrapeTimedOut) 193 baseString = [NSLocalizedString(@"Scrape timed out", "Tracker last scrape") stringByAppendingFormat: @": %@", dateString]; 194 else if (fStat.hasScraped && !fStat.lastScrapeSucceeded) 195 { 196 baseString = NSLocalizedString(@"Scrape error", "Tracker last scrape"); 197 198 NSString * errorString = [NSString stringWithUTF8String: fStat.lastScrapeResult]; 199 if ([errorString isEqualToString: @""]) 200 baseString = [baseString stringByAppendingFormat: @": %@", dateString]; 201 else 202 baseString = [baseString stringByAppendingFormat: @": %@ - %@", errorString, dateString]; 203 } 204 else 205 baseString = [NSLocalizedString(@"Last Scrape", "Tracker last scrape") stringByAppendingFormat: @": %@", dateString]; 206 207 return baseString; 208} 209 210@end 211