Как связать локальный адрес в качестве исходного адреса при использовании Ganymed API для SFTP?

Мы развертываем проект Java на Linux Server. Проект генерирует файл, который затем отправляется на удаленный сервер.

Ранее он был реализован с использованием Jsch. Однако из-за его зависимости от JCE и невозможности обновить версию java (с 5) мы переходим на Ganymed. Я использую Ganymed build 210 (а именно, протестирован для Java 5; http://www.ganymed.ethz.ch/ssh2)

Это функция, которую я использую для sftp-файла.

public boolean sftp_put() {

    File privateKeyFile = new File(identityPath);
    File rfile = new File(hostDir);
    File lfile = new File(lpath);
    boolean success = false;

    try {
        if (!lfile.exists() || lfile.isDirectory()) {
            throw new IOException("Local file must be a regular file: "
                    + lpath);
        }

        Connection ssh = new Connection(host, port);

        ssh.connect();

        ssh.authenticateWithPublicKey(user, privateKeyFile, password);
        SFTPv3Client sftp = new SFTPv3Client(ssh);

        try {
            SFTPv3FileAttributes attr = sftp.lstat(hostDir);
            if (attr.isDirectory()) {
                rfile = new File(hostDir, lfile.getName());
            }
        } catch (SFTPException e) {
            try {
                SFTPv3FileAttributes attr = sftp.lstat(rfile.getParent());
                if (!attr.isDirectory()) {
                    throw new IOException(
                            "Remote file's parent must be a directory: "
                                    + hostDir + "," + e);
                }
            } catch (SFTPException ex) {
                throw new IOException(
                        "Remote file's parent directory must exist: "
                                + hostDir + "," + ex);
            }
        }
        SFTPv3FileHandle file = sftp.createFileTruncate(rfile
                .getCanonicalPath());

        long fileOffset = 0;
        byte[] src = new byte[32768];
        int i = 0;
        FileInputStream input = new FileInputStream(lfile);
        while ((i = input.read(src)) != -1) {
            sftp.write(file, fileOffset, src, 0, i);
            fileOffset += i;
        }

        input.close();
        sftp.closeFile(file);
        sftp.close();

        success=true;
    } catch (IOException e1) {
        logger.warn("Exception while trying to sftp", e)
    }

    return success;
}

Я не могу подключиться к удаленному серверу, возможно, из-за проблем с привязкой и не знаю, что делать дальше? Я думаю о привязке локального адреса перед SFTP.

Поэтому я написал функцию сокета.

public Socket createSocket(String destinationHost, int destinationPort)
        throws IOException, UnknownHostException {
    logger.info("sftp configured bind address : " + bindAddress
            + ", bind port : " + bindPort);
    Socket socket = new Socket();
    socket.bind(new InetSocketAddress(bindAddress, bindPort));
    socket.connect(new InetSocketAddress(destinationHost, destinationPort),
            connectionTimeOut);
    if (socket.isBound()) {
        logger.info("sftp actual bind port : " + socket.getLocalPort());
    } else {
        logger.warn("sftp socket not bound to local port");
    }
    return socket;
}

Однако это также не работает, и я получаю исключение Socket Exception.

РЕДАКТИРОВАТЬ: Итак, я правильно создавал сокет, но нигде не использую тот же сокет для создания соединения. Такой метод не определен ни в одной из библиотек Ganymed.


person Arcane    schedule 13.01.2016    source источник


Ответы (1)


Поскольку в ганимеде не было встроенного метода, я отредактировал исходный код, чтобы написать метод.

Ниже приведены изменения, которые я сделал.

в класс, где я использую

SocketAddress sourceAddress = new InetSocketAddress(bindAddress,
                bindPort);
        Connection ssh = new Connection(host, port);
        ssh.bindSourceAddress(sourceAddress);
        ssh.connect();

затем я внес некоторые изменения в connection.class API Ganymed. Импортированный класс и объявленные переменные соответственно

Это простой способ передачи bindAddress.

public void bindSourceAddress(SocketAddress sourceAddress) {
            this.sourceAddress = sourceAddress;
        }

Передача адреса в класс Transport Manager при использовании метода инициализации.

if (sourceAddress != null) {
                tm.initialize(cryptoWishList, verifier, dhgexpara,
                        connectTimeout, getOrCreateSecureRND(), proxyData,
                        sourceAddress);
            } else {
                tm.initialize(cryptoWishList, verifier, dhgexpara,
                        connectTimeout, getOrCreateSecureRND(), proxyData);
            }

Изменен конструктор метода инициализации. Он, в свою очередь, вызывает функцию установления соединения, которая аналогичным образом модифицируется для размещения SocketAddress.

private void establishConnection(ProxyData proxyData, int connectTimeout, SocketAddress sourceAddress) throws IOException
{
    /* See the comment for createInetAddress() */

    if (proxyData == null)
    {
        InetAddress addr = createInetAddress(hostname);
        //test
        if (sourceAddress != null) {
                            sock.bind(sourceAddress);
                        }
        sock.connect(new InetSocketAddress(addr, port), connectTimeout);
        sock.setSoTimeout(0);
        return;
    }

    if (proxyData instanceof HTTPProxyData)
    {
        HTTPProxyData pd = (HTTPProxyData) proxyData;

        /* At the moment, we only support HTTP proxies */

        InetAddress addr = createInetAddress(pd.proxyHost);
        //test
        if (sourceAddress != null) {
                            sock.bind(sourceAddress);
                        }
        sock.connect(new InetSocketAddress(addr, pd.proxyPort), connectTimeout);
        sock.setSoTimeout(0);

Наконец привязал розетку. Будучи новичком в Java, мне потребовалось немало времени, чтобы понять это правильно. Скорее всего, никто это не прочитает и не понадобится, но опубликовал это решение на всякий случай для таких, как я!

person Arcane    schedule 15.01.2016