Trying to send a file with zmodem using lrzsz via java telnet server

960 views Asked by At

I am trying to use lrzsz to send a file by zmodem by reading stdio in java and forwarding it to a socket of a connected client.

private void sendFiles(ArrayList<String> filenames) {
    Process p;
    ProcessBuilder pb;

    filenames.add(0, "/opt/local/bin/sz");

    try {

        pb = new ProcessBuilder(filenames);

        p = pb.start();

        InputStreamReader  lrzszin = new InputStreamReader(p.getInputStream());
        OutputStreamWriter lrzszout = new OutputStreamWriter(p.getOutputStream());

        InputStreamReader telnetin = new InputStreamReader(socket.getInputStream());
        OutputStreamWriter telnetout = new OutputStreamWriter(socket.getOutputStream());


        while (p.isAlive()) {
            if (lrzszin.ready()) {
                telnetout.write(lrzszin.read());
                telnetout.flush();
            }
            if (telnetin.ready()) {
                lrzszout.write(telnetin.read());
                lrzszout.flush();
            }
        }


    } catch (IOException ex) {

    } 
}

However the zmodem downloads are coming through corrupted. and it errors out.

2

There are 2 answers

0
Andrew Pamment On BEST ANSWER

Answering my own question...

I needed to add the correct character encodings to the input and output streams.

        BufferedReader  lrzszin = new BufferedReader(new InputStreamReader(p.getInputStream(), "ISO-8859-1"));
        BufferedWriter lrzszout = new BufferedWriter(new OutputStreamWriter(p.getOutputStream(), "ISO-8859-1"));

        BufferedReader telnetin = new BufferedReader(new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
        BufferedWriter telnetout = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "ISO-8859-1"));

While SEXYZ telnet option accounts for the IAC characters, I am not sure if lrzsz does (probably not) so I added Brian's suggestion of escaping them as well.

4
Brian White On

You tagged your question "telnet" but you don't explicitly say you're using telnet to connect remotely.

Telnet is not 8-bit clean. It uses "escape" characters to exchange configuration information between the client and server. Your transfer program likely expects a raw connection.

You could try implementing basic Telnet support into your application. For your purposes, it probably means just escaping and un-escaping the IAC (0xFF) character that is used to prefix Telnet commands. Telnet interfaces will turn these bytes from the raw stream into double IAC characters on the network, much like "\\" in a string to get a single backslash.

There's no point in using zmodem over network interfaces -- it was designed for serial lines which had no built-in error detection/correction. scp or rsync (which uses ssh) are your best bets though I sometimes use the socket program (or netcat) to create a raw listening port and connect directly to that to transfer files.

Machine 1: socket -q -l 12345 <archive.zip

Machine 2: socket -q machine1 12345 >archive.zip

(commands are typed from memory and my not be strictly accurate)