/* An example of ne7ssh library usage. Please change the values in connectWithPassword 
   function before compiling.
   
   This will work with openssh server if default shell of authenticating user is bash.
   When using a different shell or custom prompt replace " $" string in waitFor() 
   method with a string corresponding with your shell prompt.
   
   If you are testing this with later openssh versions, make sure to add this
   option to your server's configuration file to enable password authentication:
   
   PasswordAuthentication yes
*/

#include <ne7ssh.h>

#if defined(WIN32) || defined (__MINGW32__)
#   include <windows.h>
#	define kill(pid,signo) raise(signo)
#	define pthread_cancel(hndl) TerminateThread(hndl,-1)
#	define pthread_exit(sig) ExitThread(sig)
typedef HANDLE pthread_t;
#endif

void* thread1_proc (void* initData);
void* thread2_proc (void* initData);
void* thread3_proc (void* initData);
pthread_t thread1, thread2, thread3;

int main(int argc,char *argv[])
{
 ne7ssh *_ssh = new ne7ssh();
 int status;
  
 // Set SSH connection options.
 _ssh->setOptions ("blowfish-cbc", "hmac-md5");

#if !defined(WIN32) && !defined(__MINGW32__)
 status = pthread_create (&thread1, NULL, thread1_proc, (void*)_ssh);
 status = pthread_create (&thread2, NULL, thread2_proc, (void*)_ssh);
 status = pthread_create (&thread3, NULL, thread3_proc, (void*)_ssh);
 pthread_join (thread1, NULL);
 pthread_join (thread2, NULL);
 pthread_join (thread3, NULL);

#else
  HANDLE h[3];
  if ((thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread1_proc, (LPVOID)_ssh, 0, NULL)) == NULL)
  {
    ne7ssh::errors()->push (-1, "Failure creating new thread.");
    return (EXIT_FAILURE);
  }
  if ((thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread2_proc, (LPVOID)_ssh, 0, NULL)) == NULL)
  {
    ne7ssh::errors()->push (-1, "Failure creating new thread.");
    return (EXIT_FAILURE);
  }
  if ((thread3 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) thread3_proc, (LPVOID)_ssh, 0, NULL)) == NULL)
  {
    ne7ssh::errors()->push (-1, "Failure creating new thread.");
    return (EXIT_FAILURE);
  }
  h[0] = thread1;
  h[1] = thread2;
  h[2] = thread3;
  WaitForMultipleObjects(3, h, TRUE, INFINITE);
#endif

 delete _ssh; 
 return EXIT_SUCCESS;
}


void* thread1_proc (void* initData)
{
 int channel1, i;
 const char* result;
 ne7ssh *_ssh = (ne7ssh*)initData;

 for (i = 0; i < 50; i++)
 {
 // Initiate a connection.
 channel1 = _ssh->connectWithPassword ("example.host", 22, "username", "password", true, 30);
 if (channel1 < 0) 
 {
    printf ("Connection failed with last error: %s\n\n", _ssh->errors()->pop());
    delete _ssh;
    return 0;
 }
  
 // Wait for bash prompt, or die in 5 seconds.
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Failed while waiting for remote shell wiht last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Send "ls" command.
 if (!_ssh->send ("ls\n", channel1)) {
    printf ("Could not send the command. Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Wait for bash prompt, or die in 5 seconds
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Timeout while waiting for remote site.Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Fetch recieved data.
 result = _ssh->read (channel1);
 printf ("Data Thread1: %s\n", result);

 // Close the connection.
 _ssh->send ("exit\n", channel1);
}
}

void* thread2_proc (void* initData)
{
 int channel1, i;
 const char* result;
 ne7ssh *_ssh = (ne7ssh*)initData;

  for (i = 0; i < 50; i++)
 {
// Initiate a connection.
 channel1 = _ssh->connectWithPassword ("example.host", 22, "username", "password", true, 30);
 if (channel1 < 0) 
 {
    printf ("Connection failed with last error: %s\n\n", _ssh->errors()->pop());
    delete _ssh;
    return 0;
 }
  
 // Wait for bash prompt, or die in 5 seconds.
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Failed while waiting for remote shell wiht last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Send "ls" command.
 if (!_ssh->send ("ls\n", channel1)) {
    printf ("Could not send the command. Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Wait for bash prompt, or die in 5 seconds
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Timeout while waiting for remote site.Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Fetch recieved data.
 result = _ssh->read (channel1);
 printf ("Data Thread 2: %s\n", result);

 // Close the connection.
 _ssh->send ("exit\n", channel1);
}
}

void* thread3_proc (void* initData)
{
 int channel1, i;
 const char* result;
 ne7ssh *_ssh = (ne7ssh*)initData;

  for (i = 0; i < 50; i++)
 {
// Initiate a connection.
 channel1 = _ssh->connectWithPassword ("example.host", 22, "username", "password", true, 30);
 if (channel1 < 0) 
 {
    printf ("Connection failed with last error: %s\n\n", _ssh->errors()->pop());
    delete _ssh;
    return 0;
 }
  
 // Wait for bash prompt, or die in 5 seconds.
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Failed while waiting for remote shell wiht last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Send "ls" command.
 if (!_ssh->send ("ls\n", channel1)) {
    printf ("Could not send the command. Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Wait for bash prompt, or die in 5 seconds
 if (!_ssh->waitFor (channel1, " $", 5)) {
    printf ("Timeout while waiting for remote site.Last error: %s\n\n", _ssh->errors()->pop (channel1));
    _ssh->close(channel1);
    delete _ssh;
    return 0;
 }

 // Fetch recieved data.
 result = _ssh->read (channel1);
 printf ("Data Thread 3: %s\n", result);

 // Close the connection.
 _ssh->send ("exit\n", channel1);
}
}

