void mov::qt::sftp_class::slotLogin() {
struct addrinfo hint;
struct addrinfo *addrs;
struct sockaddr_in *sin;
const char *fingerprint;
struct addrinfo *p;
int ret;
bool found;
sftpError = sftp_error::no;
if (sftpState == sftp_state::ready && Auth->authState == auth_state::ok) {
// инициализация библиотеки
if (libssh2_init(0) != 0) {
sftpError = sftp_error::libssh2_error;
return;
}
// поиск адреса хоста
memset(&hint, 0, sizeof(hint));
hint.ai_flags = AI_NUMERICHOST;
hint.ai_family = AF_UNSPEC;
hint.ai_socktype = SOCK_STREAM;
hint.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
if (ret == EAI_NONAME) {
hint.ai_flags = 0;
ret = getaddrinfo(Host.toLocal8Bit().data(), NULL, &hint, &addrs);
}
if (ret != 0) {
sftpError = sftp_error::resolve_error;
goto cleanup_libssh2_init;
}
found = false;
for (p = addrs; p != nullptr; p = p->ai_next) {
if (p->ai_family == AF_INET) {
found = true;
sin = reinterpret_cast(p->ai_addr);
break;
}
}
if (!found) {
sftpError = sftp_error::ip4_error;
goto cleanup_libssh2_init;
}
// создание сокета
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
sftpError = sftp_error::socket_error;
goto cleanup_libssh2_init;
}
sin->sin_family = AF_INET;
sin->sin_port = htons(Port);
// коннект
ret = ::connect(sock, (struct sockaddr *)(sin), sizeof(struct sockaddr_in));
if (ret != 0) {
sftpError = sftp_error::connect_error;
goto cleanup_socket;
}
//======================Было=============================================
// создание сессии
// session = libssh2_session_init();
// if (!session) {
// sftpError = sftp_error::session_error;
// goto cleanup_socket;
// }
// // установка баннера
// if (libssh2_session_banner_set(session, "SSH-2.0-OpenSSH_LIBSSH2_1.9.0") != 0) {
// sftpError = sftp_error::session_error;
// goto cleanup_session;
// }
// // рукопожатие
// if (libssh2_session_handshake(session, sock)) {
// sftpError = sftp_error::handshake_error;
// goto cleanup_session;
// }
// // перевод в неблокируемый режим
// libssh2_session_set_blocking(session, 0);
// получение отпечатка
//fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
// авторизация
// if (Auth->authType == auth_type::login) {
// while ((ret = libssh2_userauth_password(
// session,
// Auth->login.toLocal8Bit().data(),
// Auth->password.toLocal8Bit().data()
// )) == LIBSSH2_ERROR_EAGAIN);
// if (ret) {
// sftpError = sftp_error::auth_error;
// goto cleanup_session;
// }
// } else {
// while ((ret = libssh2_userauth_publickey_frommemory(
// session,
// Auth->login.toLocal8Bit().data(),
// Auth->login.length(),
// Auth->public_array.data(),
// Auth->public_array.size(),
// Auth->private_array.data(),
// Auth->private_array.size(),
// Auth->password.toLocal8Bit().data()
// )) == LIBSSH2_ERROR_EAGAIN);
// if (ret) {
// sftpError = sftp_error::auth_error;
// goto cleanup_session;
// }
// }
//=======================Стало============================================
try
{
SLibssh2_session session;
session.SetBanner("SSH-2.0-OpenSSH_LIBSSH2_1.9.0");
session.Handshake(sock);
session.SetBlocking(0);
fingerprint = HostKeyHash(LIBSSH2_HOSTKEY_HASH_SHA1);
if (Auth->authType == auth_type::login)
{
session.LoginByUserPwd(Auth->login.toLocal8Bit().data(), Auth->password.toLocal8Bit().data());
}
else
{
session.LoginByPublickey_frommemory(...);
}
}
catch(const char* error)
{
error;
}
//====================================================================
// инициализация ftp-сессии
do {
sftp_session = libssh2_sftp_init(session);
if (!sftp_session) {
if (libssh2_session_last_errno(session) == LIBSSH2_ERROR_EAGAIN)
waitsocket(sock, session);
else {
sftpError = sftp_error::auth_error;
goto cleanup_session;
}
}
} while (!sftp_session);
// все четко и дерзко
sftpState = sftp_state::logged_in;
return;
// аварийная очистка
// cleanup_session:
// libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing!");
// libssh2_session_free(session);
cleanup_socket:
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
cleanup_libssh2_init:
libssh2_exit();
}
}