Subject: Re: problem with big data packages using libssh2_channel_read

Re: problem with big data packages using libssh2_channel_read

From: Mateusz Pilski <mpilski_at_gmail.com>
Date: Wed, 23 Feb 2011 14:35:58 +0100

2011/2/22 Daniel Stenberg <daniel_at_haxx.se>

> On Tue, 22 Feb 2011, Mateusz Pilski wrote:
>
> Please don't top-post, it makes it very hard to follow what's being said!

sorry for that.

>
> Thank you for quick response. Unfortunately this isn't the solution for my
>> problem because channel is set for nonblocking few lines before code i
>> pasted using
>>
>
> Okay, so what version are you using on what operating system?
>
> i'm using
system: Debian 2.6.32-28
libssh2 version 1.2.7
and all of this is on quite old and slow machine:
cpu 800 mhz 64 KB cache
memory 256 MB
but still it isn't a piece of junk i remember i've played for example quake
2 on similar machine and there were no problems at all and i don't think
that sending encrypted package of 4 KB size could be more demanding than
that.
i have made some test on faster machine (cpu 2400 mhz 1024 KB chache) and
everything goes fine there.

Have you tried to repeat the problem with a recent snapshot/git version?
>
> yes, nothing changed.

>
> also there i use function libssh2_channel_handle_extended_data2(channel,
>> LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE); but i don't suppose that it have
>> influence on my problem.
>>
>
> Can you help us help you and provide a full example that repeats this
> problem?
>
> i post here mostly simplified working code with this error(compile with
-lssh2 -lncurses). Code is quite long but functions connection() and
makeconnection() are just lightly modified code of connection example from
libssh2 site (http://libssh2.org/examples/ssh2.html) so the interesting part
is only function mainloop(). To make connection change first 3 lines of
code. Because i cut most of the code result is litle messy, but what is
important is when you connect and type command "cat largefile.dat" it will
hang just like i described before. Note that if packet will be large but
still smaller than BUFFSIZE (for example if you change BUFFSIZE to 124096
and HALFBUFFSIZE to 62048) all will go well.

#define confighost "127.0.0.1"
#define configusername "login"
#define configpassword "password"
#include <libssh2.h>
#include <ncurses.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h> /* String function definitions */
#include <termios.h> /* POSIX terminal control definitions */

#define BUFFSIZE 4096
#define HALFBUFFSIZE 2048

char pass[64];
int curpos=0,comlen=0;

static void kbd_callback(const char *name, int name_len,
             const char *instruction, int instruction_len, int num_prompts,
             const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
             LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
             void **abstract)
{
    (void)name;
    (void)name_len;
    (void)instruction;
    (void)instruction_len;
    if (num_prompts == 1) {
        responses[0].text = strdup(pass);
        responses[0].length = strlen(pass);
    }
    (void)prompts;
    (void)abstract;
} /* kbd_callback */

int block=0,arrow=0;
    LIBSSH2_SESSION *session;
    LIBSSH2_CHANNEL *channel;

int connection(int *socke)
{
  unsigned long hostaddr;
    int sock, auth_pw = 0;
    struct sockaddr_in sin;
    const char *fingerprint;
    char *userauthlist;
#ifdef WIN32
    WSADATA wsadata;

    WSAStartup(MAKEWORD(2,0), &wsadata);
#endif

hostaddr = inet_addr(confighost);

    sock = socket(AF_INET, SOCK_STREAM, 0);
#ifndef WIN32

    fcntl(sock, F_SETFL, 0);
#endif
    *socke=sock;

    sin.sin_family = AF_INET;
    sin.sin_port = htons(22);
    sin.sin_addr.s_addr = hostaddr;

    if (connect(sock, (struct sockaddr*)(&sin),
                sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "Nie udało się nawiązać połączenia z %s!\nSprawdź
swoje połączenie sieciowe.\nJeśli problem będzie się powtarzać skontaktuj
się z administratorem.\n naciśnij enter aby spróbować ponownie",confighost);

getchar();

        return -1;
    }

printf("połączenie z serwerem jest aktywne\n");
fflush(stdout);
*socke=sock;
}

int makeconnection(LIBSSH2_SESSION **sesion,LIBSSH2_CHANNEL **chanel,int
*socke)
{
LIBSSH2_CHANNEL *channel;
LIBSSH2_SESSION *session;

const char *keyfile1="~/.ssh/id_rsa.pub";
const char *keyfile2="~/.ssh/id_rsa";

strcpy(pass,configpassword);

  unsigned long hostaddr;
    int sock, auth_pw = 0;
    struct sockaddr_in sin;
    const char *fingerprint;
    char *userauthlist;
sock=*socke;

    /* Create a session instance and start it up
     * This will trade welcome banners, exchange keys, and setup crypto,
compression, and MAC layers
     */
    session = libssh2_session_init();
int ind;
for(ind=0;ind<5;ind++)
    if (!libssh2_session_startup(session, sock))break;
 if(ind==5)
 {
    if(sock)
{
#ifdef WIN32
    closesocket(sock);
#else
    close(sock);
#endif
}
    connection(&sock);
    for(ind=0;ind<5;ind++)
        if (!libssh2_session_startup(session, sock))break;
    if(ind==5)
    {

        fprintf(stderr, "Nie udało się nawiązać sesji SSH\n");

    return-1;
    }
    }
    fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5);
    /* check what authentication methods are available */
    userauthlist = libssh2_userauth_list(session, configusername,
strlen(configusername));
    //printf("Authentication methods: %s\n", userauthlist);
    if (strstr(userauthlist, "password") != NULL) {
        auth_pw |= 1;
    }
    if (strstr(userauthlist, "keyboard-interactive") != NULL) {
        auth_pw |= 2;
    }
    if (strstr(userauthlist, "publickey") != NULL) {
        auth_pw |= 4;
    }

    if (auth_pw & 1) {
        /* We could authenticate via password */
        if (libssh2_userauth_password(session, configusername,
configpassword)) {
            printf("\nNieprawidłowy login lub hasło!\n");

            return -2; /*goto shutdown;*/
        } else {
 // printf("\tAuthentication by password succeeded.\n");
        }
    } else if (auth_pw & 2) {
        /* Or via keyboard-interactive */
        if (libssh2_userauth_keyboard_interactive(session, configusername,
&kbd_callback) ) {
            printf("\tAuthentication by keyboard-interactive failed!\n");

            return -2; /*goto shutdown;*/
        } else {
            printf("\tAuthentication by keyboard-interactive succeeded.\n");
        }
    } else if (auth_pw & 4) {
        /* Or by public key */
        if (libssh2_userauth_publickey_fromfile(session, configusername,
keyfile1, keyfile2, configpassword)) {
            printf("\tAuthentication by public key failed!\n");

            return -2; /*goto shutdown;*/
        } else {
            printf("\tAuthentication by public key succeeded.\n");
        }
    } else {
        printf("No supported authentication methods found!\n");

        return -2; /*goto shutdown;*/
    }

   /* Request a shell */
    if (!(channel = libssh2_channel_open_session(session))) {
        fprintf(stderr, "Unable to open a session\n");

        return -2; /*goto shutdown;*/
    }

// libssh2_channel_setenv(channel, "FOO", "bar");

    /*
     * See /etc/termcap for more options
     */
    char *termtype;
    termtype = getenv("TERM");

    if (libssh2_channel_request_pty(channel, "vt102")) {
        fprintf(stderr, "Failed requesting pty\n");

        return -3; /*goto skip_shell;*/
    }

    /* Open a SHELL on that pty */
    if (libssh2_channel_shell(channel)) {
        fprintf(stderr, "Unable to request shell on allocated pty\n");

        return -2; /*goto shutdown;*/
    }

*chanel=channel;
*sesion=session;
return 1;

}

int mainloop(LIBSSH2_CHANNEL *channel)
{
char schelout[2*BUFFSIZE];
char c[2];
int readlen,flags;

            /*set stdin nonblockign*/
    flags = fcntl(0, F_GETFL, 0);
     flags |= O_NONBLOCK;
     fcntl(0, F_SETFL, flags);
            /*set ssh channel nonblockign*/
    libssh2_channel_set_blocking(channel, 0);
    libssh2_channel_handle_extended_data2(channel,
LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE);

    /*set getch noecho*/

     struct termios attrs,oldattrs;
       tcgetattr( 0, &attrs );
    tcgetattr( 0, &oldattrs );
     attrs.c_cc[VINTR] = 0;
    attrs.c_cc[VSUSP] = 0;
    tcsetattr( 0, 0, &attrs );

int i=0;
initscr();
    while(1) /*main loop*/
    {
        libssh2_channel_flush_ex(channel,LIBSSH2_CHANNEL_FLUSH_ALL);
        /*reading*/
        for(i=0;i<BUFFSIZE;i++)schelout[i]=0;
        readlen=libssh2_channel_read(channel,schelout,HALFBUFFSIZE);
        if(readlen>0)
        {
            printf("%s",schelout);
            fflush(stdout);
        }
        /*writing*/
        c[0]=getch();
        c[1]='\0';
        if(c[0]!=-1)
        {
            libssh2_channel_write(channel,c,strlen(c));
            libssh2_channel_flush(channel);
        }
if(libssh2_channel_eof(channel)==1)break;
    }

    flags = fcntl(0, F_GETFL, 0); /*reseting terminal configuration*/
    flags &= ~O_NONBLOCK;
    fcntl(0, F_SETFL, flags);
    tcsetattr( 0, 0, &oldattrs );
return 1;
}

int main(int argc, char* argv[])
{

int sock;
char tekst[128];

session=NULL;
channel=NULL;
sock=0;

if(connection(&sock)==-1)
{
exit(1);
}
if (makeconnection(&session,&channel,&sock)==1)
{
    system("clear");
    mainloop(channel);
}
else
{
/*else faild to connect*/
    getchar();

}
/*disconnection*/
    if (channel) {
        libssh2_channel_free(channel);
        channel = NULL;
    }

if(session)
{
    libssh2_session_disconnect(session, "Normal Shutdown, Thank you for
playing");
    libssh2_session_free(session);
}
if(sock)
{
    close(sock);
}
    return 0;
}

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2011-02-23