Skip to content

Commit

Permalink
Adding src/transport.c for the SECSH transport layer read/write in a …
Browse files Browse the repository at this point in the history
…non-

blocking way. The channel code is now responsible for enabling/disabling
blocking status and to work with it.

I've also modified indenting and fixed compiler warnings at places, and
added a bunch of new examples in example/simple that I've used to verify that
the code still runs like before.

libssh2_channel_{read|write}nb_ex() and libssh2_sftp_{read|write}nb() are the
four new functions that supposedly work non-blocking.
  • Loading branch information
bagder committed Feb 2, 2007
1 parent c63ef86 commit 9d55db6
Show file tree
Hide file tree
Showing 22 changed files with 3,801 additions and 2,557 deletions.
11 changes: 1 addition & 10 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
AUTOMAKE_OPTIONS = foreign nostdinc

SUBDIRS = src tests
SUBDIRS = src example tests

include_HEADERS = include/libssh2.h include/libssh2_publickey.h \
include/libssh2_sftp.h

# and a sample tool
noinst_PROGRAMS = ssh2_sample

INCLUDES = -I$(top_srcdir)/include

ssh2_sample_SOURCES = ssh2_sample.c

ssh2_sample_LDADD = src/libssh2.la

EXTRA_DIST = LICENSE win32

ACLOCAL_AMFLAGS = -I m4
6 changes: 4 additions & 2 deletions configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ AC_ARG_ENABLE(debug-errors,
AC_HELP_STRING([--enable-debug-errors],[Output failure events to stderr]),
[AC_DEFINE(LIBSSH2_DEBUG_ERRORS, 1, [Output failure events to stderr])])
AC_ARG_ENABLE(debug-all,
AC_HELP_STRING([--enable-debug-all],[Output debugging info for all layers to stderr]),
AC_HELP_STRING([--enable-debug],[Enable debug]),
[
AC_DEFINE(LIBSSH2_DEBUG_TRANSPORT, 1, [Output transport layer debugging info to stderr])
AC_DEFINE(LIBSSH2_DEBUG_KEX, 1, [Output Key Exchange debugging info to stderr])
Expand Down Expand Up @@ -273,5 +273,7 @@ AC_C_INLINE

AC_CONFIG_FILES([Makefile
src/Makefile
tests/Makefile])
tests/Makefile
example/Makefile
example/simple/Makefile])
AC_OUTPUT
2 changes: 2 additions & 0 deletions example/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
AUTOMAKE_OPTIONS = foreign nostdinc
SUBDIRS = simple
17 changes: 17 additions & 0 deletions example/simple/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
AUTOMAKE_OPTIONS = foreign nostdinc

# samples
noinst_PROGRAMS = ssh2 scp_nonblock sftp_nonblock sftp scp

INCLUDES = -I$(top_srcdir)/include
LDADD = $(top_builddir)/src/libssh2.la

ssh2_SOURCES = ssh2.c

sftp_SOURCES = sftp.c

scp_nonblock_SOURCES = scp_nonblock.c

sftp_nonblock_SOURCES = sftp_nonblock.c

scp_SOURCES = scp.c
193 changes: 193 additions & 0 deletions example/simple/scp_nonblock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* $Id: scp_nonblock.c,v 1.1 2007/02/02 16:21:20 bagder Exp $
*
* Sample showing how to do SCP transfers in a non-blocking manner.
*/

#include <libssh2.h>

#ifndef WIN32
# include <netinet/in.h>
# include <sys/socket.h>
# include <unistd.h>
#else
# include <winsock2.h>
#endif

#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>

int main(int argc, char *argv[])
{
int sock, i, auth_pw = 1;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
char *username=(char *)"username";
char *password=(char *)"password";
char *scppath=(char *)"/tmp/TEST";
struct stat fileinfo;
int rc;
off_t got=0;

#ifdef WIN32
WSADATA wsadata;

WSAStartup(WINSOCK_VERSION, &wsadata);
#endif

/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the
* connection
*/
sock = socket(AF_INET, SOCK_STREAM, 0);

sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = htonl(0x7F000001);
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) {
fprintf(stderr, "failed to connect!\n");
return -1;
}

