Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The key to making libssh2 port forwarding work was discovering that it basically just gives you the data that came in to that port. You have to actually send the data onto a local port that you open:</p> <p>(Note, this code is not yet complete, there is no error checking, and the thread yielding isn't correct, but it gives a general outline of how to accomplish this.)</p> <pre><code>void reverse_port_forward(CMainDlg* dlg, addrinfo * hubaddr, std::string username, std::string password, int port) { int iretval; unsigned long mode = 1; int last_socket_err = 0; int other_port = 0; fd_set read_set, write_set; SOCKET sshsock = socket(AF_INET, SOCK_STREAM, 0); iretval = connect(sshsock, hubaddr-&gt;ai_addr, hubaddr-&gt;ai_addrlen); if (iretval != 0) ::PostQuitMessage(0); LIBSSH2_SESSION * session = NULL; session = libssh2_session_init(); iretval = libssh2_session_startup(session, sshsock); if (iretval) ::PostQuitMessage(0); iretval = libssh2_userauth_password(session, username.c_str(), password.c_str()); dlg-&gt;m_track_status(dlg, 1, 0, "Authorized"); LIBSSH2_LISTENER* listener = NULL; listener = libssh2_channel_forward_listen_ex(session, "127.0.0.1", port, &amp;other_port, 1); if (!listener) ::PostQuitMessage(0); LIBSSH2_CHANNEL* channel = NULL; ioctlsocket(sshsock, FIONBIO, &amp;mode); libssh2_session_set_blocking(session, 0); // non-blocking int err = LIBSSH2_ERROR_EAGAIN; while (err == LIBSSH2_ERROR_EAGAIN) { channel = libssh2_channel_forward_accept(listener); if (channel) break; err = libssh2_session_last_errno(session); boost::this_thread::yield(); } if (channel) { char buf[MAX_BUF_LEN]; char* chunk; long bytes_read = 0; long bytes_written = 0; int total_set = 0; timeval wait; wait.tv_sec = 0; wait.tv_usec = 2000; sockaddr_in localhost; localhost.sin_family = AF_INET; localhost.sin_addr.s_addr = inet_addr("127.0.0.1"); localhost.sin_port = htons(5900); SOCKET local_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ioctlsocket(local_sock, FIONBIO, &amp;mode); iretval = connect(local_sock, (sockaddr*) &amp;localhost, sizeof(localhost) ); if (iretval == SOCKET_ERROR) iretval = WSAGetLastError(); while (1) { bytes_read = libssh2_channel_read(channel, buf, MAX_BUF_LEN); if (bytes_read &gt;= 0){ FD_ZERO(&amp;read_set); FD_ZERO(&amp;write_set); FD_SET(local_sock, &amp;write_set); // wait until the socket can be written to while (select(0, &amp;read_set, &amp;write_set, NULL, &amp;wait) &lt; 1) boost::this_thread::yield(); if (FD_ISSET(local_sock, &amp;write_set)) { FD_CLR(local_sock, &amp;write_set); chunk = buf; // everything may not get written in this call because we're non blocking. So // keep writing more data until we've emptied the buffer pointer. while ((bytes_written = send(local_sock, chunk, bytes_read, 0)) &lt; bytes_read) { // if it couldn't write anything because the buffer is full, bytes_written // will be negative which won't help our pointer math much if (bytes_written &gt; 0) { chunk = buf + bytes_written; bytes_read -= bytes_written; if (bytes_read == 0) break; } FD_ZERO(&amp;read_set); FD_ZERO(&amp;write_set); FD_SET(local_sock, &amp;write_set); // wait until the socket can be written to while (select(0, &amp;read_set, &amp;write_set, NULL, &amp;wait) &lt; 1) boost::this_thread::yield(); } } } FD_ZERO(&amp;read_set); FD_ZERO(&amp;write_set); FD_SET(local_sock, &amp;read_set); select(0, &amp;read_set, &amp;write_set, NULL, &amp;wait); if (FD_ISSET(local_sock, &amp;read_set)) { FD_CLR(local_sock, &amp;read_set); bytes_read = recv(local_sock, buf, MAX_BUF_LEN, 0); if (bytes_read &gt;= 0) { while ((bytes_written = libssh2_channel_write_ex(channel, 0, buf, bytes_read)) == LIBSSH2_ERROR_EAGAIN) boost::this_thread::yield(); } } boost::this_thread::yield(); } // while } // if channel } </code></pre> <p>P.S. To make this work requires the latest SVN builds of libssh2. There were bugs in prior versions that kept port forwarding from being usable.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload