/** * Get somethin with IO. * * @param conn The connection to lldpd. * @param state_send State to be when "sending" * @param state_recv State to be when "receiving" * @param state_data Ancillary data for state handling * @param type Type of message to send (and receive) * @param to_send Data to send. * @param mi_send Marshalling info for data to send. * @param to_recv Data to receive. * @param mi_recv Marshalling info for data to recive. * @return 0 in case of success, a negative integer in case of failure. * * The current state must match one of @c CONN_STATE_IDLE, @c state_send or @c * state_recv and in the two later cases, the provided @c state_data must match. */ int _lldpctl_do_something(lldpctl_conn_t *conn, int state_send, int state_recv, const char *state_data, enum hmsg_type type, void *to_send, struct marshal_info *mi_send, void **to_recv, struct marshal_info *mi_recv) { ssize_t rc; if (conn->state == CONN_STATE_IDLE) { /* We need to build the message to send, then send * it. */ if (ctl_msg_send_unserialized(&conn->output_buffer, &conn->output_buffer_len, type, to_send, mi_send) != 0) return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); conn->state = state_send; if (state_data) conn->state_data = strdup(state_data); } if (conn->state == state_send && (state_data == NULL || !strcmp(conn->state_data, state_data))) { /* We need to send the currently built message */ rc = lldpctl_send(conn); if (rc < 0) return SET_ERROR(conn, rc); conn->state = state_recv; } if (conn->state == state_recv && (state_data == NULL || !strcmp(conn->state_data, state_data))) { /* We need to receive the answer */ while ((rc = ctl_msg_recv_unserialized(&conn->input_buffer, &conn->input_buffer_len, type, to_recv, mi_recv)) > 0) { /* We need more bytes */ rc = _lldpctl_needs(conn, rc); if (rc < 0) return SET_ERROR(conn, rc); } if (rc < 0) return SET_ERROR(conn, LLDPCTL_ERR_SERIALIZATION); /* rc == 0 */ conn->state = CONN_STATE_IDLE; free(conn->state_data); conn->state_data = NULL; return 0; } else return SET_ERROR(conn, LLDPCTL_ERR_INVALID_STATE); }
int lldpctl_watch(lldpctl_conn_t *conn) { int rc = 0; RESET_ERROR(conn); if (conn->state != CONN_STATE_IDLE) return SET_ERROR(conn, LLDPCTL_ERR_INVALID_STATE); conn->watch_triggered = 0; while (!conn->watch_triggered) { rc = _lldpctl_needs(conn, 1); if (rc < 0) return SET_ERROR(conn, rc); } RESET_ERROR(conn); return 0; }