[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
libssh questions
[Thread Prev] | [Thread Next]
- Subject: libssh questions
- From: Vishwanathan Chandru <vishwanathanc@xxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Mon, 9 Nov 2020 08:12:57 -0800
- To: libssh@xxxxxxxxxx
Hello, My name is Vish and I am a newbie to socket programming in general. This library was very easy to understand and made my life easier as I got curious about secure communications, so would like to thank the developers. I am trying to develop a peer to peer application using libssh (for learning sake). From the documentation it seems like using ssh_event_dopoll seems to be the way to go. There's also some aspect of non-secure communication with a local client and ssh_event_dopoll handles it fine. Here's what I am came up with for the server implementation: int process_call_back(socket_t fd, int revents, void* userdata) { if(revents & POLLIN) { // non libssh socket if(fd == normal_listener_socket_fd) { // accept and all. } if(fd == ssh_listener_socket) { // allocate session sd = accept(fd...) int rc = fcntl(sd, F_SETFL, O_NONBLOCK); ssh_bind_accept_fd(sshbind, session, new_sd); // one of these callbacks set the channel_data_function to keep track of data coming from ssh client via channels. ssh_callbacks_init(&cb); ssh_set_server_callbacks(session, &cb); ssh_callbacks_init(&scb); ssh_set_callbacks(session, &scb); if (ssh_handle_key_exchange(session)) { printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); } else { ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD); ssh_event_add_session(mainloop, session); } } else if(is_non_ssh_socket(fd)) { recv(fd) send(fd...) } } } int main() { // setup boilerplate if (ssh_bind_listen(sshbind) < 0) { printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); return 1; } ssh_listener_socket = ssh_bind_get_fd(sshbind); ssh_event_add_fd(mainloop, ssh_listener_socket, POLLIN, process_call_back, NULL); ssh_event_add_fd(mainloop, ssh_listener_socket, POLLPRI, process_call_back, NULL); do { if(ssh_event_dopoll(mainloop, -1)) == SSH_ERROR) { printf("\n something went wrong with errno %d ", errno); for(auto session : sessions) { // check if session is alive if(ssh_is_connected(session)) { continue; } else { auto emsg = ssh_get_error(session); auto ecode = ssh_get_error_code(session); // this session has gone to hell, take it out ssh_event_remove_session(mainloop, session); // more possible cleanup here. } } } } while (true) } Now this thing works. I was hoping to use incoming_connections callback on ssh_bind to accept incoming ssh connections but it didnt seem to work out. Is this the best way to achieve this? Second question is about handling timeouts and connection closures. I came across this thread https://www.libssh.org/archive/libssh/2019-03/0000011.html, which answered some questions. So I came up with do while loop style error handling, if ssh_event_dopoll returns error, loop through all the active sessions and remove the bad session using ssh_is_connected. Is there a better way to acheive the error handling? Third question is I also want to add the client part of the code (since this a peer to peer application). I understand that there is non blocking usage of ssh_connect. From what I can read in the documentation, I will have to call ssh_connect if SSH_AGAIN is returned and until it returns SSH_OK, I cannot proceed with the authentication step. Can I do something like this on a separate thread (the previous code snippet will be in the server thread)? ssh_session session; int session_fd = -1; int connected = 0; int process_call_back(socket_t fd, int revents, void* userdata) { if(revents & POLLOUT) { if(fd == session_fd) { int optval = 0; int optlen = sizeof(optval); int rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, optlen); if (optval == 0 ) { rc = ssh_connect(session); } if (rc == SSH_OK) { // remove the fd, because session callbacks will be added. ssh_event_remove_fd(mainloop, fd); // enable the blocking mode otherwise we have to call authentication // until it returns success. ssh_is_blocking(session, 1); // authenticate .... // set the channels and associate callbacks .... // add the session to event loop. ssh_event_add_session(mainloop, session); connected = 1; } } } } int main() { // boiler plate .... session = ssh_new(); ssh_set_blocking(session, 0); int rc = ssh_connect(session); if (rc == SSH_ERROR) { return 1; } if (rc == SSH_AGAIN) { session_fd = ssh_get_fd(session); // add POLLOUT for eastablishing connection ssh_event_add_fd(mainloop, session_fd, POLLOUT, process_call_back, NULL); } do { if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR) { break; } } while (!connected); // exchange buffers with server via channel read/write ... } Thanks and Best regards, Vish
Re: libssh questions | Vishwanathan Chandru <vishwanathanc@xxxxxxxxx> |