static void mx_forwarder_close (mx_sock_t *msp) { mx_sock_forwarder_t *msfp = mx_sock(msp, MST_FORWARDER); mx_buffer_free(msfp->msf_rbufp); }
static int mx_channel_netconf_read_hello (mx_channel_t *mcp) { mx_buffer_t *mbp = mcp->mc_rbufp; int len; for (;;) { if (mbp->mb_start + mbp->mb_len == mbp->mb_size) { mx_buffer_t *newp = mx_buffer_create(0); if (newp == NULL) { mx_log("C%u cannot extend buffer", mcp->mc_id); return TRUE; } mbp->mb_next = newp; mbp = newp; } len = mx_channel_read(mcp, mbp->mb_data + mbp->mb_start + mbp->mb_len, mbp->mb_size - (mbp->mb_start + mbp->mb_len)); if (libssh2_channel_eof(mcp->mc_channel)) { DBG_POLL("C%u eof during read_hello", mcp->mc_id); return FALSE; } if (len == LIBSSH2_ERROR_EAGAIN) { /* Nothing to read, nothing to write; move on */ DBG_POLL("C%u is drained", mcp->mc_id); #if 0 break; #else sleep(1); continue; #endif } if (len < 0) return TRUE; mbp->mb_len += len; DBG_POLL("C%u read %d", mcp->mc_id, len); if (mx_channel_netconf_has_marker(mcp)) { mx_log("C%u found end-of-frame; len %lu, discarding", mcp->mc_id, mcp->mc_rbufp->mb_len); mbp->mb_len = mbp->mb_start = 0; if (mbp->mb_next) { mx_buffer_free(mbp->mb_next); mbp->mb_next = NULL; } return TRUE; } } return FALSE; }
/* * Detect if we have the NETCONF end-of-frame marker at the end * of our input stream. */ static int mx_channel_netconf_has_marker (mx_channel_t *mcp) { char *cp; char *zp; const char *czp; mx_buffer_t *prev = NULL, *cur = mcp->mc_rbufp; /* Find the previous buffer, if there is one */ while (cur->mb_next != NULL) { prev = cur; cur = cur->mb_next; } for (;;) { for (cp = cur->mb_data + cur->mb_start + cur->mb_len - 1; cp > cur->mb_data + cur->mb_start; cp--) if (!isspace((int) *cp)) goto found_end; if (prev == NULL) return FALSE; cur = prev; prev = NULL; } found_end: /* * We've found the last trailing non-ws char, so we need * to see if the previous bytes are the NETCONF framing * marker. The marker might span the last buffer and * the previous one, which is annoy to handle. */ if (cp - (cur->mb_data + cur->mb_start) > mx_netconf_marker_len) { zp = cp + 1 - mx_netconf_marker_len; if (0) mx_log("[%.*s] [%.*s]", mx_netconf_marker_len, zp, mx_netconf_marker_len, mx_netconf_marker); if (memcmp(zp, mx_netconf_marker, mx_netconf_marker_len) == 0) { /* * Mark the new end of the string, discarding the * marker and and trailing whitespace. */ *zp = '\0'; /* Shouldn't matter, but ... */ cur->mb_len = zp - (cur->mb_data + cur->mb_start); if (cur->mb_next) { /* If the next buffer is empty, free it */ mx_buffer_free(cur->mb_next); cur->mb_next = NULL; } return TRUE; } } else { int left = cp - (cur->mb_data + cur->mb_start); czp = mx_netconf_marker + mx_netconf_marker_len - left; if (memcmp(cp, czp, left) == 0) { if (prev) { left = mx_netconf_marker_len - left; if (memcmp(prev->mb_data + prev->mb_start + prev->mb_len - left, mx_netconf_marker, left) == 0) { prev->mb_len -= left; /* Shouldn't matter, but ... */ prev->mb_data[prev->mb_start + prev->mb_len] = '\0'; prev->mb_next = NULL; mx_buffer_free(cur); return TRUE; } } } } return FALSE; }