1 /* 2 * File : TRTrackerServerFactoryImpl.java 3 * Created : 13-Dec-2003 4 * By : parg 5 * 6 * Azureus - a Java Bittorrent client 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details ( see the LICENSE file ). 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 package org.gudy.azureus2.core3.tracker.server.impl; 24 25 /** 26 * @author parg 27 * 28 */ 29 30 import java.io.ByteArrayOutputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.net.InetAddress; 34 import java.net.InetSocketAddress; 35 import java.nio.channels.SocketChannel; 36 import java.util.*; 37 38 import org.gudy.azureus2.core3.config.COConfigurationManager; 39 import org.gudy.azureus2.core3.tracker.server.*; 40 import org.gudy.azureus2.core3.tracker.server.impl.dht.TRTrackerServerDHT; 41 import org.gudy.azureus2.core3.tracker.server.impl.tcp.TRTrackerServerTCP; 42 import org.gudy.azureus2.core3.tracker.server.impl.tcp.blocking.TRBlockingServer; 43 import org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking.TRNonBlockingServer; 44 import org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking.TRNonBlockingServerProcessor; 45 import org.gudy.azureus2.core3.tracker.server.impl.tcp.nonblocking.TRNonBlockingServerProcessorFactory; 46 import org.gudy.azureus2.core3.tracker.server.impl.udp.*; 47 import org.gudy.azureus2.core3.util.AEMonitor; 48 import org.gudy.azureus2.core3.util.AsyncController; 49 import org.gudy.azureus2.plugins.tracker.Tracker; 50 51 import com.aelitis.azureus.core.stats.AzureusCoreStats; 52 import com.aelitis.azureus.core.stats.AzureusCoreStatsProvider; 53 import com.aelitis.azureus.core.util.CopyOnWriteList; 54 55 public class 56 TRTrackerServerFactoryImpl 57 { 58 protected static CopyOnWriteList servers = new CopyOnWriteList(); 59 60 protected static List listeners = new ArrayList(); 61 protected static AEMonitor class_mon = new AEMonitor( "TRTrackerServerFactory" ); 62 63 static{ 64 Set types = new HashSet(); 65 66 types.add( AzureusCoreStats.ST_TRACKER_READ_BYTES ); 67 types.add( AzureusCoreStats.ST_TRACKER_WRITE_BYTES ); 68 types.add( AzureusCoreStats.ST_TRACKER_ANNOUNCE_COUNT ); 69 types.add( AzureusCoreStats.ST_TRACKER_ANNOUNCE_TIME ); 70 types.add( AzureusCoreStats.ST_TRACKER_SCRAPE_COUNT ); 71 types.add( AzureusCoreStats.ST_TRACKER_SCRAPE_TIME ); 72 AzureusCoreStats.registerProvider( types, new AzureusCoreStatsProvider() { public void updateStats( Set types, Map values ) { long read_bytes = 0; long write_bytes = 0; long announce_count = 0; long announce_time = 0; long scrape_count = 0; long scrape_time = 0; Iterator it = servers.iterator(); while( it.hasNext()){ TRTrackerServerStats stats = ((TRTrackerServer)it.next()).getStats(); read_bytes += stats.getBytesIn(); write_bytes += stats.getBytesOut(); announce_count += stats.getAnnounceCount(); announce_time += stats.getAnnounceTime(); scrape_count += stats.getScrapeCount(); scrape_time += stats.getScrapeTime(); } if ( types.contains( AzureusCoreStats.ST_TRACKER_READ_BYTES )){ values.put( AzureusCoreStats.ST_TRACKER_READ_BYTES, new Long( read_bytes )); } if ( types.contains( AzureusCoreStats.ST_TRACKER_WRITE_BYTES )){ values.put( AzureusCoreStats.ST_TRACKER_WRITE_BYTES, new Long( write_bytes )); } if ( types.contains( AzureusCoreStats.ST_TRACKER_ANNOUNCE_COUNT )){ values.put( AzureusCoreStats.ST_TRACKER_ANNOUNCE_COUNT, new Long( announce_count )); } if ( types.contains( AzureusCoreStats.ST_TRACKER_ANNOUNCE_TIME )){ values.put( AzureusCoreStats.ST_TRACKER_ANNOUNCE_TIME, new Long( announce_time )); } if ( types.contains( AzureusCoreStats.ST_TRACKER_SCRAPE_COUNT )){ values.put( AzureusCoreStats.ST_TRACKER_SCRAPE_COUNT, new Long( scrape_count )); } if ( types.contains( AzureusCoreStats.ST_TRACKER_SCRAPE_TIME )){ values.put( AzureusCoreStats.ST_TRACKER_SCRAPE_TIME, new Long( scrape_time )); } } })73 AzureusCoreStats.registerProvider( 74 types, 75 new AzureusCoreStatsProvider() 76 { 77 public void 78 updateStats( 79 Set types, 80 Map values ) 81 { 82 long read_bytes = 0; 83 long write_bytes = 0; 84 long announce_count = 0; 85 long announce_time = 0; 86 long scrape_count = 0; 87 long scrape_time = 0; 88 89 Iterator it = servers.iterator(); 90 91 while( it.hasNext()){ 92 93 TRTrackerServerStats stats = ((TRTrackerServer)it.next()).getStats(); 94 95 read_bytes += stats.getBytesIn(); 96 write_bytes += stats.getBytesOut(); 97 announce_count += stats.getAnnounceCount(); 98 announce_time += stats.getAnnounceTime(); 99 scrape_count += stats.getScrapeCount(); 100 scrape_time += stats.getScrapeTime(); 101 } 102 103 if ( types.contains( AzureusCoreStats.ST_TRACKER_READ_BYTES )){ 104 105 values.put( AzureusCoreStats.ST_TRACKER_READ_BYTES, new Long( read_bytes )); 106 } 107 if ( types.contains( AzureusCoreStats.ST_TRACKER_WRITE_BYTES )){ 108 109 values.put( AzureusCoreStats.ST_TRACKER_WRITE_BYTES, new Long( write_bytes )); 110 } 111 if ( types.contains( AzureusCoreStats.ST_TRACKER_ANNOUNCE_COUNT )){ 112 113 values.put( AzureusCoreStats.ST_TRACKER_ANNOUNCE_COUNT, new Long( announce_count )); 114 } 115 if ( types.contains( AzureusCoreStats.ST_TRACKER_ANNOUNCE_TIME )){ 116 117 values.put( AzureusCoreStats.ST_TRACKER_ANNOUNCE_TIME, new Long( announce_time )); 118 } 119 if ( types.contains( AzureusCoreStats.ST_TRACKER_SCRAPE_COUNT )){ 120 121 values.put( AzureusCoreStats.ST_TRACKER_SCRAPE_COUNT, new Long( scrape_count )); 122 } 123 if ( types.contains( AzureusCoreStats.ST_TRACKER_SCRAPE_TIME )){ 124 125 values.put( AzureusCoreStats.ST_TRACKER_SCRAPE_TIME, new Long( scrape_time )); 126 } 127 } 128 }); 129 } 130 131 public static TRTrackerServer create( String name, int protocol, int port, InetAddress bind_ip, boolean ssl, boolean apply_ip_filter, boolean main_tracker, boolean start_up_ready, Map<String,Object> properties )132 create( 133 String name, 134 int protocol, 135 int port, 136 InetAddress bind_ip, 137 boolean ssl, 138 boolean apply_ip_filter, 139 boolean main_tracker, 140 boolean start_up_ready, 141 Map<String,Object> properties ) 142 143 throws TRTrackerServerException 144 { 145 if ( properties == null ){ 146 147 properties = new HashMap<String, Object>(); 148 } 149 150 Boolean pr_non_blocking = (Boolean)properties.get(Tracker.PR_NON_BLOCKING ); 151 152 try{ 153 class_mon.enter(); 154 155 TRTrackerServerImpl server; 156 157 if ( protocol == TRTrackerServerFactory.PR_TCP ){ 158 159 boolean explicit_non_blocking = pr_non_blocking != null && pr_non_blocking; 160 161 boolean non_blocking = 162 ( COConfigurationManager.getBooleanParameter( "Tracker TCP NonBlocking" ) && main_tracker ) || 163 ( explicit_non_blocking ); 164 165 if ( non_blocking && !ssl ){ 166 167 TRNonBlockingServer nb_server = 168 new TRNonBlockingServer( 169 name, 170 port, 171 bind_ip, 172 apply_ip_filter, 173 start_up_ready, 174 new TRNonBlockingServerProcessorFactory() 175 { 176 public TRNonBlockingServerProcessor 177 create( 178 TRTrackerServerTCP _server, 179 SocketChannel _socket ) 180 { 181 return( new NonBlockingProcessor( _server, _socket )); 182 183 } 184 }); 185 186 server = nb_server; 187 188 if ( explicit_non_blocking ){ 189 190 nb_server.setRestrictNonBlocking( false ); 191 } 192 }else{ 193 194 server = new TRBlockingServer( name, port, bind_ip, ssl, apply_ip_filter, start_up_ready ); 195 } 196 197 }else if ( protocol == TRTrackerServerFactory.PR_UDP ){ 198 199 if ( ssl ){ 200 201 throw( new TRTrackerServerException( "TRTrackerServerFactory: UDP doesn't support SSL")); 202 } 203 204 server = new TRTrackerServerUDP( name, port, start_up_ready ); 205 206 }else{ 207 208 server = new TRTrackerServerDHT( name, start_up_ready ); 209 } 210 211 servers.add( server ); 212 213 for (int i=0;i<listeners.size();i++){ 214 215 ((TRTrackerServerFactoryListener)listeners.get(i)).serverCreated( server ); 216 } 217 218 return( server ); 219 220 }finally{ 221 222 class_mon.exit(); 223 } 224 } 225 226 protected static void close( TRTrackerServerImpl server )227 close( 228 TRTrackerServerImpl server ) 229 { 230 try{ 231 class_mon.enter(); 232 233 server.closeSupport(); 234 235 if ( servers.remove( server )){ 236 237 for (int i=0;i<listeners.size();i++){ 238 239 ((TRTrackerServerFactoryListener)listeners.get(i)).serverDestroyed( server ); 240 } 241 } 242 }finally{ 243 244 class_mon.exit(); 245 } 246 } 247 248 public static void addListener( TRTrackerServerFactoryListener l )249 addListener( 250 TRTrackerServerFactoryListener l ) 251 { 252 try{ 253 class_mon.enter(); 254 255 listeners.add( l ); 256 257 Iterator it = servers.iterator(); 258 259 while( it.hasNext()){ 260 261 l.serverCreated((TRTrackerServer)it.next()); 262 } 263 }finally{ 264 265 class_mon.exit(); 266 } 267 } 268 269 public static void removeListener( TRTrackerServerFactoryListener l )270 removeListener( 271 TRTrackerServerFactoryListener l ) 272 { 273 try{ 274 class_mon.enter(); 275 276 listeners.remove( l ); 277 278 }finally{ 279 280 class_mon.exit(); 281 } 282 } 283 284 protected static class 285 NonBlockingProcessor 286 extends TRNonBlockingServerProcessor 287 { 288 protected NonBlockingProcessor( TRTrackerServerTCP _server, SocketChannel _socket )289 NonBlockingProcessor( 290 TRTrackerServerTCP _server, 291 SocketChannel _socket ) 292 { 293 super( _server, _socket ); 294 } 295 296 protected ByteArrayOutputStream process( String input_header, String lowercase_input_header, String url_path, InetSocketAddress remote_address, boolean announce_and_scrape_only, InputStream is, AsyncController async )297 process( 298 String input_header, 299 String lowercase_input_header, 300 String url_path, 301 InetSocketAddress remote_address, 302 boolean announce_and_scrape_only, 303 InputStream is, 304 AsyncController async ) 305 306 throws IOException 307 { 308 ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); 309 310 InetSocketAddress local_address = null; // TODO 311 312 processRequest(input_header, lowercase_input_header, url_path, local_address, remote_address, announce_and_scrape_only, false, is, os, async ); 313 314 return( os ); 315 } 316 } 317 } 318