Denis Malyshkin | 1 Feb 2012 09:20
Favicon

Several direct_tcpip channels in one SSH session

Hi,

Is it possible to do opening of several direct_tcpip channels in one SSH 
session simultaneously (in async mode)?
I.e. to call libssh2_channel_direct_tcpip_ex(...) several times for one 
session without waiting while previous calls to it are completed.

For example, is it possible to write something like the next (it is just 
an example, not a compilable code):

list<channel_param> params;  // List of parameters for creating channels
while (!params.empty()) {
    for(list<channel_param>::iterator i = params.begin();  i != 
params.end();  ) {
        LIBSSH2_CHANNEL * channel = 
libssh2_channel_direct_tcpip_ex(session, i->host, i->port, ...);
        if (!channel) {
            if (last_error() != LIBSSH2_ERROR_EAGAIN) {
                // Error, respond to the caller, remove channel from the 
creation list.
                NotifyError(*i);
                i = params.erase(i);
            } else {
                ++i;
            }
        } else {
            // Channel created, respond to the caller, remove channel 
from the creation list.
            NotifyCreated(channel, *i);
            i = params.erase(i);
(Continue reading)

Mark Brand | 1 Feb 2012 09:40
Picon

libssh2 1.4.0 missing libssh_error() function?

Hi,

Just tried out the libssh2 1.4.0. When I try to link an application I 
get this error:

> libssh2.a(libgcrypt.o):libgcrypt.c:(.text+0xf8b): undefined reference 
> to `__libssh_error'

As far as I can tell, libssh_error() isn't defined in sources. Or am I 
overlooking something?

regards,

Mark
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Peter Stuge | 1 Feb 2012 09:49
Picon

Re: Several direct_tcpip channels in one SSH session

Denis Malyshkin wrote:
> Is it possible to do opening of several direct_tcpip channels in one SSH 
> session simultaneously (in async mode)?
> I.e. to call libssh2_channel_direct_tcpip_ex(...) several times for one 
> session without waiting while previous calls to it are completed.
..
> As I saw in the source code, channel_direct_tcpip(...) uses some
> variables in the 'session' structure (like session->direct_state, 
> session->direct_message and so on). So it seems that only one channel 
> creation call can be execute for a session at the moment. And the next 
> channel can be created only then a creation of the previous one is
> finished (successfully or with error). Is it correct?

Sure, it's pretty clear from the code and indeed your analysis.

The easy way out is to use blocking mode while creating the channels,
and switch to non-blocking only after they exist. This is what the
example/direct-tcpip.c demonstrates.

As an alternative, you can of course block in your code during
creation, and not create number two until the first channel is ready.
This is what you'll need to do if you already process other channels.

Finally, you can of course propose an improvement of the library. I
think it would be great to see an improvement in this area, and if
you come up with a nice solution for direct-tcpip channels then it
could also be applied to all other channel types.

Note that we want to reduce the number of malloc calls in libssh2.

(Continue reading)

Peter Stuge | 1 Feb 2012 09:56
Picon

Re: libssh2 1.4.0 missing libssh_error() function?

Mark Brand wrote:
> Just tried out the libssh2 1.4.0. When I try to link an application I get 
> this error:
>
>> libssh2.a(libgcrypt.o):libgcrypt.c:(.text+0xf8b): undefined reference to 
>> `__libssh_error'
>
> As far as I can tell, libssh_error() isn't defined in sources. Or am I 
> overlooking something?

>:(

commit 209de22299b4b58e582891dfba70f57e1e0492db
Author: Peter Krempa <pkrempa@...>
Date:   Mon Dec 19 15:02:15 2011 +0100

    userauth: Provide more informations if ssh pub key extraction fails

    If the function that extracts/computes the public key from a private key
    fails the errors it reports were masked by the function calling it. This
    patch modifies the key extraction function to return errors using
    _libssh_error() function.  The error messages are tweaked to contain
    reference to the failed operaton in addition to the reason.

Both the commit message and the code refer to the completely bogus
function name in one place. A few other places in the changed code
get it right.

Where is review before applying patches? wtf. I've pushed a fix for
this. I guess 1.4.1 would be in order.
(Continue reading)

Daniel Stenberg | 1 Feb 2012 13:22
Picon
Favicon
Gravatar

Re: libssh2 1.4.0 missing libssh_error() function?

On Wed, 1 Feb 2012, Peter Stuge wrote:

> Where is review before applying patches?

Everyone is welcome and encouraged to review them. I read the patches I apply 
and I also need to use my judgement and basic testing when accepting them. 
Sometimes that leads to broken builds like this when I've missed a flaw.

Evidently, not only me but not a single person built libssh2 from git with 
gcrypt for over a month before the release.

Getting a better and automated test system running would of course also be a 
good idea.

--

-- 

  / daniel.haxx.se
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Peter Stuge | 1 Feb 2012 14:06
Picon

Re: libssh2 1.4.0 missing libssh_error() function?

Daniel Stenberg wrote:
> Getting a better and automated test system running would of course
> also be a good idea.

Yes! Much much better for stuff like this!

I will set up Gerrit and Jenkins for libusb, once I've figured out
wrinkles I'm happy to duplicate also for libssh2. There will be a
Windows build environment as well.

//Peter
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Alexander Lamaison | 2 Feb 2012 01:42
Picon

SFTP issues

SFTP reading is completely broken for me in 1.4.0 (though it has been
for a while).  The last release that works for me is 1.2.7.

Some revisions cause a read with a buffer larger than 65-130k to
block.  Other revisions cause reads to return 0 prematurely indicating
the end of the file (usually around the 200k mark).  Recent revisions
do the latter.

Using my usual test script (attached) and git bisect I've narrowed
down the offending commits.  Apparently, premature EOF is caused by
03ca9020756a4e16f0294e5b35e9826ee6af2364 [1] and blocking is caused by
90b4b4073f34919aa72deff61a5c9bc188c47c95 [2].  It's difficult to know
how accurate these are as there were several overlapping, interacting
bugs and attempts to fix them that kept changing the SFTP behaviour.

This is all on Windows 7 64-bit.  To try the script yourself, run it as:
    libssh2_bigread ip_address username password path
If you run it with something like /dev/zero as the path, the expected
behaviour is that it will try reading from that path with increasing
buffer sizes up to about 8MB.

Daniel, liuzl: we went through this process in September and you guys
made some fixes which I though had solved it.  I've changed both the
Windows and Linux machines I'm testing on since then so I don't know
if that's why the problems are back.  I don't understand enough about
the SFTP layer to suggest a fix but, as usual, I'll happily test any
patches.

Alex

(Continue reading)

Peter Stuge | 2 Feb 2012 13:03
Picon

Re: SFTP issues

Hi Alex,

Alexander Lamaison wrote:
> SFTP reading is completely broken for me in 1.4.0 (though it has been
> for a while).  The last release that works for me is 1.2.7.

Bad. We need to fix this.

> Some revisions cause a read with a buffer larger than 65-130k to
> block.  Other revisions cause reads to return 0 prematurely indicating
> the end of the file (usually around the 200k mark).  Recent revisions
> do the latter.
> 
> Using my usual test script (attached) and git bisect I've narrowed
> down the offending commits.  Apparently, premature EOF is caused by
> 03ca9020756a4e16f0294e5b35e9826ee6af2364 [1] and blocking is caused by
> 90b4b4073f34919aa72deff61a5c9bc188c47c95 [2].  It's difficult to know
> how accurate these are as there were several overlapping, interacting
> bugs and attempts to fix them that kept changing the SFTP behaviour.
> 
> This is all on Windows 7 64-bit.  To try the script yourself, run it as:
>     libssh2_bigread ip_address username password path
> If you run it with something like /dev/zero as the path, the expected
> behaviour is that it will try reading from that path with increasing
> buffer sizes up to about 8MB.
> 
> Daniel, liuzl: we went through this process in September and you guys
> made some fixes which I though had solved it.  I've changed both the
> Windows and Linux machines I'm testing on since then so I don't know
> if that's why the problems are back.  I don't understand enough about
(Continue reading)

libssh2 Trac | 2 Feb 2012 19:16
Picon
Favicon

#235: [PATCH] Provide symbol versioning support

#235: [PATCH] Provide symbol versioning support
------------------------------------+--------------------
 Reporter:  crrodriguez.clavid.com  |       Owner:
     Type:  defect                  |      Status:  new
 Priority:  high                    |   Milestone:  1.4.0
Component:  API                     |     Version:  1.3.0
 Keywords:                          |  Blocked By:
   Blocks:                          |
------------------------------------+--------------------
 The attached patch provides support for symbol versioning if available, as
 well cleanup the symbol visibility support.

 This will fix a not-so-hypotethical scenario (aka.happends all the time
 with many different libraries) that breaks "always moving" linux
 distributions when upstream adds new functions without incrementing
 SOVERSION, resulting in inconsistent linkages, undefined symbols and
 broken user's systems.

--

-- 
Ticket URL: <http://trac.libssh2.org/ticket/235>
libssh2 <http://trac.libssh2.org/>
C library for writing portable SSH2 clients

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Gaurav Suryagandh | 3 Feb 2012 07:11
Picon

hi

Hello All,

I am trying to use libssh2_channel_direct_tcpip_ex() for setting up  the
channel.

I am able to get first request set correctly and getting right reply
from the http server which is running on different machine.

                <<========================================>> channel
machine A       <-----------------------------------------> machin B
(running apache)                                            (access web)

apache on 8080                                               mapped <at>
8083


I am using select to handle multiple request, but its not helping.
below is my code.

    rc = libssh2_init (0);

    if (rc != 0) {
        fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
        return 1;
    }

    /* Connect to SSH server */
    sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    sin.sin_family = AF_INET;
    if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(server_ip))) {
        perror("inet_addr");
        return -1;
    }
    sin.sin_port = htons(22);
    if (connect(sock, (struct sockaddr*)(&sin),
                sizeof(struct sockaddr_in)) != 0) {
        fprintf(stderr, "failed to connect!\n");
        return -1;
    }

    /* Create a session instance */
    session = libssh2_session_init();

    if(!session) {
        fprintf(stderr, "Could not initialize SSH session!\n");
        return -1;
    }

    /* ... start it up. This will trade welcome banners, exchange keys,
     *      * and setup crypto, compression, and MAC layers
     *           */
    rc = libssh2_session_startup(session, sock);

    if(rc) {
        fprintf(stderr, "Error when starting up SSH session: %d\n", rc);
        return -1;
    }

    /* At this point we havn't yet authenticated.  The first thing to do
     *      * is check the hostkey's fingerprint against our known hosts
Your app
     *           * may have it hard coded, may go to a file, may present
it to the
     *                * user, that's your call
     *                     */
    fingerprint = libssh2_hostkey_hash(session,
LIBSSH2_HOSTKEY_HASH_SHA1);

    fprintf(stderr, "Fingerprint: ");
    for(i = 0; i < 20; i++)
        fprintf(stderr, "%02X ", (unsigned char)fingerprint[i]);
    fprintf(stderr, "\n");

    /* check what authentication methods are available */
    userauthlist = libssh2_userauth_list(session, username,
strlen(username));

    printf("Authentication methods: %s\n", userauthlist);
    if (strstr(userauthlist, "password"))
        auth |= AUTH_PASSWORD;
    if (strstr(userauthlist, "publickey"))
        auth |= AUTH_PUBLICKEY;

    /* check for options */
    if(argc > 8) {
        if ((auth & AUTH_PASSWORD) && !strcasecmp(argv[8], "-p"))
            auth = AUTH_PASSWORD;
        if ((auth & AUTH_PUBLICKEY) && !strcasecmp(argv[8], "-k"))
            auth = AUTH_PUBLICKEY;
    }

    if (auth & AUTH_PASSWORD) {
        if (libssh2_userauth_password(session, username, password)) {

            fprintf(stderr, "Authentication by password failed.\n");
            goto shutdown;
        }
    } else if (auth & AUTH_PUBLICKEY) {
        if (libssh2_userauth_publickey_fromfile(session, username,
keyfile1,

                    keyfile2, password)) {
            printf("\tAuthentication by public key failed!\n");
            goto shutdown;
        }
        printf("\tAuthentication by public key succeeded.\n");
    } else {
        printf("No supported authentication methods found!\n");
        goto shutdown;
    }

    listensock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(local_listenport);
    if (INADDR_NONE == (sin.sin_addr.s_addr =
inet_addr(local_listenip))) {
        perror("inet_addr");
        goto shutdown;
    }
    sockopt = 1;
    setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &sockopt,
sizeof(sockopt));
    sinlen=sizeof(sin);
    if (-1 == bind(listensock, (struct sockaddr *)&sin, sinlen)) {
        perror("bind - 1 ");
        goto shutdown;
    }
    if (-1 == listen(listensock, 2)) {
        perror("listen");
        goto shutdown;
    }

    printf("Waiting for TCP connection on %s:%d...\n",
            inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));

    forwardsock = accept(listensock, (struct sockaddr *)&sin, &sinlen);
    if (-1 == forwardsock) {
        perror("accept");
        goto shutdown;
    }

    shost = inet_ntoa(sin.sin_addr);
    sport = ntohs(sin.sin_port);

    printf("Forwarding connection from %s:%d here to remote %s:%d\n",
shost,
            sport, remote_desthost, remote_destport);

    channel = libssh2_channel_direct_tcpip_ex(session, remote_desthost,

            remote_destport, shost, sport);
    if (!channel) {
        fprintf(stderr, "Could not open the direct-tcpip channel!\n"
                "(Note that this can be a problem at the server!"
                " Please review the server logs.)\n");
        goto shutdown;
    }

    /* Must use non-blocking IO hereafter due to the current libssh2 API
*/
    libssh2_session_set_blocking(session, 0);


    while (1) {
        FD_ZERO(&fds);
        FD_SET(forwardsock, &fds);
        tv.tv_sec = 0;
        tv.tv_usec = 100000;
        rc = select(forwardsock + 1, &fds, NULL, NULL, &tv);
        if (-1 == rc) {
            perror("select");
            goto shutdown;
        }
        if (rc && FD_ISSET(forwardsock, &fds)) {
            len = recv(forwardsock, buf, sizeof(buf), 0);
            if (len < 0) {
                perror("read");
                goto shutdown;
            } else if (0 == len) {
                printf("The client at %s:%d disconnected!\n", shost,
sport);
                goto shutdown;
            }
            wr = 0;
            do {
                i = libssh2_channel_write(channel, buf, len);

                if (i < 0) {
                    fprintf(stderr, "libssh2_channel_write: %d\n", i);
                    goto shutdown;
                }
                wr += i;
            } while(i > 0 && wr < len);
        }
        while (1) {
            len = libssh2_channel_read(channel, buf, sizeof(buf));

            if (LIBSSH2_ERROR_EAGAIN == len)
                break;
            else if (len < 0) {
                fprintf(stderr, "libssh2_channel_read: %d", (int)len);
                goto shutdown;
            }
            wr = 0;
            while (wr < len) {
                i = send(forwardsock, buf + wr, len - wr, 0);
                if (i <= 0) {
                    perror("write");
                    goto shutdown;
                }
                wr += i;
            }
            if (libssh2_channel_eof(channel)) {

                printf("The server at %s:%d disconnected!\n",
                        remote_desthost, remote_destport);
                goto shutdown;
            }
        }
    }

shutdown:
#ifdef WIN32
    closesocket(forwardsock);
    closesocket(listensock);
#else
    close(forwardsock);
    close(listensock);
#endif
    if (channel)
        libssh2_channel_free(channel);

    libssh2_session_disconnect(session, "Client disconnecting
normally");

    libssh2_session_free(session);


#ifdef WIN32
    closesocket(sock);
#else
    close(sock);
#endif

    libssh2_exit();


Please let me know if something is wrong with this code.

Thanks,
Gaurav




_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Gmane