comparison src/org/tmatesoft/hg/internal/remote/SshConnector.java @ 699:a483b2b68a2e

Provisional APIs and respective implementation for http, https and ssh remote repositories
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 08 Aug 2013 19:18:50 +0200
parents 822f3a83ff57
children
comparison
equal deleted inserted replaced
698:822f3a83ff57 699:a483b2b68a2e
18 18
19 import java.io.BufferedReader; 19 import java.io.BufferedReader;
20 import java.io.ByteArrayInputStream; 20 import java.io.ByteArrayInputStream;
21 import java.io.Closeable; 21 import java.io.Closeable;
22 import java.io.EOFException; 22 import java.io.EOFException;
23 import java.io.File;
24 import java.io.FilterInputStream; 23 import java.io.FilterInputStream;
25 import java.io.FilterOutputStream; 24 import java.io.FilterOutputStream;
26 import java.io.IOException; 25 import java.io.IOException;
27 import java.io.InputStream; 26 import java.io.InputStream;
28 import java.io.InputStreamReader; 27 import java.io.InputStreamReader;
29 import java.io.OutputStream; 28 import java.io.OutputStream;
30 import java.io.SequenceInputStream; 29 import java.io.SequenceInputStream;
31 import java.net.URI;
32 import java.util.ArrayList; 30 import java.util.ArrayList;
33 import java.util.Collection; 31 import java.util.Collection;
34 import java.util.Collections; 32 import java.util.Collections;
35 import java.util.List; 33 import java.util.List;
36 34
35 import org.tmatesoft.hg.auth.HgAuthFailedException;
36 import org.tmatesoft.hg.auth.HgAuthenticator;
37 import org.tmatesoft.hg.core.HgRemoteConnectionException; 37 import org.tmatesoft.hg.core.HgRemoteConnectionException;
38 import org.tmatesoft.hg.core.Nodeid; 38 import org.tmatesoft.hg.core.Nodeid;
39 import org.tmatesoft.hg.core.SessionContext; 39 import org.tmatesoft.hg.core.SessionContext;
40 import org.tmatesoft.hg.repo.HgRemoteRepository.Range; 40 import org.tmatesoft.hg.repo.HgRemoteRepository.Range;
41 import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteDescriptor;
41 import org.tmatesoft.hg.repo.HgRuntimeException; 42 import org.tmatesoft.hg.repo.HgRuntimeException;
42 import org.tmatesoft.hg.util.LogFacility.Severity; 43 import org.tmatesoft.hg.util.LogFacility.Severity;
43 44
44 import com.trilead.ssh2.Connection; 45 import com.trilead.ssh2.Connection;
45 import com.trilead.ssh2.ConnectionInfo;
46 import com.trilead.ssh2.Session; 46 import com.trilead.ssh2.Session;
47 import com.trilead.ssh2.StreamGobbler; 47 import com.trilead.ssh2.StreamGobbler;
48 48
49 /** 49 /**
50 * Remote repository via SSH 50 * Remote repository via SSH
51 * 51 *
52 * @author Artem Tikhomirov 52 * @author Artem Tikhomirov
53 * @author TMate Software Ltd. 53 * @author TMate Software Ltd.
54 */ 54 */
55 public class SshConnector implements Connector { 55 public class SshConnector extends ConnectorBase {
56 private RemoteDescriptor rd;
56 private SessionContext sessionCtx; 57 private SessionContext sessionCtx;
57 private URI uri;
58 private Connection conn; 58 private Connection conn;
59 private Session session; 59 private Session session;
60 private int sessionUse; 60 private int sessionUse;
61 61
62 private StreamGobbler remoteErr, remoteOut; 62 private StreamGobbler remoteErr, remoteOut;
63 private OutputStream remoteIn; 63 private OutputStream remoteIn;
64 64
65 public void init(URI uri, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException { 65 public void init(RemoteDescriptor remote, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException {
66 rd = remote;
66 sessionCtx = sessionContext; 67 sessionCtx = sessionContext;
67 this.uri = uri; 68 setURI(remote.getURI());
68 } 69 }
69 70
70 public void connect() throws HgRemoteConnectionException, HgRuntimeException { 71 public void connect() throws HgAuthFailedException, HgRemoteConnectionException, HgRuntimeException {
71 try { 72 try {
72 conn = new Connection(uri.getHost(), uri.getPort() == -1 ? 22 : uri.getPort()); 73 conn = new Connection(uri.getHost(), uri.getPort() == -1 ? 22 : uri.getPort());
73 conn.connect(); 74 conn.connect();
74 } catch (IOException ex) { 75 authenticateClient();
75 throw new HgRemoteConnectionException("Failed to establish connection"); 76 } catch (IOException ex) {
76 } 77 throw new HgRemoteConnectionException("Failed to establish connection").setServerInfo(getServerLocation());
77 try { 78 }
78 conn.authenticateWithPublicKey(System.getProperty("user.name"), new File(System.getProperty("user.home"), ".ssh/id_rsa"), null); 79 }
79 ConnectionInfo ci = conn.getConnectionInfo(); 80
80 System.out.printf("%s %s %s %d %s %s %s\n", ci.clientToServerCryptoAlgorithm, ci.clientToServerMACAlgorithm, ci.keyExchangeAlgorithm, ci.keyExchangeCounter, ci.serverHostKeyAlgorithm, ci.serverToClientCryptoAlgorithm, ci.serverToClientMACAlgorithm); 81 private void authenticateClient() throws HgAuthFailedException {
81 } catch (IOException ex) { 82 SshAuthMethod m = new SshAuthMethod(conn);
82 throw new HgRemoteConnectionException("Failed to authenticate", ex).setServerInfo(getServerLocation()); 83 if (uri.getUserInfo() != null) {
83 } 84 try {
85 m.tryWithUserInfo(uri.getUserInfo());
86 return;
87 } catch (HgAuthFailedException ex) {
88 // FALL-THROUGH to try with Authenticator
89 }
90 }
91 HgAuthenticator auth = sessionCtx.getAuthenticator(rd);
92 auth.authenticate(rd, m);
84 } 93 }
85 94
86 public void disconnect() throws HgRemoteConnectionException { 95 public void disconnect() throws HgRemoteConnectionException {
87 if (session != null) { 96 if (session != null) {
88 forceSessionClose(); 97 doSessionClose();
89 } 98 }
90 if (conn != null) { 99 if (conn != null) {
91 conn.close(); 100 conn.close();
92 conn = null; 101 conn = null;
93 } 102 }
117 assert session != null; 126 assert session != null;
118 if (sessionUse > 1) { 127 if (sessionUse > 1) {
119 sessionUse--; 128 sessionUse--;
120 return; 129 return;
121 } 130 }
122 forceSessionClose(); 131 doSessionClose();
123 } 132 }
124 133
125 public String getServerLocation() {
126 return uri.toString(); // FIXME
127 }
128
129 public String getCapabilities() throws HgRemoteConnectionException { 134 public String getCapabilities() throws HgRemoteConnectionException {
130 try { 135 try {
131 consume(remoteOut); 136 consume(remoteOut);
132 consume(remoteErr); 137 consume(remoteErr);
133 remoteIn.write(CMD_HELLO.getBytes()); 138 remoteIn.write(CMD_HELLO.getBytes());
289 throw new IOException(String.format("Expected response length instead of %s", sb)); 294 throw new IOException(String.format("Expected response length instead of %s", sb));
290 } 295 }
291 } 296 }
292 297
293 298
294 private void forceSessionClose() { 299 private void doSessionClose() {
295 if (session != null) { 300 if (session != null) {
296 closeQuietly(remoteErr); 301 closeQuietly(remoteErr);
297 closeQuietly(remoteOut); 302 closeQuietly(remoteOut);
298 remoteErr = remoteOut = null; 303 remoteErr = remoteOut = null;
299 closeQuietly(remoteIn); 304 closeQuietly(remoteIn);