void* Entry() { while(!TestDestroy()) { // First, poll the channel int bytes = ssh_channel_poll_timeout(m_channel, 500, 0); if(bytes == SSH_ERROR) { // an error clCommandEvent event(wxEVT_SSH_CHANNEL_READ_ERROR); m_handler->AddPendingEvent(event); break; } else if(bytes == SSH_EOF) { clCommandEvent event(wxEVT_SSH_CHANNEL_CLOSED); m_handler->AddPendingEvent(event); break; } else if(bytes == 0) { continue; } else { // there is something to read char* buffer = new char[bytes + 1]; if(ssh_channel_read(m_channel, buffer, bytes, 0) != bytes) { clCommandEvent event(wxEVT_SSH_CHANNEL_READ_ERROR); m_handler->AddPendingEvent(event); wxDELETEA(buffer); break; } else { buffer[bytes] = 0; clCommandEvent event(wxEVT_SSH_CHANNEL_READ_OUTPUT); event.SetString(wxString(buffer, wxConvUTF8)); m_handler->AddPendingEvent(event); wxDELETEA(buffer); } } } return NULL; }
static void *nogvl_poll(void *ptr) { struct nogvl_poll_args *args = ptr; args->rc = ssh_channel_poll_timeout(args->channel, args->timeout, args->is_stderr); return NULL; }
/* return -1 means either poll error or that session was invalidated (socket error), EINTR is handled inside */ static int nc_read_poll(struct nc_session *session, int io_timeout) { sigset_t sigmask, origmask; int ret = -2; struct pollfd fds; if ((session->status != NC_STATUS_RUNNING) && (session->status != NC_STATUS_STARTING)) { ERR("Session %u: invalid session to poll.", session->id); return -1; } switch (session->ti_type) { #ifdef NC_ENABLED_SSH case NC_TI_LIBSSH: /* EINTR is handled, it resumes waiting */ ret = ssh_channel_poll_timeout(session->ti.libssh.channel, io_timeout, 0); if (ret == SSH_ERROR) { ERR("Session %u: SSH channel poll error (%s).", session->id, ssh_get_error(session->ti.libssh.session)); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } else if (ret == SSH_EOF) { ERR("Session %u: SSH channel unexpected EOF.", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } else if (ret > 0) { /* fake it */ ret = 1; fds.revents = POLLIN; } else { /* ret == 0 */ fds.revents = 0; } break; #endif #ifdef NC_ENABLED_TLS case NC_TI_OPENSSL: ret = SSL_pending(session->ti.tls); if (ret) { /* some buffered TLS data available */ ret = 1; fds.revents = POLLIN; break; } fds.fd = SSL_get_fd(session->ti.tls); #endif /* fallthrough */ case NC_TI_FD: if (session->ti_type == NC_TI_FD) { fds.fd = session->ti.fd.in; } fds.events = POLLIN; fds.revents = 0; sigfillset(&sigmask); pthread_sigmask(SIG_SETMASK, &sigmask, &origmask); ret = poll(&fds, 1, io_timeout); pthread_sigmask(SIG_SETMASK, &origmask, NULL); break; default: ERRINT; return -1; } /* process the poll result, unified ret meaning for poll and ssh_channel poll */ if (ret < 0) { /* poll failed - something really bad happened, close the session */ ERR("Session %u: poll error (%s).", session->id, strerror(errno)); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } else { /* status > 0 */ /* in case of standard (non-libssh) poll, there still can be an error */ if (fds.revents & POLLHUP) { ERR("Session %u: communication channel unexpectedly closed.", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_DROPPED; return -1; } if (fds.revents & POLLERR) { ERR("Session %u: communication channel error.", session->id); session->status = NC_STATUS_INVALID; session->term_reason = NC_SESSION_TERM_OTHER; return -1; } } return ret; }