/*

sshclient.h

  Authors:
        Tatu Ylonen <ylo@ssh.fi>
        Markku-Juhani Saarinen <mjos@ssh.fi>
        Timo J. Rinne <tri@ssh.fi>
        Sami Lehtinen <sjl@ssh.fi>

  Copyright (C) 1997-1998 SSH Communications Security Oy, Espoo, Finland
  All rights reserved.

SSH client functionality for processing a connection.

*/

#ifndef SSHCLIENT_H
#define SSHCLIENT_H

#include "sshcommon.h"
#include "sshcrypt.h"
#include "sshconfig.h"
#include "sshauthmethods.h"
#include "sshuser.h"
#include "sshtrans.h"
#include "sshchsession.h"
#include "sshreadline.h"
#include "sshoperation.h"

typedef struct SshClientRec *SshClient;

typedef void (*SshClientStreamWrapperFunc)(Boolean ssh1_compatibility,
                                           SshClient client);

/* Data type for the SSH client object.  The client object processes
   one connection (potentially multiple sessions/channels). */

struct SshClientRec
{
  /* Used to make sure that a given SshClient-object will only be destroyed
     once. Earlier it was possible for ssh_client_destroy to be called
     again from a callback when ssh_client_destroy()'s earlier call was not
     yet complete. */
  Boolean being_destroyed;
  
  /* Connection data for both client and server. */
  SshCommon common;

  /* Configuration options that are relevant for this client. */
  SshConfig config;
  
  /* Authentication methods. */
  SshAuthClientMethod *methods;

  /* Data for the user at the client end. */
  SshUser user_data;

  /* Whether a session channel has been requested. */
  Boolean session_requested;
  
  /* Stream for stdio, needed by authentication etc, whatever need
     interaction from the user (when we're running standalone). */
  SshStream stdio_stream;
  
  /* Function which is called after a successful authentication,
     either be the SshClient interface (before the
     authentication_notify callback is called) or the ssh1-emulation
     library. */
  SshClientStreamWrapperFunc stream_wrapper_func;
  
  /* Readline context, used by the authentication mecahanism for user
     interface. */
  SshReadLineCtx rl;
  
  /* This data is included here in order to be able to implement ssh1
     compatibility module and attach it to version_check callback. 
     This information is filled in in ssh_client_wrap.  Stdio/stderr 
     streams are the ones that are connected to the main session channel. */
  SshStream transport_stream;
  /* The transport context. This is to be used _ONLY_ to gather
     statistics. */
  void *tr_context;
  
  SshStream stderr_stream;
  const char *remote_server;
  const char *remote_user;
  const char *remote_command;
  Boolean allocate_pty;
  const char *terminal_type;
  void (*close_notify)(SshUInt32 exit_status, void *context);

  /* These are wrappers for the same calls from the SshCommon
     level. These are needed, so that we can give a SshClient object
     to SshCommon, because we need to call registered
     stream_wrapper_func before authentication_notify at this
     module. */
  SshConnDisconnectProc disconnect;  
  SshConnDebugProc debug;
  SshCommonAuthenticationNotify authentication_notify;


  void *context;
};

/* Data type for SSH client's general data. Holds practically everything
 needed by client prog.  */

typedef struct {
  SshConfig config;
  SshUser user_data;

  char *command;
  int exit_status; /* command's exit status */

  Boolean allocate_pty;
  Boolean is_subsystem;
  Boolean no_session_channel;
  char *term;
  char **env;

  SshClient client;
  Boolean debug;

  SshForward local_forwards;
  SshForward remote_forwards;

  SshStream main_stdio_stream;
  SshStream main_stderr_stream;
  SshStream user_input_stream;
} *SshClientData;

/* Callback function to be called whenever a channel is closed.
     `channel_id'    the channel id passed when the channel was created
     `context'       context argument from ssh_client_wrap. */
typedef void (*SshClientChannelCloseProc)(int channel_id,
                                          void *context);

