public static GhidraServerHandle getGhidraServerHandle(ServerInfo server, TaskMonitor monitor)
			throws IOException, CancelledException {

		GhidraServerHandle gsh = null;
		boolean canCancel = monitor.isCancelEnabled(); // original state
		try {

			// Test SSL Handshake to ensure that user is able to decrypt keystore.
			// This is intended to work around an RMI issue where a continuous
			// retry condition can occur when a user cancels the password entry
			// for their keystore which should cancel any connection attempt
			testServerSSLConnection(server, monitor);

			monitor.setCancelEnabled(false);
			monitor.setMessage("Connecting...");

			Registry reg =
				LocateRegistry.getRegistry(server.getServerName(), server.getPortNumber(),
					new SslRMIClientSocketFactory());
			checkServerBindNames(reg);

			gsh = (GhidraServerHandle) reg.lookup(GhidraServerHandle.BIND_NAME);
			gsh.checkCompatibility(GhidraServerHandle.INTERFACE_VERSION);
		}
		catch (NotBoundException e) {
			throw new IOException(e.getMessage());
		}
		catch (SSLHandshakeException e) {
			if (isSSLHandshakeCancelled(e)) {
				return null;
			}
			throw e;
		}
		catch (RemoteException e) {
			Throwable cause = e.getCause();
			if (cause instanceof UnmarshalException || cause instanceof ClassNotFoundException) {
				throw new RemoteException("Incompatible Ghidra Server interface version");
			}
			if (cause instanceof SSLHandshakeException) {
				if (isSSLHandshakeCancelled((SSLHandshakeException) cause)) {
					return null;
				}
			}
			throw e;
		}
		finally {
			monitor.setCancelEnabled(canCancel);
			monitor.setMessage("");
		}
		return gsh;
	}
Obtain a remote instance of the Ghidra Server Handle object
@param server server information
@param monitor cancellable monitor
@return Ghidra Server Handle object
@throws IOException if a connection error occurs
@throws CancelledException if connection attempt was cancelled
Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ServerConnectTask.java