Changeset 32b095e


Ignore:
Timestamp:
Jan 10, 2014 9:11:55 PM (6 years ago)
Author:
str4d <str4d@…>
Branches:
master
Children:
4308ce6
Parents:
eb4bdfc
Message:

BOB: Implement ClientApp? interface (ticket #347)

Files:
3 edited

Legend:

Unmodified
Added
Removed
  • apps/BOB/src/net/i2p/BOB/BOB.java

    reb4bdfc r32b095e  
    1616package net.i2p.BOB;
    1717
     18import static net.i2p.app.ClientAppState.*;
     19
    1820import java.io.File;
    1921import java.io.FileInputStream;
     
    2628import java.net.Socket;
    2729import java.net.SocketTimeoutException;
     30import java.util.Arrays;
    2831import java.util.Properties;
    2932import java.util.concurrent.atomic.AtomicBoolean;
    3033
    3134import net.i2p.I2PAppContext;
     35import net.i2p.app.*;
    3236import net.i2p.client.I2PClient;
     37import net.i2p.util.I2PAppThread;
    3338import net.i2p.util.Log;
    3439import net.i2p.util.SimpleScheduler;
     
    106111 * @author sponge
    107112 */
    108 public class BOB {
     113public class BOB implements Runnable, ClientApp {
    109114
    110115        public final static String PROP_CONFIG_LOCATION = "BOB.config";
     
    112117        public final static String PROP_BOB_HOST = "BOB.host";
    113118        public final static String PROP_CFG_VER = "BOB.CFG.VER";
    114         private static NamedDB database;
    115         private static Properties props = new Properties();
    116         private static AtomicBoolean spin = new AtomicBoolean(true);
     119
     120        private static BOB _bob;
     121
     122        private NamedDB database;
     123        private Properties props = new Properties();
     124        private AtomicBoolean spin = new AtomicBoolean(true);
    117125        private static final String P_RUNNING = "RUNNING";
    118126        private static final String P_STARTING = "STARTING";
    119127        private static final String P_STOPPING = "STOPPING";
    120         private static AtomicBoolean lock = new AtomicBoolean(false);
     128        private AtomicBoolean lock = new AtomicBoolean(false);
    121129        // no longer used.
    122130        // private static int maxConnections = 0;
     131
     132        private final Log _log;
     133        private final ClientAppManager _mgr;
     134        private final String[] _args;
     135        private volatile ClientAppState _state = UNINITIALIZED;
     136
     137        private volatile ServerSocket listener;
     138        private volatile Thread _runner;
    123139
    124140        /**
     
    126142         *
    127143         * @param arg
     144         * @deprecated
    128145         */
    129146        public static void info(String arg) {
     
    136153         *
    137154         * @param arg
     155         * @deprecated
    138156         */
    139157        public static void warn(String arg) {
     
    146164         *
    147165         * @param arg
     166         * @deprecated
    148167         */
    149168        public static void error(String arg) {
     
    154173        /**
    155174         * Stop BOB gracefully
     175         * @deprecated unused
    156176         */
    157177        public static void stop() {
    158                 spin.set(false);
     178                _bob.shutdown(null);
     179        }
     180
     181        /**
     182         *  For ClientApp interface.
     183         *  Does NOT open the listener socket or start threads; caller must call startup()
     184         *
     185         *  @param mgr may be null
     186         *  @param args non-null
     187         *  @throws Exception on bad args
     188         *  @since 0.9.10
     189         */
     190        public BOB(I2PAppContext context, ClientAppManager mgr, String[] args) {
     191                _log = context.logManager().getLog(BOB.class);
     192                _mgr = mgr;
     193                _args = args;
     194                _state = INITIALIZED;
     195                database = new NamedDB();
     196                loadConfig();
    159197        }
    160198
     
    165203         */
    166204        public static void main(String[] args) {
    167                 database = new NamedDB();
    168                 ServerSocket listener = null;
     205                try {
     206                        _bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
     207                        _bob.startup();
     208                } catch (RuntimeException e) {
     209                        e.printStackTrace();
     210                        throw e;
     211                } catch (Exception e) {
     212                        e.printStackTrace();
     213                        throw new RuntimeException(e);
     214                }
     215        }
     216
     217        /**
     218         * @since 0.9.10
     219         */
     220        private void loadConfig() {
    169221                int i = 0;
    170222                boolean save = false;
     
    177229                i = Y1.hashCode();
    178230                i = Y2.hashCode();
    179                 Log _log = new Log(BOB.class);
     231                {
     232                        File cfg = new File(configLocation);
     233                        if (!cfg.isAbsolute()) {
     234                                cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
     235                        }
     236                        try {
     237                                FileInputStream fi = new FileInputStream(cfg);
     238                                props.load(fi);
     239                                fi.close();
     240                        } catch (FileNotFoundException fnfe) {
     241                                if (_log.shouldLog(Log.WARN))
     242                                        _log.warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.", fnfe);
     243                                save = true;
     244                        } catch (IOException ioe) {
     245                                if (_log.shouldLog(Log.WARN))
     246                                        _log.warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.", ioe);
     247                        }
     248                }
     249                // Global router and client API configurations that are missing are set to defaults here.
     250                if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
     251                        props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
     252                        save = true;
     253                }
     254                if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
     255                        props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
     256                        save = true;
     257                }
     258                if (!props.containsKey(PROP_BOB_PORT)) {
     259                        props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
     260                        save = true;
     261                }
     262                if (!props.containsKey("inbound.length")) {
     263                        props.setProperty("inbound.length", "1");
     264                        save = true;
     265                }
     266                if (!props.containsKey("outbound.length")) {
     267                        props.setProperty("outbound.length", "1");
     268                        save = true;
     269                }
     270                if (!props.containsKey("inbound.lengthVariance")) {
     271                        props.setProperty("inbound.lengthVariance", "0");
     272                        save = true;
     273                }
     274                if (!props.containsKey("outbound.lengthVariance")) {
     275                        props.setProperty("outbound.lengthVariance", "0");
     276                        save = true;
     277                }
     278                if (!props.containsKey(PROP_BOB_HOST)) {
     279                        props.setProperty(PROP_BOB_HOST, "localhost");
     280                        save = true;
     281                }
     282                // PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
     283                if (!props.containsKey(PROP_CFG_VER)) {
     284                        props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
     285                        props.setProperty(PROP_CFG_VER,"1");
     286                        save = true;
     287                }
     288                if (save) {
     289                        File cfg = new File(configLocation);
     290                        if (!cfg.isAbsolute()) {
     291                                cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
     292                        }
     293                        try {
     294                                if (_log.shouldLog(Log.WARN))
     295                                        _log.warn("Writing new defaults file " + cfg.getAbsolutePath());
     296                                FileOutputStream fo = new FileOutputStream(cfg);
     297                                props.store(fo, cfg.getAbsolutePath());
     298                                fo.close();
     299                        } catch (IOException ioe) {
     300                                if (_log.shouldLog(Log.ERROR))
     301                                        _log.error("IOException on BOB config file " + cfg.getAbsolutePath(), ioe);
     302                        }
     303                }
     304        }
     305
     306        /**
     307         * @since 0.9.10
     308         */
     309        private void startListener() throws IOException {
     310                listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
     311                listener.setSoTimeout(500); // .5 sec
     312        }
     313
     314        /**
     315         * @since 0.9.10
     316         */
     317        private void startThread() {
     318                I2PAppThread t = new I2PAppThread(this, "BOBListener");
     319                t.start();
     320                _runner = t;
     321        }
     322
     323        /**
     324         * @since 0.9.10
     325         */
     326        public void run() {
     327                if (listener == null) return;
     328                changeState(RUNNING);
     329                if (_log.shouldLog(Log.INFO))
     330                        _log.info("BOB is now running.");
     331                if (_mgr != null)
     332                        _mgr.register(this);
     333
     334                int i = 0;
     335                boolean g = false;
     336                spin.set(true);
    180337                try {
    181                         {
    182                                 File cfg = new File(configLocation);
    183                                 if (!cfg.isAbsolute()) {
    184                                         cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
     338                        Socket server = null;
     339
     340                        while (spin.get()) {
     341                                //DoCMDS connection;
     342
     343                                try {
     344                                        server = listener.accept();
     345                                        server.setKeepAlive(true);
     346                                        g = true;
     347                                } catch (ConnectException ce) {
     348                                        g = false;
     349                                } catch (SocketTimeoutException ste) {
     350                                        g = false;
    185351                                }
    186                                 try {
    187                                         FileInputStream fi = new FileInputStream(cfg);
    188                                         props.load(fi);
    189                                         fi.close();
    190                                 } catch (FileNotFoundException fnfe) {
    191                                         warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.");
    192                                         warn(fnfe.toString());
    193                                         save = true;
    194                                 } catch (IOException ioe) {
    195                                         warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.");
    196                                         warn(ioe.toString());
     352
     353                                if (g) {
     354                                        DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
     355                                        Thread t = new Thread(conn_c);
     356                                        t.setName("BOB.DoCMDS " + i);
     357                                        t.start();
     358                                        i++;
    197359                                }
    198360                        }
    199                         // Global router and client API configurations that are missing are set to defaults here.
    200                         if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
    201                                 props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
    202                                 save = true;
    203                         }
    204                         if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
    205                                 props.setProperty(I2PClient.PROP_TCP_PORT, "7654");
    206                                 save = true;
    207                         }
    208                         if (!props.containsKey(PROP_BOB_PORT)) {
    209                                 props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
    210                                 save = true;
    211                         }
    212                         if (!props.containsKey("inbound.length")) {
    213                                 props.setProperty("inbound.length", "1");
    214                                 save = true;
    215                         }
    216                         if (!props.containsKey("outbound.length")) {
    217                                 props.setProperty("outbound.length", "1");
    218                                 save = true;
    219                         }
    220                         if (!props.containsKey("inbound.lengthVariance")) {
    221                                 props.setProperty("inbound.lengthVariance", "0");
    222                                 save = true;
    223                         }
    224                         if (!props.containsKey("outbound.lengthVariance")) {
    225                                 props.setProperty("outbound.lengthVariance", "0");
    226                                 save = true;
    227                         }
    228                         if (!props.containsKey(PROP_BOB_HOST)) {
    229                                 props.setProperty(PROP_BOB_HOST, "localhost");
    230                                 save = true;
    231                         }
    232                         // PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
    233                         if (!props.containsKey(PROP_CFG_VER)) {
    234                                 props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
    235                                 props.setProperty(PROP_CFG_VER,"1");
    236                                 save = true;
    237                         }
    238                         if (save) {
    239                                 File cfg = new File(configLocation);
    240                                 if (!cfg.isAbsolute()) {
    241                                         cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
    242                                 }
    243                                 try {
    244                                         warn("Writing new defaults file " + cfg.getAbsolutePath());
    245                                         FileOutputStream fo = new FileOutputStream(cfg);
    246                                         props.store(fo, cfg.getAbsolutePath());
    247                                         fo.close();
    248                                 } catch (IOException ioe) {
    249                                         error("IOException on BOB config file " + cfg.getAbsolutePath() + ", " + ioe);
    250                                 }
    251                         }
    252 
    253                         i = 0;
    254                         boolean g = false;
    255                         spin.set(true);
    256                         try {
    257                                 info("BOB is now running.");
    258                                 listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
    259                                 Socket server = null;
    260                                 listener.setSoTimeout(500); // .5 sec
    261                                
    262                                 while (spin.get()) {
    263                                         //DoCMDS connection;
    264 
    265                                         try {
    266                                                 server = listener.accept();
    267                                                 server.setKeepAlive(true);
    268                                                 g = true;
    269                                         } catch (ConnectException ce) {
    270                                                 g = false;
    271                                         } catch (SocketTimeoutException ste) {
    272                                                 g = false;
    273                                         }
    274 
    275                                         if (g) {
    276                                                 DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
    277                                                 Thread t = new Thread(conn_c);
    278                                                 t.setName("BOB.DoCMDS " + i);
    279                                                 t.start();
    280                                                 i++;
    281                                         }
    282                                 }
    283                         } catch (IOException ioe) {
    284                                 error("IOException on socket listen: " + ioe);
    285                                 ioe.printStackTrace();
    286                         }
     361                        changeState(STOPPING);
     362                } catch (Exception e) {
     363                        if (spin.get() && _log.shouldLog(Log.ERROR))
     364                                _log.error("Unexpected error while listening for connections", e);
     365                        else
     366                                e = null;
     367                        changeState(STOPPING, e);
    287368                } finally {
    288                         info("BOB is now shutting down...");
     369                        if (_log.shouldLog(Log.INFO))
     370                                _log.info("BOB is now shutting down...");
    289371                        // Clean up everything.
    290372                        try {
     
    317399                                }
    318400                        }
    319                         info("BOB is now stopped.");
    320 
     401                        changeState(STOPPED);
     402                        if (_log.shouldLog(Log.INFO))
     403                                _log.info("BOB is now stopped.");
    321404                }
    322405        }
     
    370453                }
    371454        }
     455
     456        ////// begin ClientApp interface
     457
     458        /**
     459         * @since 0.9.10
     460         */
     461        @Override
     462        public void startup() throws IOException {
     463                if (_state != INITIALIZED)
     464                        return;
     465                changeState(STARTING);
     466                try {
     467                        startListener();
     468                } catch (IOException e) {
     469                        if (_log.shouldLog(Log.ERROR))
     470                                _log.error("Error starting BOB on"
     471                                                + props.getProperty(PROP_BOB_HOST)
     472                                                + ":" + props.getProperty(PROP_BOB_PORT), e);
     473                        changeState(START_FAILED, e);
     474                        throw e;
     475                }
     476                startThread();
     477        }
     478
     479        /**
     480         * @since 0.9.10
     481         */
     482        @Override
     483        public void shutdown(String[] args) {
     484                if (_state != RUNNING)
     485                        return;
     486                changeState(STOPPING);
     487                spin.set(false);
     488                if (_runner != null)
     489                        _runner.interrupt();
     490                else
     491                        changeState(STOPPED);
     492        }
     493
     494        /**
     495         * @since 0.9.10
     496         */
     497        @Override
     498        public ClientAppState getState() {
     499                return _state;
     500        }
     501
     502        /**
     503         * @since 0.9.10
     504         */
     505        @Override
     506        public String getName() {
     507                return "BOB";
     508        }
     509
     510        /**
     511         * @since 0.9.10
     512         */
     513        @Override
     514        public String getDisplayName() {
     515                return "BOB " + Arrays.toString(_args);
     516        }
     517
     518        ////// end ClientApp interface
     519        ////// begin ClientApp helpers
     520
     521        /**
     522         *  @since 0.9.10
     523         */
     524        private void changeState(ClientAppState state) {
     525                changeState(state, null);
     526        }
     527
     528        /**
     529         *  @since 0.9.10
     530         */
     531        private synchronized void changeState(ClientAppState state, Exception e) {
     532                _state = state;
     533                if (_mgr != null)
     534                        _mgr.notify(this, state, null, e);
     535        }
     536
     537        ////// end ClientApp helpers
    372538}
  • history.txt

    reb4bdfc r32b095e  
     12014-01-10 str4d
     2 * BOB: Implement ClientApp interface (ticket #347)
     3
    142014-01-09
    25 * Translations
  • router/java/src/net/i2p/router/RouterVersion.java

    reb4bdfc r32b095e  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 5;
     21    public final static long BUILD = 6;
    2222
    2323    /** for example "-test" */
Note: See TracChangeset for help on using the changeset viewer.