/* Takes a stream, and creates an SSH client for processing that
   connection.  This closes the stream and returns NULL (without
   calling the destroy function) if an error occurs.  The random state
   is required to stay valid until the client has been destroyed.
   ``config'' must remain valid until the client is destroyed; it is
   not automatically freed.
     `stream'        the connection stream
     `config'        configuration data (not freed, must remain valid)
     `user_data'     data for client user
     `server_host_name'
                     name of the server host, as typed by the user
     `user'          (initial) user to log in as (may be changed during auth)
     `command'       the command to run in the server end
     `term'          the terminal type, needed by ssh1-emulation code
     ^stream_wrapper_func'
                     function, that is called when the stdio-streams can
                     be wrapped (this was added mainly to make ssh1-emulation
                     possible)
     `stdio_stream'  the main stdio_stream, needed mainly by ssh1-emulation
     `allocate_pty'  TRUE if pty should be allocated for command
     `disconnect'    function to call on disconnect
     `debug'         function to call on debug message (may be NULL)
     `authentication_notify'
                     function to call when authentication result is known
                     (may be NULL)
     `close_notify'  function, which is called when the underlying stream
                     is closed for some reason
     `context'       context to pass to ``destroy''
   The object should be destroyed from the ``disconnect'' callback or from
   a ``close_notify'' callback (see below).  */
SshClient ssh_client_wrap(SshStream stream, SshConfig config,
                          SshUser user_data,
                          const char *server_host_name,
                          const char *user,
                          const char *command,
                          const char *term,
                          SshClientStreamWrapperFunc stream_wrapper_func,
                          SshStream stdio_stream,
                          Boolean allocate_pty,
                          SshConnDisconnectProc disconnect,
                          SshConnDebugProc debug,
                          SshCommonAuthenticationNotify authentication_notify,
                          void (*close_notify)(SshUInt32 exit_status, 
                                               void *context),
                          void *context);

/* Forcibly destroys the given connection. */
void ssh_client_destroy(SshClient client);

/* Starts a new command at the server.
     `client'       the client protocol object
     `stdio_stream' stream for stdin/stdout data
     `stderr_stream' stream for stderr data, or NULL to merge with stdout
     `auto_close'   automatically close stdio and stderr on channel close
     `is_subsystem' TRUE if command is a subsystem name instead of command
     `command'      command to execute, or NULL for shell
     `allocate_pty' TRUE if pty should be allocated for the command
     `term'         terminal type for pty (e.g., "vt100"), NULL otherwise
     `env'          NULL, or "name=value" strings to pass as environment
     `forward_x11'  TRUE to request X11 forwarding
     `forward_agent' TRUE to request agent forwarding
     `completion'   completion procedure to be called when done (may be NULL)
     `close_notify' function to call when ch closed (may be NULL)
     `context'      argument to pass to ``completion''.
   It is not an error if some forwarding fails, or an environment variable
   passing is denied.  The ``close_notify'' callback will be called
   regardless of the way the session is destroyed - ssh_client_destroy will
   call ``close_notify'' for all open channels.  It is also called if opening
   the cannnel fails.  It is legal to call ssh_conn_destroy from
   ``close_notify'', unless it has already been called. */
void ssh_client_start_session(SshClient client, SshStream stdio_stream,
                              SshStream stderr_stream, Boolean auto_close,
                              Boolean is_subsystem, const char *command,
                              Boolean allocate_pty, const char *term,
                              const char **env,
                              Boolean forward_x11, Boolean forward_agent,
                              void (*completion)(Boolean success,
                                                 SshChannelSession session,
                                                 void *context),
                              void (*close_notify)(SshUInt32 exit_status,
                                                   void *context),
                              void *context);

/* Requests forwarding of the given remote TCP/IP port.  If the completion
   procedure is non-NULL, it will be called when done. */
void ssh_client_remote_tcp_ip_forward(SshClient client,
                                      const char *address_to_bind,
                                      const char *port,
                                      const char *connect_to_host,
                                      const char *connect_to_port,
                                      const char *protocol,
                                      void (*completion)(Boolean success,
                                                         void *context),
                                      void *context);

/* Requests forwarding of the given local TCP/IP port.  If the completion
   procedure is non-NULL, it will be called when done. */
Boolean ssh_client_local_tcp_ip_forward(SshClient client,
                                        const char *address_to_bind,
                                        const char *port,
                                        const char *connect_to_host,
                                        const char *connect_to_port,
                                        const char *protocol);

/* Opens a direct connection to the given TCP/IP port at the remote side.
   The originator values should be set to useful values and are passed
   to the other side.  ``stream'' will be used to transfer channel data. */
void ssh_client_open_remote_tcp_ip(SshClient client, SshStream stream,
                                   const char *connect_to_host,
                                   const char *connect_to_port,
                                   const char *originator_ip,
                                   const char *originator_port);

/* Function, that informs the calling parent process of success in
   authentication. Is not called automatically by SshClient, but is
   here for convenience. */
void ssh_client_parent_notify_authentication(Boolean successful,
                                             SshStream stream);

#endif /* SSHCLIENT_H */