/* We set the socket non-blocking. We do it after the connect just to
simplify the example code. */
#ifdef F_SETFL
/* FIXME: this can/should be done in a more portable manner */
rc = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, rc | O_NONBLOCK);
#else
#error "add support for setting the socket non-blocking here"
#endif

/* Create a session instance
*/
session = libssh2_session_init();
if(!session)
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, "Failure establishing 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_MD5);
printf("Fingerprint: ");
for(i = 0; i < 16; i++) {
printf("%02X ", (unsigned char)fingerprint[i]);
}
printf("\n");

if(argc > 1) {
username = argv[1];
}
if(argc > 2) {
password = argv[2];
}
if(argc > 3) {
scppath = argv[3];
}

if (auth_pw) {
/* We could authenticate via password */
if (libssh2_userauth_password(session, username, password)) {
printf("Authentication by password failed.\n");
goto shutdown;
}
} else {
/* Or by public key */
if (libssh2_userauth_publickey_fromfile(session, username,
"/home/username/.ssh/id_rsa.pub",
"/home/username/.ssh/id_rsa",
password)) {
printf("\tAuthentication by public key failed\n");
goto shutdown;
}
}

/* Request a file via SCP */
channel = libssh2_scp_recv(session, scppath, &fileinfo);

if (!channel) {
fprintf(stderr, "Unable to open a session\n");
goto shutdown;
}
fprintf(stderr, "libssh2_scp_recv() is done, now receive data!\n");

while(got < fileinfo.st_size) {
char mem[1000];

struct timeval timeout;
int rc;
fd_set fd;

do {
int amount=sizeof(mem);

if((fileinfo.st_size -got) < amount) {
amount = fileinfo.st_size -got;
}

/* loop until we block */
rc = libssh2_channel_readnb(channel, mem, amount);
if(rc > 0) {
write(2, mem, rc);
got += rc;
}
} while (rc > 0);

if(rc == LIBSSH2CHANNEL_EAGAIN) {
/* this is due to blocking that would occur otherwise
so we loop on this condition */

timeout.tv_sec = 10;
timeout.tv_usec = 0;

FD_ZERO(&fd);

FD_SET(sock, &fd);

rc = select(sock+1, &fd, &fd, NULL, &timeout);
if(rc <= 0) {
/* negative is error
0 is timeout */
fprintf(stderr, "SCP timed out: %d\n", rc);
}
continue;
}
break;
}

libssh2_channel_free(channel);
channel = NULL;

shutdown:

libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);

#ifdef WIN32
Sleep(1000);
closesocket(sock);
#else
sleep(1);
close(sock);
#endif
printf("all done\n");
return 0;
}
5 changes: 4 additions & 1 deletion example/simple/sftp.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* $Id: sftp.c,v 1.1 2007/01/24 14:15:36 bagder Exp $
* $Id: sftp.c,v 1.2 2007/02/02 16:21:20 bagder Exp $
*
* Sample showing how to do SFTP transfers.
*/
Expand Down Expand Up @@ -109,13 +109,15 @@ int main(int argc, char *argv[])
}
}

fprintf(stderr, "libssh2_sftp_init()!\n");
sftp_session = libssh2_sftp_init(session);

if (!sftp_session) {
fprintf(stderr, "Unable to init SFTP session\n");
goto shutdown;
}

fprintf(stderr, "libssh2_sftp_open()!\n");
/* Request a file via SFTP */
sftp_handle =
libssh2_sftp_open(sftp_session, sftppath, LIBSSH2_FXF_READ, 0);
Expand All @@ -129,6 +131,7 @@ int main(int argc, char *argv[])
char mem[512];

/* loop until we fail */
fprintf(stderr, "libssh2_sftp_read()!\n");
rc = libssh2_sftp_read(sftp_handle, mem, sizeof(mem));
if(rc > 0) {
write(2, mem, rc);
Expand Down
Loading

0 comments on commit 9d55db6

Please sign in to comment.