Fixed Restconf nghttp2 client EPIPE crash
This commit is contained in:
parent
c3b120b364
commit
7b099a5685
2 changed files with 34 additions and 27 deletions
|
|
@ -358,9 +358,11 @@ native_buf_write(char *buf,
|
||||||
er = errno;
|
er = errno;
|
||||||
switch (SSL_get_error(ssl, len)){
|
switch (SSL_get_error(ssl, len)){
|
||||||
case SSL_ERROR_SYSCALL: /* 5 */
|
case SSL_ERROR_SYSCALL: /* 5 */
|
||||||
if (er == ECONNRESET) {/* Connection reset by peer */
|
if (er == ECONNRESET || /* Connection reset by peer */
|
||||||
if (ssl)
|
er == EPIPE) { /* Reading end of socket is closed */
|
||||||
|
if (ssl){
|
||||||
SSL_free(ssl);
|
SSL_free(ssl);
|
||||||
|
}
|
||||||
close(s);
|
close(s);
|
||||||
clixon_event_unreg_fd(s, restconf_connection);
|
clixon_event_unreg_fd(s, restconf_connection);
|
||||||
goto ok; /* Close socket and ssl */
|
goto ok; /* Close socket and ssl */
|
||||||
|
|
@ -812,6 +814,7 @@ restconf_http2_process(restconf_conn *rc,
|
||||||
int ret;
|
int ret;
|
||||||
nghttp2_error ngerr;
|
nghttp2_error ngerr;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if (rc->rc_exit){ /* Server-initiated exit for http/2 */
|
if (rc->rc_exit){ /* Server-initiated exit for http/2 */
|
||||||
if ((ngerr = nghttp2_session_terminate_session(rc->rc_ngsession, 0)) < 0){
|
if ((ngerr = nghttp2_session_terminate_session(rc->rc_ngsession, 0)) < 0){
|
||||||
clicon_err(OE_NGHTTP2, ngerr, "nghttp2_session_terminate_session %d", ngerr);
|
clicon_err(OE_NGHTTP2, ngerr, "nghttp2_session_terminate_session %d", ngerr);
|
||||||
|
|
@ -822,7 +825,7 @@ restconf_http2_process(restconf_conn *rc,
|
||||||
if ((ret = http2_recv(rc, (unsigned char *)buf, n)) < 0)
|
if ((ret = http2_recv(rc, (unsigned char *)buf, n)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
restconf_close_ssl_socket(rc, 1);
|
restconf_close_ssl_socket(rc, 0);
|
||||||
if (restconf_conn_free(rc) < 0)
|
if (restconf_conn_free(rc) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -839,6 +842,7 @@ restconf_http2_process(restconf_conn *rc,
|
||||||
}
|
}
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_LIBNGHTTP2 */
|
#endif /* HAVE_LIBNGHTTP2 */
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,10 @@ nghttp2_print_headers(nghttp2_nv *nva,
|
||||||
* `nghttp2_session_send()` to send data to the remote endpoint. If
|
* `nghttp2_session_send()` to send data to the remote endpoint. If
|
||||||
* the application uses solely `nghttp2_session_mem_send()` instead,
|
* the application uses solely `nghttp2_session_mem_send()` instead,
|
||||||
* this callback function is unnecessary.
|
* this callback function is unnecessary.
|
||||||
* XXX see buf_write
|
* It must return the number of bytes sent if it succeeds.
|
||||||
|
* If it cannot send any single byte without blocking,
|
||||||
|
* it must return :enum:`NGHTTP2_ERR_WOULDBLOCK`.
|
||||||
|
* For other errors, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
|
||||||
*/
|
*/
|
||||||
static ssize_t
|
static ssize_t
|
||||||
session_send_callback(nghttp2_session *session,
|
session_send_callback(nghttp2_session *session,
|
||||||
|
|
@ -162,24 +165,22 @@ session_send_callback(nghttp2_session *session,
|
||||||
int flags,
|
int flags,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
restconf_conn *rc = (restconf_conn *)user_data;
|
restconf_conn *rc = (restconf_conn *)user_data;
|
||||||
int er;
|
int er;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
ssize_t totlen = 0;
|
ssize_t totlen = 0;
|
||||||
int s;
|
int s;
|
||||||
SSL *ssl;
|
|
||||||
int sslerr;
|
int sslerr;
|
||||||
|
|
||||||
clicon_debug(1, "%s buflen:%zu", __FUNCTION__, buflen);
|
clicon_debug(1, "%s buflen:%zu", __FUNCTION__, buflen);
|
||||||
s = rc->rc_s;
|
s = rc->rc_s;
|
||||||
ssl = rc->rc_ssl;
|
|
||||||
while (totlen < buflen){
|
while (totlen < buflen){
|
||||||
if (ssl){
|
if (rc->rc_ssl){
|
||||||
if ((len = SSL_write(ssl, buf+totlen, buflen-totlen)) <= 0){
|
if ((len = SSL_write(rc->rc_ssl, buf+totlen, buflen-totlen)) <= 0){
|
||||||
er = errno;
|
er = errno;
|
||||||
sslerr = SSL_get_error(ssl, len);
|
sslerr = SSL_get_error(rc->rc_ssl, len);
|
||||||
clicon_debug(1, "%s errno:;%d sslerr:%d", __FUNCTION__, errno, sslerr);
|
clicon_debug(1, "%s errno:%d sslerr:%d", __FUNCTION__, errno, sslerr);
|
||||||
switch (sslerr){
|
switch (sslerr){
|
||||||
case SSL_ERROR_WANT_WRITE: /* 3 */
|
case SSL_ERROR_WANT_WRITE: /* 3 */
|
||||||
clicon_debug(1, "%s write SSL_ERROR_WANT_WRITE", __FUNCTION__);
|
clicon_debug(1, "%s write SSL_ERROR_WANT_WRITE", __FUNCTION__);
|
||||||
|
|
@ -187,12 +188,9 @@ session_send_callback(nghttp2_session *session,
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case SSL_ERROR_SYSCALL: /* 5 */
|
case SSL_ERROR_SYSCALL: /* 5 */
|
||||||
if (er == ECONNRESET) {/* Connection reset by peer */
|
if (er == ECONNRESET || /* Connection reset by peer */
|
||||||
if (ssl)
|
er == EPIPE) { /* Reading end of socket is closed */
|
||||||
SSL_free(ssl);
|
goto done; /* Cleanup in http2_recv() */
|
||||||
close(s);
|
|
||||||
// XXX clixon_event_unreg_fd(s, restconf_connection);
|
|
||||||
goto ok; /* Close socket and ssl */
|
|
||||||
}
|
}
|
||||||
else if (er == EAGAIN){
|
else if (er == EAGAIN){
|
||||||
/* same as want_write above, but different behaviour on different
|
/* same as want_write above, but different behaviour on different
|
||||||
|
|
@ -204,7 +202,7 @@ session_send_callback(nghttp2_session *session,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
clicon_err(OE_RESTCONF, er, "SSL_write %d", er);
|
clicon_err(OE_RESTCONF, er, "SSL_write %d", sslerr);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -247,7 +245,7 @@ session_send_callback(nghttp2_session *session,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
clicon_debug(1, "%s retval:%zd", __FUNCTION__, totlen);
|
clicon_debug(1, "%s retval:%zd", __FUNCTION__, totlen);
|
||||||
return totlen;
|
return retval == 0 ? totlen : retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Invoked when |session| wants to receive data from the remote peer.
|
/*! Invoked when |session| wants to receive data from the remote peer.
|
||||||
|
|
@ -481,7 +479,6 @@ http2_exec(restconf_conn *rc,
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
sd->sd_code = 404; /* not found */
|
sd->sd_code = 404; /* not found */
|
||||||
|
|
||||||
}
|
}
|
||||||
if (restconf_param_del_all(rc->rc_h) < 0) // XXX
|
if (restconf_param_del_all(rc->rc_h) < 0) // XXX
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -882,7 +879,7 @@ error_callback2(nghttp2_session *session,
|
||||||
* @param[in] buf Character buffer
|
* @param[in] buf Character buffer
|
||||||
* @param[in] n Lenght of buf
|
* @param[in] n Lenght of buf
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
* @retval 0 Invald request
|
* @retval 0 Invalid request
|
||||||
* @retval -1 Fatal error
|
* @retval -1 Fatal error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -918,11 +915,15 @@ http2_recv(restconf_conn *rc,
|
||||||
}
|
}
|
||||||
/* sends highest prio frame from outbound queue to remote peer. It does this as
|
/* sends highest prio frame from outbound queue to remote peer. It does this as
|
||||||
* many as possible until user callback :type:`nghttp2_send_callback` returns
|
* many as possible until user callback :type:`nghttp2_send_callback` returns
|
||||||
* * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
|
* :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
|
||||||
|
* @see session_send_callback()
|
||||||
*/
|
*/
|
||||||
|
clicon_err_reset();
|
||||||
if ((ngerr = nghttp2_session_send(rc->rc_ngsession)) != 0){
|
if ((ngerr = nghttp2_session_send(rc->rc_ngsession)) != 0){
|
||||||
clicon_err(OE_NGHTTP2, ngerr, "nghttp2_session_send");
|
if (clicon_errno)
|
||||||
goto done;
|
goto done;
|
||||||
|
else
|
||||||
|
goto fail; /* Not fatal error */
|
||||||
}
|
}
|
||||||
retval = 1; /* OK */
|
retval = 1; /* OK */
|
||||||
done:
|
done:
|
||||||
|
|
@ -943,6 +944,7 @@ http2_send_server_connection(restconf_conn *rc)
|
||||||
,{NGHTTP2_SETTINGS_ENABLE_PUSH, 0}};
|
,{NGHTTP2_SETTINGS_ENABLE_PUSH, 0}};
|
||||||
nghttp2_error ngerr;
|
nghttp2_error ngerr;
|
||||||
|
|
||||||
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
if ((ngerr = nghttp2_submit_settings(rc->rc_ngsession,
|
if ((ngerr = nghttp2_submit_settings(rc->rc_ngsession,
|
||||||
NGHTTP2_FLAG_NONE,
|
NGHTTP2_FLAG_NONE,
|
||||||
iv,
|
iv,
|
||||||
|
|
@ -956,6 +958,7 @@ http2_send_server_connection(restconf_conn *rc)
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue