#285: multithread calls libssh2.a error
-----------------------------------------------------+--------------------
Reporter: beiguan001 | Owner:
Type: defect | Status: new
Priority: high | Milestone: 1.4.3
Component: API | Version: 1.4.2
Keywords: multi-thread libssh2_session_handshake | Blocked By:
Blocks: |
-----------------------------------------------------+--------------------
When using multiple threads, in libssh2_session_handshake abnormal.
If you do not multi-threaded, no problem.
How to use multi-thread calls libssh2?
//////////// main cpp//////////
void* work_thread(void* arg)
{
string ipaddr = "132.31.0.13";
string user = "user";
string passwd = "pass";
int port = 22;
Ssh2Client ssh3;
ssh3.setHost(ipaddr.c_str(), user.c_str(), passwd.c_str(), port);
ssh3.setTimeOut(10000L);//10s
if(ssh3.ssh2_connect() < 0)
cout << "Error : connect error!" << endl;
if(ssh3.ssh2_open_session() < 0)
{
cout << "Error : ssh2_open_session error!" << endl;
exit(0);
}
}
int main(int argc,char* argv[])
{
int nthread = 1;
pthread_t tid;
for(int i=0;i<nthread;i++)
{
pthread_create(&tid,NULL,work_thread,NULL);
}
}
//////////////////////Ssh2Client.cpp
void Ssh2Client::setHost(const char *host, const char *user, const char
*passwd, int pt)
{
hostname = host;
username = user;
password = passwd;
port = pt;
}
int Ssh2Client::ssh2_connect()
{
int rc = 0;
unsigned long hostaddr;
struct sockaddr_in sin;
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
#endif
rc = libssh2_init(0);
if (rc != 0)
{
sprintf(errmsg, "libssh2 initialization failed (%d)\n",
rc);
return -1;
}
thread_setup();
hostaddr = inet_addr(hostname);
sock = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct
sockaddr_in)) != 0)
{
sprintf(errmsg, "failed to connect!\n");
return -1;
}
return 0;
}
int Ssh2Client::ssh2_open_session()
{
int rc = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;
const char *fingerprint;
/* Create a session instance */
session = libssh2_session_init();
if (!session)
return -1;
// libssh2_session_set_timeout(session, timeout);
/* tell libssh2 we want it all done non-blocking */
// libssh2_session_set_blocking(session, block);
/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_handshake(session, sock)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc)
{
printf("File = %s, Line = %d, rc = %d\n", __FILE__, __LINE__, rc);
sprintf(errmsg, "Failure establishing SSH session: %d\n", rc);
return -1;
}
nh = libssh2_knownhost_init(session);
if(!nh) {
/* eeek, do cleanup here */
return -2;
}
/* read all hosts from here */
libssh2_knownhost_readfile(nh, "known_hosts",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
/* store all known hosts to here */
libssh2_knownhost_writefile(nh, "dumpfile",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);
fingerprint = libssh2_session_hostkey(session, &len, &type);
if(fingerprint) {
struct libssh2_knownhost *host;
#if LIBSSH2_VERSION_NUM >= 0x010206
/* introduced in 1.2.6 */
int check = libssh2_knownhost_checkp(nh, hostname, 22,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#else
/* 1.2.5 or older */
int check = libssh2_knownhost_check(nh, hostname,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#endif
sprintf(errmsg, "Host check: %d, key: %s\n", check,
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");
/*****
* At this point, we could verify that 'check' tells us the key is
* fine or bail out.
*****/
}
else {
/* eeek, do cleanup here */
return -3;
}
libssh2_knownhost_free(nh);
if ( strlen(password) != 0 ) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username,
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc)
{
sprintf(errmsg, "Authentication by password failed.\n");
ssh2_free_session();
ssh2_close();
return -1;
}
}
else {
/* Or by public key */
char *home = getenv("HOME");
if(home == NULL)
{
sprintf(errmsg,"HOME not defined\n");
return -1;
}
char path1[1024];
char path2[1024];
strcat(path1,home);
strcat(path1,"/.ssh/id_rsa.pub");
strcat(path2,home);
strcat(path2,"/.ssh/id_rsa");
free(home);
while ((rc =
libssh2_userauth_publickey_fromfile(session,username,path1,path2,password))
==
LIBSSH2_ERROR_EAGAIN);
if (rc)
{
sprintf(errmsg, "\tAuthentication by public key failed\n");
ssh2_free_session();
ssh2_close();
return -1;
}
}
return 0;
}
///////////////////////////////////////////////////////
-- Ticket URL: <https://trac.libssh2.org/ticket/285> libssh2 <https://trac.libssh2.org/> C library for writing portable SSH2 clients _______________________________________________ libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-develReceived on 2014-02-11