Changeset 68c6179


Ignore:
Timestamp:
Feb 6, 2016 1:44:08 PM (4 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
ceb7791
Parents:
62ad799
Message:

SAM v3.3: Fixes after testing

  • Fix master acceptor
  • Clean up error message generation
  • Add basic master session test for SAMStreamSink
Location:
apps/sam/java/src/net/i2p/sam
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • apps/sam/java/src/net/i2p/sam/MasterSession.java

    r62ad799 r68c6179  
    1919import net.i2p.client.I2PSessionException;
    2020import net.i2p.client.I2PSessionMuxedListener;
     21import net.i2p.client.streaming.I2PServerSocket;
    2122import net.i2p.client.streaming.I2PSocket;
    2223import net.i2p.data.DataFormatException;
     
    328329
    329330                public void run() {
    330                         while (!stop && getSocketServer() != null) {
    331                                
     331                        if (_log.shouldWarn())
     332                                _log.warn("Stream acceptor started");
     333                        final I2PServerSocket i2pss = socketMgr.getServerSocket();
     334                        while (!stop) {
    332335                                // wait and accept a connection from I2P side
    333336                                I2PSocket i2ps;
    334337                                try {
    335                                         i2ps = getSocketServer().accept();
    336                                         if (i2ps == null)
     338                                        i2ps = i2pss.accept();
     339                                        if (i2ps == null)  // never null as of 0.9.17
    337340                                                continue;
    338341                                } catch (SocketTimeoutException ste) {
  • apps/sam/java/src/net/i2p/sam/SAMv1Handler.java

    r62ad799 r68c6179  
    5252    private static final AtomicLong __id = new AtomicLong();
    5353    private static final int FIRST_READ_TIMEOUT = 60*1000;
     54    protected static final String SESSION_ERROR = "SESSION STATUS RESULT=I2P_ERROR";
    5455   
    5556    /**
     
    133134                    sock.setSoTimeout(0);
    134135                } catch (SocketTimeoutException ste) {
    135                     writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"command timeout, bye\"\n");
     136                    writeString(SESSION_ERROR, "command timeout, bye");
    136137                    break;
    137138                }
     
    223224                    if (_log.shouldLog(Log.DEBUG))
    224225                        _log.debug("Trying to create a session, but one still exists");
    225                     return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n");
     226                    return writeString(SESSION_ERROR, "Session already exists");
    226227                }
    227228                if (props.isEmpty()) {
    228229                    if (_log.shouldLog(Log.DEBUG))
    229230                        _log.debug("No parameters specified in SESSION CREATE message");
    230                     return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n");
     231                    return writeString(SESSION_ERROR, "No parameters for SESSION CREATE");
    231232                }
    232233               
     
    235236                    if (_log.shouldLog(Log.DEBUG))
    236237                        _log.debug("SESSION DESTINATION parameter not specified");
    237                     return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n");
     238                    return writeString(SESSION_ERROR, "DESTINATION not specified");
    238239                }
    239240               
     
    265266                    if (_log.shouldLog(Log.DEBUG))
    266267                        _log.debug("SESSION STYLE parameter not specified");
    267                     return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n");
     268                    return writeString(SESSION_ERROR, "No SESSION STYLE specified");
    268269                }
    269270               
     
    289290                        if (_log.shouldLog(Log.DEBUG))
    290291                            _log.debug("Unknown DIRECTION parameter value: [" + dir + "]");
    291                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown DIRECTION parameter\"\n");
     292                        return writeString(SESSION_ERROR, "Unknown DIRECTION parameter");
    292293                    }
    293294               
     
    297298                    if (_log.shouldLog(Log.DEBUG))
    298299                        _log.debug("Unrecognized SESSION STYLE: \"" + style +"\"");
    299                     return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n");
     300                    return writeString(SESSION_ERROR, "Unrecognized SESSION STYLE");
    300301                }
    301302                return writeString("SESSION STATUS RESULT=OK DESTINATION="
     
    305306                    _log.debug("Unrecognized SESSION message opcode: \""
    306307                           + opcode + "\"");
    307                 return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n");
     308                return writeString(SESSION_ERROR, "Unrecognized opcode");
    308309            }
    309310        } catch (DataFormatException e) {
    310311            if (_log.shouldLog(Log.DEBUG))
    311312                _log.debug("Invalid destination specified");
    312             return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
     313            return writeString("SESSION STATUS RESULT=INVALID_KEY", e.getMessage());
    313314        } catch (I2PSessionException e) {
    314315            if (_log.shouldLog(Log.DEBUG))
    315316                _log.debug("I2P error when instantiating session", e);
    316             return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
     317            return writeString(SESSION_ERROR, e.getMessage());
    317318        } catch (SAMException e) {
    318319            _log.error("Unexpected SAM error", e);
    319             return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
     320            return writeString(SESSION_ERROR, e.getMessage());
    320321        } catch (IOException e) {
    321322            _log.error("Unexpected IOException", e);
    322             return writeString("SESSION STATUS RESULT=I2P_ERROR DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
     323            return writeString(SESSION_ERROR, e.getMessage());
    323324        }
    324325    }
     
    10131014        return rv;
    10141015    }
     1016
     1017    /**
     1018     * Write a string and message, escaping the message.
     1019     * Writes s + createMessageString(msg) + \n
     1020     *
     1021     * @param s The string, non-null
     1022     * @param s The message may be null
     1023     * @since 0.9.25
     1024     */
     1025    protected boolean writeString(String s, String msg) {
     1026        return writeString(s + createMessageString(msg) + '\n');
     1027    }
    10151028 
    10161029    public void receiveStreamBytes(int id, ByteBuffer data) throws IOException {
  • apps/sam/java/src/net/i2p/sam/SAMv3Handler.java

    r62ad799 r68c6179  
    5757        private static final int FIRST_READ_TIMEOUT = 60*1000;
    5858        private static final int READ_TIMEOUT = 3*60*1000;
     59        private static final String AUTH_ERROR = "AUTH STATUS RESULT=I2P_ERROR";
    5960       
    6061        /**
     
    197198                                                                        if (_log.shouldWarn())
    198199                                                                                _log.warn("Failed to respond to PING");
    199                                                                         writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"PONG timeout\"\n");
     200                                                                        writeString(SESSION_ERROR, "PONG timeout");
    200201                                                                        break;
    201202                                                                }
     
    212213                                                                        if (_log.shouldWarn())
    213214                                                                                _log.warn("Failed to respond to PING");
    214                                                                         writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"PONG timeout\"\n");
     215                                                                        writeString(SESSION_ERROR, "PONG timeout");
    215216                                                                        break;
    216217                                                                }
     
    218219                                                                if (_log.shouldWarn())
    219220                                                                        _log.warn("2nd timeout");
    220                                                                 writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"command timeout, bye\"\n");
     221                                                                writeString(SESSION_ERROR, "command timeout, bye");
    221222                                                                break;
    222223                                                        } else {
     
    239240                                                socket.setSoTimeout(0);
    240241                                        } catch (SocketTimeoutException ste) {
    241                                                 writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"command timeout, bye\"\n");
     242                                                writeString(SESSION_ERROR, "command timeout, bye");
    242243                                                break;
    243244                                        }
     
    276277                                if (opcode == null) {
    277278                                        // This is not a correct message, for sure
    278                                         if (writeString(domain + " STATUS RESULT=I2P_ERROR MESSAGE=\"command not specified\"\n"))
     279                                        if (writeString(domain + " STATUS RESULT=I2P_ERROR", "command not specified"))
    279280                                                continue;
    280281                                        else
     
    399400                String nick = (String) props.remove("ID");
    400401                if (nick == null)
    401                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"ID not specified\"\n");
     402                        return writeString(SESSION_ERROR, "ID not specified");
    402403
    403404                String style = (String) props.remove("STYLE");
    404405                if (style == null && !opcode.equals("REMOVE"))
    405                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No SESSION STYLE specified\"\n");
     406                        return writeString(SESSION_ERROR, "No SESSION STYLE specified");
    406407
    407408                try{
     
    411412                                        if (_log.shouldLog(Log.DEBUG))
    412413                                                _log.debug("Trying to create a session, but one still exists");
    413                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Session already exists\"\n");
     414                                        return writeString(SESSION_ERROR, "Session already exists");
    414415                                }
    415416                                if (props.isEmpty()) {
    416417                                        if (_log.shouldLog(Log.DEBUG))
    417418                                                _log.debug("No parameters specified in SESSION CREATE message");
    418                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"No parameters for SESSION CREATE\"\n");
     419                                        return writeString(SESSION_ERROR, "No parameters for SESSION CREATE");
    419420                                }
    420421
     
    423424                                        if (_log.shouldLog(Log.DEBUG))
    424425                                                _log.debug("SESSION DESTINATION parameter not specified");
    425                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"DESTINATION not specified\"\n");
     426                                        return writeString(SESSION_ERROR, "DESTINATION not specified");
    426427                                }
    427428
     
    434435                                                sigType = SigType.parseSigType(sigTypeStr);
    435436                                                if (sigType == null) {
    436                                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"SIGNATURE_TYPE "
    437                                                                            + sigTypeStr + " unsupported\"\n");
     437                                                        return writeString(SESSION_ERROR, "SIGNATURE_TYPE "
     438                                                                           + sigTypeStr + " unsupported");
    438439                                                }
    439440                                        } else {
     
    512513                                        if (_log.shouldLog(Log.DEBUG))
    513514                                                _log.debug("Unrecognized SESSION STYLE: \"" + style +"\"");
    514                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized SESSION STYLE\"\n");
     515                                        return writeString(SESSION_ERROR, "Unrecognized SESSION STYLE");
    515516                                }
    516517                                ok = true ;
     
    521522                                ok = true;
    522523                                if (streamSession == null || datagramSession == null || rawSession == null)
    523                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Not a MASTER session\"\n");
     524                                        return writeString(SESSION_ERROR, "Not a MASTER session");
    524525                                MasterSession msess = (MasterSession) session;
    525526                                String msg;
     
    530531                                }
    531532                                if (msg == null)
    532                                         return writeString("SESSION STATUS RESULT=OK MESSAGE=\"" + opcode + ' ' + nick + "\"\n");
     533                                        return writeString("SESSION STATUS RESULT=OK", opcode + ' ' + nick);
    533534                                else
    534                                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + msg + "\"\n");
     535                                        return writeString(SESSION_ERROR, msg);
    535536                        } else {
    536537                                if (_log.shouldLog(Log.DEBUG))
    537538                                        _log.debug("Unrecognized SESSION message opcode: \""
    538539                                                + opcode + "\"");
    539                                 return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"Unrecognized opcode\"\n");
     540                                return writeString(SESSION_ERROR, "Unrecognized opcode");
    540541                        }
    541542                } catch (DataFormatException e) {
    542543                        if (_log.shouldLog(Log.DEBUG))
    543544                                _log.debug("Invalid destination specified");
    544                         return writeString("SESSION STATUS RESULT=INVALID_KEY DESTINATION=" + dest + " MESSAGE=\"" + e.getMessage() + "\"\n");
     545                        return writeString("SESSION STATUS RESULT=INVALID_KEY", e.getMessage());
    545546                } catch (I2PSessionException e) {
    546547                        if (_log.shouldLog(Log.DEBUG))
    547548                                _log.debug("I2P error when instantiating session", e);
    548                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
     549                        return writeString(SESSION_ERROR, e.getMessage());
    549550                } catch (SAMException e) {
    550551                        if (_log.shouldLog(Log.INFO))
    551552                                _log.info("Funny SAM error", e);
    552                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
     553                        return writeString(SESSION_ERROR, e.getMessage());
    553554                } catch (IOException e) {
    554555                        _log.error("Unexpected IOException", e);
    555                         return writeString("SESSION STATUS RESULT=I2P_ERROR MESSAGE=\"" + e.getMessage() + "\"\n");
     556                        return writeString(SESSION_ERROR, e.getMessage());
    556557                } finally {
    557558                        // unregister the session if it has not been created
     
    797798                        String pw = props.getProperty("PASSWORD");
    798799                        if (user == null || pw == null)
    799                                 return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"USER and PASSWORD required\"\n");
     800                                return writeString(AUTH_ERROR, "USER and PASSWORD required");
    800801                        String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
    801802                        if (i2cpProps.containsKey(prop))
    802                                 return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"user " + user + " already exists\"\n");
     803                                return writeString(AUTH_ERROR, "user " + user + " already exists");
    803804                        PasswordManager pm = new PasswordManager(I2PAppContext.getGlobalContext());
    804805                        String shash = pm.createHash(pw);
     
    807808                        String user = props.getProperty("USER");
    808809                        if (user == null)
    809                                 return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"USER required\"\n");
     810                                return writeString(AUTH_ERROR, "USER required");
    810811                        String prop = SAMBridge.PROP_PW_PREFIX + user + SAMBridge.PROP_PW_SUFFIX;
    811812                        if (!i2cpProps.containsKey(prop))
    812                                 return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"user " + user + " not found\"\n");
     813                                return writeString(AUTH_ERROR, "user " + user + " not found");
    813814                        i2cpProps.remove(prop);
    814815                } else {
    815                         return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"Unknown AUTH command\"\n");
     816                        return writeString(AUTH_ERROR, "Unknown AUTH command");
    816817                }
    817818                try {
     
    819820                        return writeString("AUTH STATUS RESULT=OK\n");
    820821                } catch (IOException ioe) {
    821                         return writeString("AUTH STATUS RESULT=I2P_ERROR MESSAGE=\"Config save failed: " + ioe + "\"\n");
     822                        return writeString(AUTH_ERROR, "Config save failed: " + ioe);
    822823                }
    823824        }
  • apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java

    r62ad799 r68c6179  
    297297
    298298                if (masterMode) {
    299                     String req = "SESSION CREATE DESTINATION=TRANSIENT STYLE=MASTER ID=master " + opts + '\n';
     299                    String req = "SESSION CREATE DESTINATION=TRANSIENT STYLE=MASTER ID=masterSend " + opts + '\n';
    300300                    samOut.write(req.getBytes("UTF-8"));
    301301                    samOut.flush();
  • apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java

    r62ad799 r68c6179  
    5959   
    6060    private static final int STREAM=0, DG=1, V1DG=2, RAW=3, V1RAW=4, RAWHDR = 5, FORWARD = 6, FORWARDSSL=7;
     61    private static final int MASTER=8;
    6162    private static final String USAGE = "Usage: SAMStreamSink [-s] [-m mode] [-v version] [-b samHost] [-p samPort]\n" +
    6263                                        "                     [-o opt=val] [-u user] [-w password] myDestFile sinkDir\n" +
     
    6566                                        "              stream-forward: 6; stream-forward-ssl: 7\n" +
    6667                                        "       -s: use SSL to connect to bridge\n" +
     68                                        "       -x: use master session (forces -v 3.3)\n" +
    6769                                        "       multiple -o session options are allowed";
    6870    private static final int V3FORWARDPORT=9998;
     
    7072
    7173    public static void main(String args[]) {
    72         Getopt g = new Getopt("SAM", args, "sb:m:p:u:v:w:");
     74        Getopt g = new Getopt("SAM", args, "sxb:m:p:u:v:w:");
    7375        boolean isSSL = false;
     76        boolean isMaster = false;
    7477        int mode = STREAM;
    7578        String version = "1.0";
     
    8689                break;
    8790
     91            case 'x':
     92                isMaster = true;
     93                break;
     94
    8895            case 'm':
    8996                mode = Integer.parseInt(g.getOptarg());
     
    131138            System.err.println(USAGE);
    132139            return;
     140        }
     141        if (isMaster) {
     142            mode += MASTER;
     143            version = "3.3";
    133144        }
    134145        if ((user == null && password != null) ||
     
    170181                _log.debug("Reader created");
    171182            String ourDest = handshake(out, version, true, eventHandler, mode, user, password, sessionOpts);
     183            if (mode >= MASTER)
     184                mode -= MASTER;
    172185            if (ourDest == null)
    173186                throw new IOException("handshake failed");
     
    561574    }
    562575   
    563     /** @return our b64 dest or null */
     576    /**
     577     * @param isMaster is this the control socket
     578     * @return our b64 dest or null
     579     */
    564580    private String handshake(OutputStream samOut, String version, boolean isMaster,
    565581                             SAMEventHandler eventHandler, int mode, String user, String password,
     
    642658                    dest = _destFile;
    643659                }
     660                boolean masterMode;  // are we using v3.3 master session
     661                String command;
     662                if (mode >= MASTER) {
     663                    masterMode = true;
     664                    command = "ADD";
     665                    mode -= MASTER;
     666                } else {
     667                    masterMode = false;
     668                    command = "CREATE DESTINATION=" + dest;
     669                }
    644670                String style;
    645671                if (mode == STREAM || mode == FORWARD || mode == FORWARDSSL)
     
    655681                else
    656682                    style = "RAW HEADER=true PORT=" + V3DGPORT;
    657                 String req = "SESSION CREATE STYLE=" + style + " DESTINATION=" + dest + ' ' + _conOptions + ' ' + sopts + '\n';
     683
     684                if (masterMode) {
     685                    String req = "SESSION CREATE DESTINATION=" + dest + " STYLE=MASTER ID=masterSink " + sopts + '\n';
     686                    samOut.write(req.getBytes("UTF-8"));
     687                    samOut.flush();
     688                    if (_log.shouldLog(Log.DEBUG))
     689                        _log.debug("SESSION CREATE STYLE=MASTER sent");
     690                    boolean ok = eventHandler.waitForSessionCreateReply();
     691                    if (!ok)
     692                        throw new IOException("SESSION CREATE STYLE=MASTER failed");
     693                    if (_log.shouldLog(Log.DEBUG))
     694                        _log.debug("SESSION CREATE STYLE=MASTER reply found: " + ok);
     695                }
     696
     697                String req = "SESSION " + command + " STYLE=" + style + ' ' + _conOptions + ' ' + sopts + '\n';
    658698                samOut.write(req.getBytes("UTF-8"));
    659699                samOut.flush();
    660700                if (_log.shouldLog(Log.DEBUG))
    661                     _log.debug("Session create sent");
     701                    _log.debug("SESSION " + command + " sent");
    662702                if (mode == STREAM) {
    663                     boolean ok = eventHandler.waitForSessionCreateReply();
     703                    // why only waiting in stream mode?
     704                    boolean ok;
     705                    if (masterMode)
     706                        ok = eventHandler.waitForSessionAddReply();
     707                    else
     708                        ok = eventHandler.waitForSessionCreateReply();
    664709                    if (!ok)
    665                         throw new IOException("Session create failed");
     710                        throw new IOException("SESSION " + command + " failed");
    666711                    if (_log.shouldLog(Log.DEBUG))
    667                         _log.debug("Session create reply found: " + ok);
     712                        _log.debug("SESSION " + command + " reply found: " + ok);
    668713                }
    669714                req = "NAMING LOOKUP NAME=ME\n";
Note: See TracChangeset for help on using the changeset viewer.