Changeset 513e1b9


Ignore:
Timestamp:
Nov 28, 2015 9:25:44 PM (5 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
68b4ad2
Parents:
dffd441
Message:

SAM: Handle UTF-8 in ReadLine? (ticket #1488)
Allow forever timeout in ReadLine?
Use ReadLine? in v1 and v3 handlers
Fix send client closing too fast in v1 stream mode
UTF-8 test and fixes in clients

Location:
apps/sam/java/src/net/i2p/sam
Files:
1 added
6 edited

Legend:

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

    rdffd441 r513e1b9  
    44import java.io.IOException;
    55import java.io.InputStream;
    6 import java.io.InputStreamReader;
     6import java.io.Reader;
    77import java.net.Socket;
    88import java.net.SocketException;
     
    1111/**
    1212 * Modified from I2PTunnelHTTPServer
     13 * Handles UTF-8. Does not buffer past the end of line.
    1314 *
    1415 * @since 0.9.24
     
    2526     *
    2627     *  @param buf output
    27      *  @param timeout throws SocketTimeoutException immediately if zero or negative
     28     *  @param timeout forever if if zero or negative
    2829     *  @throws SocketTimeoutException if timeout is reached before newline
    2930     *  @throws EOFException if EOF is reached before newline
     
    3233     */
    3334    public static void readLine(Socket socket, StringBuilder buf, int timeout) throws IOException {
    34         if (timeout <= 0)
    35             throw new SocketTimeoutException();
    36         long expires = System.currentTimeMillis() + timeout;
    37         // this reads and buffers extra bytes, so we can't use it
    38         // unless we're going to decode UTF-8 on-the-fly, we're stuck with ASCII
    39         //InputStreamReader in = new InputStreamReader(socket.getInputStream(), "UTF-8");
    40         InputStream in = socket.getInputStream();
     35        final int origTimeout = timeout;
    4136        int c;
    4237        int i = 0;
    43         socket.setSoTimeout(timeout);
    44         while ( (c = in.read()) != -1) {
     38        final long expires;
     39        if (origTimeout > 0) {
     40            socket.setSoTimeout(timeout);
     41            expires = System.currentTimeMillis() + timeout;
     42        } else {
     43            expires = 0;
     44        }
     45        final Reader reader = new UTF8Reader(socket.getInputStream());
     46        while ( (c = reader.read()) != -1) {
    4547            if (++i > MAX_LINE_LENGTH)
    4648                throw new LineTooLongException("Line too long - max " + MAX_LINE_LENGTH);
    4749            if (c == '\n')
    4850                break;
    49             int newTimeout = (int) (expires - System.currentTimeMillis());
    50             if (newTimeout <= 0)
    51                 throw new SocketTimeoutException();
    52             buf.append((char)c);
    53             if (newTimeout != timeout) {
    54                 timeout = newTimeout;
    55                 socket.setSoTimeout(timeout);
     51            if (origTimeout > 0) {
     52                int newTimeout = (int) (expires - System.currentTimeMillis());
     53                if (newTimeout <= 0)
     54                    throw new SocketTimeoutException();
     55                buf.append((char)c);
     56                if (newTimeout != timeout) {
     57                    timeout = newTimeout;
     58                    socket.setSoTimeout(timeout);
     59                }
     60            } else {
     61                buf.append((char)c);
    5662            }
    5763        }
    5864        if (c == -1) {
    59             if (System.currentTimeMillis() >= expires)
     65            if (origTimeout > 0 && System.currentTimeMillis() >= expires)
    6066                throw new SocketTimeoutException();
    6167            else
  • apps/sam/java/src/net/i2p/sam/SAMHandlerFactory.java

    rdffd441 r513e1b9  
    5858            throw new SAMException("Unexpected error", e);
    5959        }
     60        if (log.shouldDebug())
     61            log.debug("New message received: [" + line + ']');
    6062
    6163        // Message format: HELLO VERSION [MIN=v1] [MAX=v2]
  • apps/sam/java/src/net/i2p/sam/SAMv1Handler.java

    rdffd441 r513e1b9  
    9999        boolean canContinue = false;
    100100        Properties props;
     101        final StringBuilder buf = new StringBuilder(128);
    101102
    102103        this.thread.setName("SAMv1Handler " + _id);
     
    121122                        break;
    122123                }
    123                 java.io.InputStream is = clientSocketChannel.socket().getInputStream();
    124                 if (is == null) {
    125                         _log.info("Connection closed by client");
    126                         break;
    127                 }
    128                 msg = DataHelper.readLine(is);
    129                 if (msg == null) {
    130                     _log.info("Connection closed by client (line read : null)");
    131                     break;
    132                 }
     124                buf.setLength(0);
     125                // TODO set timeout first time
     126                ReadLine.readLine(clientSocketChannel.socket(), buf, 0);
     127                msg = buf.toString();
    133128
    134129                if (_log.shouldLog(Log.DEBUG)) {
    135                     _log.debug("New message received: [" + msg + "]");
     130                    _log.debug("New message received: [" + msg + ']');
    136131                }
    137132                props = SAMUtils.parseParams(msg);
  • apps/sam/java/src/net/i2p/sam/SAMv3Handler.java

    rdffd441 r513e1b9  
    330330                                } else {
    331331                                        buf.setLength(0);                                       
    332                                         if (DataHelper.readLine(in, buf))
    333                                                 line = buf.toString();
    334                                         else
    335                                                 line = null;
    336                                 }
    337                                 if (line==null) {
    338                                         if (_log.shouldLog(Log.DEBUG))
    339                                                 _log.debug("Connection closed by client (line read : null)");
    340                                         break;
    341                                 }
    342 
    343                                 if (_log.shouldLog(Log.DEBUG)) {
    344                                         if (_log.shouldLog(Log.DEBUG))
    345                                                 _log.debug("New message received: [" + msg + "]");
    346                                 }
     332                                        // TODO first time, set a timeout
     333                                        ReadLine.readLine(socket, buf, 0);
     334                                        line = buf.toString();
     335                                }
     336
     337                                if (_log.shouldLog(Log.DEBUG))
     338                                        _log.debug("New message received: [" + line + ']');
    347339                                props = SAMUtils.parseParams(line);
    348340                                domain = props.getProperty(SAMUtils.COMMAND);
  • apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java

    rdffd441 r513e1b9  
    238238            try {
    239239                if (user != null && password != null)
    240                     samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=" + user + " PASSWORD=" + password + '\n').getBytes());
     240                    samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=\"" + user.replace("\"", "\\\"") +
     241                                  "\" PASSWORD=\"" + password.replace("\"", "\\\"") + "\"\n").getBytes("UTF-8"));
    241242                else
    242                     samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
     243                    samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes("UTF-8"));
    243244                samOut.flush();
    244245                if (_log.shouldLog(Log.DEBUG))
     
    257258                    _context.random().nextBytes(id);
    258259                    _v3ID = Base32.encode(id);
     260                    if (_isV32)
     261                        _v3ID = "xx€€xx" + _v3ID;
    259262                    _conOptions = "ID=" + _v3ID;
    260263                }
     
    267270                    style = "RAW";
    268271                String req = "SESSION CREATE STYLE=" + style + " DESTINATION=TRANSIENT " + _conOptions + ' ' + opts + '\n';
    269                 samOut.write(req.getBytes());
     272                samOut.write(req.getBytes("UTF-8"));
    270273                samOut.flush();
    271274                if (_log.shouldLog(Log.DEBUG))
     
    278281
    279282                req = "NAMING LOOKUP NAME=ME\n";
    280                 samOut.write(req.getBytes());
     283                samOut.write(req.getBytes("UTF-8"));
    281284                samOut.flush();
    282285                if (_log.shouldLog(Log.DEBUG))
     
    364367                        buf.append(" FROM_PORT=1234 TO_PORT=5678");
    365368                    buf.append('\n');
    366                     byte[] msg = DataHelper.getASCII(buf.toString());
     369                    byte[] msg = DataHelper.getUTF8(buf.toString());
    367370                    synchronized (_samOut) {
    368371                        _samOut.write(msg);
     
    432435                                        throw new IOException("unsupported mode " + _mode);
    433436                                    }
    434                                     byte msg[] = DataHelper.getASCII(m);
     437                                    byte msg[] = DataHelper.getUTF8(m);
    435438                                    _samOut.write(msg);
    436439                                }
     
    441444                            // real datagrams
    442445                            ByteArrayOutputStream baos = new ByteArrayOutputStream(read + 1024);
    443                             baos.write(DataHelper.getASCII("3.0 "));
    444                             baos.write(DataHelper.getASCII(_v3ID));
     446                            baos.write(DataHelper.getUTF8("3.0 "));
     447                            baos.write(DataHelper.getUTF8(_v3ID));
    445448                            baos.write((byte) ' ');
    446                             baos.write(DataHelper.getASCII(_remoteDestination));
     449                            baos.write(DataHelper.getUTF8(_remoteDestination));
    447450                            if (_isV32) {
    448451                                // only set TO_PORT to test session setting of FROM_PORT
    449452                                if (_mode == RAW)
    450                                     baos.write(DataHelper.getASCII(" PROTOCOL=123 TO_PORT=5678"));
     453                                    baos.write(DataHelper.getUTF8(" PROTOCOL=123 TO_PORT=5678"));
    451454                                else
    452                                     baos.write(DataHelper.getASCII(" TO_PORT=5678"));
     455                                    baos.write(DataHelper.getUTF8(" TO_PORT=5678"));
    453456                            }
    454457                            baos.write((byte) '\n');
     
    477480                    }
    478481                } else {
    479                     byte msg[] = ("STREAM CLOSE ID=" + _connectionId + "\n").getBytes();
    480482                    try {
     483                        byte msg[] = ("STREAM CLOSE ID=" + _connectionId + "\n").getBytes("UTF-8");
    481484                        synchronized (_samOut) {
    482485                            _samOut.write(msg);
    483486                            _samOut.flush();
    484                             _samOut.close();
     487                            // we can't close this yet, we will lose data
     488                            //_samOut.close();
    485489                        }
    486490                    } catch (IOException ioe) {
     
    493497           
    494498            closed();
     499            // stop the reader, since we're only doing this once for testing
     500            // you wouldn't do this in a real application
     501            // closing the master socket too fast will kill the data socket flushing through
     502            try {
     503                Thread.sleep(10000);
     504            } catch (InterruptedException ie) {}
    495505            if (_log.shouldLog(Log.DEBUG))
    496506                _log.debug("Runner exiting");
     
    499509            if (_reader2 != null)
    500510                _reader2.stopReading();
    501             // stop the reader, since we're only doing this once for testing
    502             // you wouldn't do this in a real application
    503             if (_isV3) {
    504                 // closing the master socket too fast will kill the data socket flushing through
    505                 try {
    506                     Thread.sleep(10000);
    507                 } catch (InterruptedException ie) {}
    508             }
    509511            _reader.stopReading();
    510512        }
  • apps/sam/java/src/net/i2p/sam/client/SAMStreamSink.java

    rdffd441 r513e1b9  
    308308                    Thread.sleep(127*1000);
    309309                    synchronized(_out) {
    310                         _out.write(DataHelper.getASCII("PING " + System.currentTimeMillis() + '\n'));
     310                        _out.write(DataHelper.getUTF8("PING " + System.currentTimeMillis() + '\n'));
    311311                        _out.flush();
    312312                    }
     
    378378            synchronized (_out) {
    379379                try {
    380                     _out.write(("PONG " + data + '\n').getBytes());
     380                    _out.write(("PONG " + data + '\n').getBytes("UTF-8"));
    381381                    _out.flush();
    382382                } catch (IOException ioe) {
     
    515515            try {
    516516                if (user != null && password != null)
    517                     samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=" + user + " PASSWORD=" + password + '\n').getBytes());
     517                    samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + " USER=" + user + " PASSWORD=" + password + '\n').getBytes("UTF-8"));
    518518                else
    519                     samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes());
     519                    samOut.write(("HELLO VERSION MIN=1.0 MAX=" + version + '\n').getBytes("UTF-8"));
    520520                samOut.flush();
    521521                if (_log.shouldLog(Log.DEBUG))
     
    537537                    else
    538538                        throw new IllegalStateException("mode " + mode);
    539                     samOut.write(req.getBytes());
     539                    samOut.write(req.getBytes("UTF-8"));
    540540                    samOut.flush();
    541541                    if (_log.shouldLog(Log.DEBUG))
     
    601601                    style = "RAW HEADER=true PORT=" + V3DGPORT;
    602602                String req = "SESSION CREATE STYLE=" + style + " DESTINATION=" + dest + ' ' + _conOptions + ' ' + sopts + '\n';
    603                 samOut.write(req.getBytes());
     603                samOut.write(req.getBytes("UTF-8"));
    604604                samOut.flush();
    605605                if (_log.shouldLog(Log.DEBUG))
     
    613613                }
    614614                req = "NAMING LOOKUP NAME=ME\n";
    615                 samOut.write(req.getBytes());
     615                samOut.write(req.getBytes("UTF-8"));
    616616                samOut.flush();
    617617                if (_log.shouldLog(Log.DEBUG))
     
    650650        try {
    651651            fos = new FileOutputStream(f);
    652             fos.write(dest.getBytes());
     652            fos.write(dest.getBytes("UTF-8"));
    653653            if (_log.shouldLog(Log.DEBUG))
    654654                _log.debug("My destination written to " + _destFile);
Note: See TracChangeset for help on using the changeset viewer.