示例#1
0
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);
}
示例#2
0
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;
}
示例#3
0
/*
 * 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);
}