static enum xprt_stat Svctcp_stat(SVCXPRT * xprt) { register struct tcp_conn *cd = (struct tcp_conn *)(xprt->xp_p1); if(cd->strm_stat == XPRT_DIED) return (XPRT_DIED); if(!xdrrec_eof(&(cd->xdrs))) return (XPRT_MOREREQS); return (XPRT_IDLE); }
static enum xprt_stat svctcp_stat (SVCXPRT *xprt) { struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); if (cd->strm_stat == XPRT_DIED) return XPRT_DIED; if (!xdrrec_eof (&(cd->xdrs))) return XPRT_MOREREQS; return XPRT_IDLE; }
/* * ndmp_process_messages * * Reads the next message into the stream buffer. * Processes messages until the stream buffer is empty. * * This function processes all data in the stream buffer before returning. * This allows functions like poll() to be used to determine when new * messages have arrived. If only some of the messages in the stream buffer * were processed and then poll was called, poll() could block waiting for * a message that had already been received and read into the stream buffer. * * This function processes both request and reply messages. * Request messages are dispatched using the appropriate function from the * message handling table. * Only one reply messages may be pending receipt at a time. * A reply message, if received, is placed in connection->conn_msginfo * before returning to the caller. * Errors are reported if a reply is received but not expected or if * more than one reply message is received * * Parameters: * connection (input) - connection pointer. * reply_expected (output) - TRUE - a reply message is expected. * FALSE - no reply message is expected and * an error will be reported if a reply * is received. * * Returns: * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, * error processing reply message. * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, * reply seen. * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, * no reply seen. * NDMP_PROC_REP_ERR - error; connection no longer established. * * Notes: * If the peer is generating a large number of requests, a caller * looking for a reply will be blocked while the requests are handled. * This is because this function does not return until the stream * buffer is empty. * Code needs to be added to allow a return if the stream buffer * is not empty but there is data available on the socket. This will * prevent poll() from blocking and prevent a caller looking for a reply * from getting blocked by a bunch of requests. */ static int ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected) { msg_info_t reply_msginfo; boolean_t reply_read = FALSE; boolean_t reply_error = FALSE; int err; NDMP_LOG(LOG_DEBUG, "reply_expected: %s", reply_expected == TRUE ? "TRUE" : "FALSE"); (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t)); do { (void) memset((void *)&connection->conn_msginfo, 0, sizeof (msg_info_t)); if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { if (connection->conn_eof) { NDMP_LOG(LOG_DEBUG, "detected eof"); return (NDMP_PROC_ERR); } if (err < 1) { NDMP_LOG(LOG_DEBUG, "error decoding header"); /* * Error occurred decoding the header. * Don't send a reply since we don't know * the message or if the message was even * a request message. To be safe, assume * that the message was a reply if a reply * was expected. Need to do this to prevent * hanging ndmp_send_request() waiting for a * reply. Don't set reply_read so that the * reply will be processed if it is received * later. */ if (reply_read == FALSE) reply_error = TRUE; continue; } if (connection->conn_msginfo.mi_hdr.message_type != NDMP_MESSAGE_REQUEST) { NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", connection->conn_msginfo.mi_hdr.message); if (reply_expected == FALSE || reply_read == TRUE) NDMP_LOG(LOG_DEBUG, "Unexpected reply message: 0x%x", connection->conn_msginfo.mi_hdr. message); ndmp_free_message((ndmp_connection_t *) connection); if (reply_read == FALSE) { reply_read = TRUE; reply_error = TRUE; } continue; } NDMP_LOG(LOG_DEBUG, "received request: 0x%x", connection->conn_msginfo.mi_hdr.message); (void) ndmp_send_response((ndmp_connection_t *) connection, err, NULL); ndmp_free_message((ndmp_connection_t *)connection); continue; } if (connection->conn_msginfo.mi_hdr.message_type != NDMP_MESSAGE_REQUEST) { NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", connection->conn_msginfo.mi_hdr.message); if (reply_expected == FALSE || reply_read == TRUE) { NDMP_LOG(LOG_DEBUG, "Unexpected reply message: 0x%x", connection->conn_msginfo.mi_hdr.message); ndmp_free_message((ndmp_connection_t *) connection); continue; } reply_read = TRUE; reply_msginfo = connection->conn_msginfo; continue; } NDMP_LOG(LOG_DEBUG, "received request: 0x%x", connection->conn_msginfo.mi_hdr.message); /* * The following is needed to catch an improperly constructed * handler table or to deal with an NDMP client that is not * conforming to the negotiated protocol version. */ if (connection->conn_msginfo.mi_handler->mh_func == NULL) { NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x", connection->conn_msginfo.mi_hdr.message); (void) ndmp_send_response((ndmp_connection_t *) connection, NDMP_NOT_SUPPORTED_ERR, NULL); ndmp_free_message((ndmp_connection_t *)connection); continue; } /* * Call the handler function. * The handler will send any necessary reply. */ (*connection->conn_msginfo.mi_handler->mh_func) (connection, connection->conn_msginfo.mi_body); ndmp_free_message((ndmp_connection_t *)connection); } while (xdrrec_eof(&connection->conn_xdrs) == FALSE && connection->conn_eof == FALSE); NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer"); if (connection->conn_eof == TRUE) { if (reply_msginfo.mi_body) free(reply_msginfo.mi_body); return (NDMP_PROC_ERR); } if (reply_error) { if (reply_msginfo.mi_body) free(reply_msginfo.mi_body); return (NDMP_PROC_REP_ERR); } if (reply_read) { connection->conn_msginfo = reply_msginfo; return (NDMP_PROC_MSG); } return (NDMP_PROC_REP); }