Yes, a vote is already going on to start the SSH subproject. On Sun, Nov 23, 2008 at 8:19 AM, Jason Dillon <[EMAIL PROTECTED]> wrote: > On Nov 22, 2008, at 6:48 PM, Guillaume Nodet wrote: >>> >>> <snip> >>> Bliss:Applications jason$ ssh localhost -p 8081 >>> [EMAIL PROTECTED]'s password: >>> channel_by_id: 1: bad id: channel free >>> channel_input_success_failure: 1: unknown >>> channel_by_id: 1: bad id: channel free >>> channel_input_success_failure: 1: unknown >>> </snip> >>> >>> This is from "OpenSSH_5.1p1, OpenSSL 0.9.7l 28 Sep 2006" on Mac OS X. It >>> does connect and seems to work well. Though seems to not handle sending >>> over exceptions, like when a command is not resolved. But I might look >>> into >>> that some more later today. >> >> Not sure what those lines mean. When I connect using OpenSSH and >> launch a bad command in ServiceMix, I can see the usual output from >> gshell on stderr with the ansi colors. > > I will investigate more... I did not see the exception spat out on the > client when entering a bad command... perhaps that is because of the above > msgs? > >> There are still lots of things to do, but i think i could release a >> 0.1 very soon. >> Btw, this project should soon move into Apache as a Mina subproject, >> but I will do a release before that at google so that we can embed it. > > Have you talked to the mina folks about it? Anyways, I can't stop saying > how thrilled I am about this. You rock! Needless to say next time we meet > up I'm gonna buy you all the beer you can drink ;-) > > --jason > > >> >>> Your thoughts? >>> >>> --jason >>> >>> >>> On Nov 13, 2008, at 5:58 AM, Guillaume Nodet wrote: >>> >>>> I've just done a real quick prototype to plug into smx kernel and I've >>>> been able to log in into smx kernel using an ssh client and issue a >>>> few commands. >>>> Following is the class that does everything and the spring config to >>>> start the ssh server. >>>> The BogusPasswordAuthenticator is a dummy class which I pasted below >>>> too. >>>> >>>> Notice the use of stream filters to convert CR / CRLF stuff. I think >>>> this is because both sshd and the geronimo gshell do not handle well >>>> the pty request and/or VT100 stuff. But I'm still not sure where the >>>> conversion should happen exactly. >>>> >>>> Also note that i've redefined the ConsoleErrorHandlerImpl, because the >>>> default one uses the application.getIO() for displaying errors so they >>>> are not available remotely. >>>> >>>> Let me know what you think, but it basically makes the whole remote >>>> bits of gshell unused. >>>> I have not implemented the ssh command which should be easy using jsch >>>> lib. >>>> >>>> Let me know if / how I can help you with that bits. >>>> >>>> ================================================== >>>> package org.apache.servicemix.kernel.gshell.core.sshd; >>>> >>>> import com.google.code.sshd.PasswordAuthenticator; >>>> >>>> public class BogusPasswordAuthenticator implements PasswordAuthenticator >>>> { >>>> >>>> public Object authenticate(String username, String password) { >>>> return (username != null && username.equals(password)) ? >>>> username : null; >>>> } >>>> } >>>> >>>> >>>> ================================================== >>>> <bean name="sshServer" class="com.google.code.sshd.SshServer" >>>> init-method="start" destroy-method="stop"> >>>> <property name="port" value="8000" /> >>>> <property name="shellFactory"> >>>> <bean >>>> >>>> class="org.apache.servicemix.kernel.gshell.core.sshd.GShellShellFactory"> >>>> <property name="branding" ref="branding" /> >>>> <property name="completers"> >>>> <list> >>>> <ref bean="commandsCompleter"/> >>>> <ref bean="aliasNameCompleter"/> >>>> </list> >>>> </property> >>>> <property name="executor" ref="commandLineExecutor" /> >>>> <property name="history"> >>>> <bean >>>> class="org.apache.geronimo.gshell.wisdom.shell.HistoryImpl"> >>>> <constructor-arg ref="application"/> >>>> </bean> >>>> </property> >>>> <property name="prompter"> >>>> <bean >>>> class="org.apache.geronimo.gshell.wisdom.shell.ConsolePrompterImpl"> >>>> <constructor-arg ref="application"/> >>>> </bean> >>>> </property> >>>> </bean> >>>> </property> >>>> <property name="hostKeyProvider"> >>>> <bean class="com.google.code.sshd.hostkeys.FileHostKeyProvider"> >>>> <constructor-arg> >>>> <list> >>>> <value>${hostKey}</value> >>>> </list> >>>> </constructor-arg> >>>> </bean> >>>> </property> >>>> <property name="passwordAuthenticator"> >>>> <!-- TODO: provide real authentication --> >>>> <bean >>>> >>>> >>>> class="org.apache.servicemix.kernel.gshell.core.sshd.BogusPasswordAuthenticator" >>>> /> >>>> </property> >>>> <!-- Do not use public keys for now >>>> <property name="publickeyAuthenticator"> >>>> <bean class="com.google.code.sshd.BogusPublickeyAuthenticator" >>>> /> >>>> </property> >>>> --> >>>> <!-- Standard properties --> >>>> <property name="channelFactories"> >>>> <list> >>>> <bean >>>> class="com.google.code.sshd.channel.ChannelSession$Factory" /> >>>> </list> >>>> </property> >>>> <property name="cipherFactories"> >>>> <list> >>>> <bean class="com.google.code.sshd.cipher.AES128CBC$Factory" >>>> /> >>>> <bean >>>> class="com.google.code.sshd.cipher.TripleDESCBC$Factory" /> >>>> <bean >>>> class="com.google.code.sshd.cipher.BlowfishCBC$Factory" /> >>>> <bean class="com.google.code.sshd.cipher.AES192CBC$Factory" >>>> /> >>>> <bean class="com.google.code.sshd.cipher.AES256CBC$Factory" >>>> /> >>>> </list> >>>> </property> >>>> <property name="compressionFactories"> >>>> <list> >>>> <bean >>>> class="com.google.code.sshd.compression.CompressionNone$Factory" /> >>>> </list> >>>> </property> >>>> <property name="keyExchangeFactories"> >>>> <list> >>>> <bean class="com.google.code.sshd.kex.DHG1$Factory" /> >>>> </list> >>>> </property> >>>> <property name="macFactories"> >>>> <list> >>>> <bean class="com.google.code.sshd.mac.HMACMD5$Factory" /> >>>> <bean class="com.google.code.sshd.mac.HMACSHA1$Factory" /> >>>> <bean class="com.google.code.sshd.mac.HMACMD596$Factory" /> >>>> <bean class="com.google.code.sshd.mac.HMACSHA196$Factory" /> >>>> </list> >>>> </property> >>>> <property name="randomFactory"> >>>> <bean class="com.google.code.sshd.random.JceRandom$Factory" /> >>>> </property> >>>> <property name="userAuthFactories"> >>>> <list> >>>> <bean >>>> class="com.google.code.sshd.auth.UserAuthPublicKey$Factory" /> >>>> <bean >>>> class="com.google.code.sshd.auth.UserAuthPassword$Factory" /> >>>> </list> >>>> </property> >>>> <property name="signatureFactories"> >>>> <list> >>>> <bean >>>> class="com.google.code.sshd.signature.SignatureDSA$Factory" /> >>>> <bean >>>> class="com.google.code.sshd.signature.SignatureRSA$Factory" /> >>>> </list> >>>> </property> >>>> </bean> >>>> >>>> >>>> >>>> =================================================== >>>> package org.apache.servicemix.kernel.gshell.core.sshd; >>>> >>>> import java.util.Map; >>>> import java.util.List; >>>> import java.io.OutputStream; >>>> import java.io.InputStream; >>>> import java.io.Closeable; >>>> import java.io.IOException; >>>> >>>> import com.google.code.sshd.ShellFactory; >>>> import com.google.code.sshd.shell.CrLfFilterInputStream; >>>> import org.apache.geronimo.gshell.shell.ShellContext; >>>> import org.apache.geronimo.gshell.io.IO; >>>> import org.apache.geronimo.gshell.command.Variables; >>>> import org.apache.geronimo.gshell.console.Console; >>>> import org.apache.geronimo.gshell.console.JLineConsole; >>>> import org.apache.geronimo.gshell.console.completer.AggregateCompleter; >>>> import org.apache.geronimo.gshell.notification.ExitNotification; >>>> import org.apache.geronimo.gshell.notification.ErrorNotification; >>>> import org.apache.geronimo.gshell.application.model.Branding; >>>> import org.apache.geronimo.gshell.commandline.CommandLineExecutor; >>>> import org.apache.geronimo.gshell.ansi.AnsiRenderer; >>>> import org.slf4j.LoggerFactory; >>>> import org.slf4j.Logger; >>>> import jline.History; >>>> import jline.Completor; >>>> >>>> public class GShellShellFactory implements ShellFactory { >>>> >>>> private Logger logger = LoggerFactory.getLogger(getClass()); >>>> private Branding branding; >>>> private Console.Prompter prompter; >>>> private CommandLineExecutor executor; >>>> private History history; >>>> private List<Completor> completers; >>>> >>>> public Branding getBranding() { >>>> return branding; >>>> } >>>> >>>> public void setBranding(Branding branding) { >>>> this.branding = branding; >>>> } >>>> >>>> public Console.Prompter getPrompter() { >>>> return prompter; >>>> } >>>> >>>> public void setPrompter(Console.Prompter prompter) { >>>> this.prompter = prompter; >>>> } >>>> >>>> public CommandLineExecutor getExecutor() { >>>> return executor; >>>> } >>>> >>>> public void setExecutor(CommandLineExecutor executor) { >>>> this.executor = executor; >>>> } >>>> >>>> public History getHistory() { >>>> return history; >>>> } >>>> >>>> public void setHistory(History history) { >>>> this.history = history; >>>> } >>>> >>>> public List<Completor> getCompleters() { >>>> return completers; >>>> } >>>> >>>> public void setCompleters(List<Completor> completers) { >>>> this.completers = completers; >>>> } >>>> >>>> public Shell createShell() { >>>> return new ShellImpl(); >>>> } >>>> >>>> public class ShellImpl implements ShellFactory.DirectShell, >>>> org.apache.geronimo.gshell.shell.Shell { >>>> >>>> private InputStream in; >>>> private OutputStream out; >>>> private OutputStream err; >>>> private IO io; >>>> private Variables variables; >>>> private ShellContext context; >>>> private boolean closed; >>>> >>>> public ShellImpl() { >>>> } >>>> >>>> public void setInputStream(InputStream in) { >>>> this.in = in; >>>> } >>>> >>>> public void setOutputStream(OutputStream out) { >>>> this.out = out; >>>> } >>>> >>>> public void setErrorStream(OutputStream err) { >>>> this.err = err; >>>> } >>>> >>>> public void start(Map<String,String> env) throws Exception { >>>> this.io = new IO(new CrLfFilterInputStream(in, "IN: ", logger), >>>> new LfToCrLfFilterOutputStream(out, >>>> "OUT:", logger), >>>> new LfToCrLfFilterOutputStream(err, >>>> "ERR:", logger), >>>> false); >>>> this.variables = new Variables((Map) env); >>>> this.context = new ShellContext() { >>>> public org.apache.geronimo.gshell.shell.Shell getShell() { >>>> return ShellImpl.this; >>>> } >>>> public IO getIo() { >>>> return ShellImpl.this.io; >>>> } >>>> public Variables getVariables() { >>>> return ShellImpl.this.variables; >>>> } >>>> }; >>>> new Thread() { >>>> public void run() { >>>> try { >>>> ShellImpl.this.run(); >>>> } catch (Exception e) { >>>> e.printStackTrace(); >>>> } finally { >>>> close(); >>>> } >>>> } >>>> }.start(); >>>> } >>>> >>>> public boolean isAlive() { >>>> return !closed; >>>> } >>>> >>>> public int exitValue() { >>>> if (!closed) { >>>> throw new IllegalThreadStateException(); >>>> } >>>> return 0; >>>> } >>>> >>>> public void destroy() { >>>> close(); >>>> } >>>> >>>> public ShellContext getContext() { >>>> return context; >>>> } >>>> >>>> public Object execute(String line) throws Exception { >>>> return executor.execute(getContext(), line); >>>> } >>>> >>>> public Object execute(String command, Object[] args) throws >>>> Exception { >>>> return executor.execute(getContext(), args); >>>> } >>>> >>>> public Object execute(Object... args) throws Exception { >>>> return executor.execute(getContext(), args); >>>> } >>>> >>>> public boolean isOpened() { >>>> return !closed; >>>> } >>>> >>>> public void close() { >>>> closed = true; >>>> close(in); >>>> close(out); >>>> close(err); >>>> } >>>> >>>> public boolean isInteractive() { >>>> return false; >>>> } >>>> >>>> public void run(Object... args) throws Exception { >>>> Console.Executor executor = new Console.Executor() { >>>> public Result execute(final String line) throws Exception { >>>> assert line != null; >>>> try { >>>> ShellImpl.this.execute(line); >>>> } >>>> catch (ExitNotification n) { >>>> return Result.STOP; >>>> } >>>> return Result.CONTINUE; >>>> } >>>> }; >>>> >>>> IO io = getContext().getIo(); >>>> >>>> // Setup the console runner >>>> JLineConsole console = new JLineConsole(executor, io); >>>> console.setPrompter(getPrompter()); >>>> console.setErrorHandler(new ConsoleErrorHandlerImpl(io)); >>>> console.setHistory(getHistory()); >>>> if (completers != null) { >>>> // Have to use aggregate here to get the completion >>>> list to update properly >>>> console.addCompleter(new AggregateCompleter(completers)); >>>> } >>>> console.run(); >>>> } >>>> >>>> private void close(Closeable c) { >>>> try { >>>> c.close(); >>>> } catch (IOException e) { >>>> // Ignore >>>> } >>>> } >>>> >>>> } >>>> >>>> public static class ConsoleErrorHandlerImpl implements >>>> Console.ErrorHandler { >>>> private final Logger log = LoggerFactory.getLogger(getClass()); >>>> >>>> private final IO io; >>>> >>>> private AnsiRenderer renderer = new AnsiRenderer(); >>>> >>>> public ConsoleErrorHandlerImpl(final IO io) { >>>> assert io != null; >>>> this.io = io; >>>> } >>>> >>>> public Result handleError(final Throwable error) { >>>> assert error != null; >>>> >>>> displayError(error); >>>> >>>> return Result.CONTINUE; >>>> } >>>> >>>> private void displayError(final Throwable error) { >>>> assert error != null; >>>> >>>> // Decode any error notifications >>>> Throwable cause = error; >>>> if (error instanceof ErrorNotification) { >>>> cause = error.getCause(); >>>> } >>>> >>>> // >>>> // TODO: Use the Render API >>>> // >>>> >>>> // Spit out the terse reason why we've failed >>>> io.err.print("@|bold,red ERROR| "); >>>> io.err.print(cause.getClass().getSimpleName()); >>>> io.err.println(": @|bold,red " + cause.getMessage() + "|"); >>>> >>>> // Determine if the stack trace flag is set >>>> String stackTraceProperty = >>>> System.getProperty("gshell.show.stacktrace"); >>>> boolean stackTraceFlag = false; >>>> if (stackTraceProperty != null) { >>>> stackTraceFlag = stackTraceProperty.trim().equals("true"); >>>> } >>>> >>>> if (io.isDebug()) { >>>> // If we have debug enabled then skip the fancy bits >>>> below, and log the full error, don't decode shit >>>> log.debug(error.toString(), error); >>>> } >>>> else if (io.isVerbose() || stackTraceFlag) { >>>> // Render a fancy ansi colored stack trace >>>> StackTraceElement[] trace = cause.getStackTrace(); >>>> StringBuilder buff = new StringBuilder(); >>>> >>>> // >>>> // TODO: Move this to helper in gshell-ansi >>>> // >>>> >>>> for (StackTraceElement e : trace) { >>>> buff.append(" @|bold at| "). >>>> append(e.getClassName()). >>>> append("."). >>>> append(e.getMethodName()). >>>> append(" (@|bold "); >>>> >>>> buff.append(e.isNativeMethod() ? "Native Method" : >>>> (e.getFileName() != null && >>>> e.getLineNumber() != -1 ? e.getFileName() + ":" + e.getLineNumber() : >>>> (e.getFileName() != null ? >>>> e.getFileName() : "Unknown Source"))); >>>> >>>> buff.append("|)"); >>>> >>>> // >>>> // FIXME: This does not properly display the full >>>> exception detail when cause contains nested exceptions >>>> // >>>> >>>> io.err.println(buff); >>>> >>>> buff.setLength(0); >>>> } >>>> } >>>> io.err.flush(); >>>> } >>>> } >>>> >>>> } >>>> >>>> >>>> On Tue, Nov 11, 2008 at 8:07 AM, Jason Dillon <[EMAIL PROTECTED]> >>>> wrote: >>>>> >>>>> How does one hook up GShell to use this stuff? >>>>> >>>>> --jason >>>>> >>>>> >>>>> On Nov 7, 2008, at 4:22 AM, Guillaume Nodet wrote: >>>>> >>>>>> Over the past days, I've been working on a implementing a SSH server >>>>>> in java to replace to gshell remoting bits. >>>>>> The project is currently hosted at google code: >>>>>> http://code.google.com/p/sshd/ >>>>>> >>>>>> This project is based on Mina and the current status is that the ssh >>>>>> protocol is in a working state, but there are still a lots of things >>>>>> to iron. >>>>>> I've been able to connect using openssh 5.0 and 5.1 and also jsch >>>>>> (from which i borrowed from code btw) and launch an /bin/sh shell and >>>>>> issue a few commands. >>>>>> I'd be happy if any committer is interested to work on that to give >>>>>> him commits rights on the project. >>>>>> >>>>>> -- >>>>>> Cheers, >>>>>> Guillaume Nodet >>>>>> ------------------------ >>>>>> Blog: http://gnodet.blogspot.com/ >>>>>> ------------------------ >>>>>> Open Source SOA >>>>>> http://fusesource.com >>>>> >>>>> >>>> >>>> >>>> >>>> -- >>>> Cheers, >>>> Guillaume Nodet >>>> ------------------------ >>>> Blog: http://gnodet.blogspot.com/ >>>> ------------------------ >>>> Open Source SOA >>>> http://fusesource.com >>> >>> >> >> >> >> -- >> Cheers, >> Guillaume Nodet >> ------------------------ >> Blog: http://gnodet.blogspot.com/ >> ------------------------ >> Open Source SOA >> http://fusesource.com > >
-- Cheers, Guillaume Nodet ------------------------ Blog: http://gnodet.blogspot.com/ ------------------------ Open Source SOA http://fusesource.com