server session BUGFIX check that all received SSH data were processed
Fixes #77
diff --git a/src/session_p.h b/src/session_p.h
index 7b135b4..7cb8427 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -558,7 +558,9 @@
* returned POLLIN.
*
* @param[in] session NETCONF session communicating on the socket.
- * @param[in,out] timeout Timeout for locking ti_lock.
+ * @param[in] timeout Timeout for locking ti_lock.
+ * @param[in] ssh_message Whether to also check for standard SSH messages or just do
+ * application data poll.
* @return NC_PSPOLL_TIMEOUT,
* NC_PSPOLL_RPC (has new data),
* NC_PSPOLL_PENDING (other channel has data),
@@ -567,7 +569,7 @@
* NC_PSPOLL_SSH_CHANNEL,
* NC_PSPOLL_ERROR.
*/
-int nc_ssh_pollin(struct nc_session *session, int timeout);
+int nc_ssh_pollin(struct nc_session *session, int timeout, int ssh_message);
void nc_server_ssh_clear_opts(struct nc_server_ssh_opts *opts);
diff --git a/src/session_server.c b/src/session_server.c
index a14ae73..faf5524 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -1196,7 +1196,7 @@
uint16_t j;
/* things are not that simple with SSH... */
- ret = nc_ssh_pollin(ps->sessions[i], timeout);
+ ret = nc_ssh_pollin(ps->sessions[i], timeout, 1);
/* clear POLLIN on sessions sharing this session's SSH session */
if (ret & (NC_PSPOLL_RPC | NC_PSPOLL_SSH_MSG | NC_PSPOLL_SSH_CHANNEL)) {
@@ -1291,6 +1291,17 @@
nc_server_rpc_free(rpc, server_opts.ctx);
+#ifdef NC_ENABLED_SSH
+ /* is there any data received but not processed? */
+ if (cur_session->ti_type == NC_TI_LIBSSH) {
+ /* ignore errors */
+ if (nc_ssh_pollin(cur_session, 0, 0) == NC_PSPOLL_RPC) {
+ ps->pfds[i].revents = POLLIN;
+ ret |= NC_PSPOLL_PENDING;
+ }
+ }
+#endif /* NC_ENABLED_SSH */
+
/* is there some other socket waiting? */
for (++i; i < ps->session_count; ++i) {
if (ps->pfds[i].revents) {
diff --git a/src/session_server_ssh.c b/src/session_server_ssh.c
index b6a7fc8..f10b8dc 100644
--- a/src/session_server_ssh.c
+++ b/src/session_server_ssh.c
@@ -1031,45 +1031,46 @@
}
int
-nc_ssh_pollin(struct nc_session *session, int timeout)
+nc_ssh_pollin(struct nc_session *session, int timeout, int ssh_message)
{
int ret;
struct nc_session *new;
- ret = nc_timedlock(session->ti_lock, timeout, __func__);
-
- if (ret < 0) {
- return NC_PSPOLL_ERROR;
- } else if (!ret) {
- return NC_PSPOLL_TIMEOUT;
- }
-
- ret = ssh_execute_message_callbacks(session->ti.libssh.session);
- pthread_mutex_unlock(session->ti_lock);
-
- if (ret != SSH_OK) {
- ERR("Session %u: failed to receive SSH messages (%s).", session->id,
- ssh_get_error(session->ti.libssh.session));
- session->status = NC_STATUS_INVALID;
- session->term_reason = NC_SESSION_TERM_OTHER;
- return NC_PSPOLL_SESSION_TERM | NC_PSPOLL_SESSION_ERROR;
- }
-
- /* new SSH message */
- if (session->flags & NC_SESSION_SSH_NEW_MSG) {
- session->flags &= ~NC_SESSION_SSH_NEW_MSG;
- if (session->ti.libssh.next) {
- for (new = session->ti.libssh.next; new != session; new = new->ti.libssh.next) {
- if ((new->status == NC_STATUS_STARTING) && new->ti.libssh.channel
- && (new->flags & NC_SESSION_SSH_SUBSYS_NETCONF)) {
- /* new NETCONF SSH channel */
- return NC_PSPOLL_SSH_CHANNEL;
- }
- }
+ if (ssh_message) {
+ ret = nc_timedlock(session->ti_lock, timeout, __func__);
+ if (ret < 0) {
+ return NC_PSPOLL_ERROR;
+ } else if (!ret) {
+ return NC_PSPOLL_TIMEOUT;
}
- /* just some SSH message */
- return NC_PSPOLL_SSH_MSG;
+ ret = ssh_execute_message_callbacks(session->ti.libssh.session);
+ pthread_mutex_unlock(session->ti_lock);
+
+ if (ret != SSH_OK) {
+ ERR("Session %u: failed to receive SSH messages (%s).", session->id,
+ ssh_get_error(session->ti.libssh.session));
+ session->status = NC_STATUS_INVALID;
+ session->term_reason = NC_SESSION_TERM_OTHER;
+ return NC_PSPOLL_SESSION_TERM | NC_PSPOLL_SESSION_ERROR;
+ }
+
+ /* new SSH message */
+ if (session->flags & NC_SESSION_SSH_NEW_MSG) {
+ session->flags &= ~NC_SESSION_SSH_NEW_MSG;
+ if (session->ti.libssh.next) {
+ for (new = session->ti.libssh.next; new != session; new = new->ti.libssh.next) {
+ if ((new->status == NC_STATUS_STARTING) && new->ti.libssh.channel
+ && (new->flags & NC_SESSION_SSH_SUBSYS_NETCONF)) {
+ /* new NETCONF SSH channel */
+ return NC_PSPOLL_SSH_CHANNEL;
+ }
+ }
+ }
+
+ /* just some SSH message */
+ return NC_PSPOLL_SSH_MSG;
+ }
}
/* no new SSH message, maybe NETCONF data? */