#include <sys/un.h>
#include "lldpctl.h"
-#include "private.h"
+#include "atom.h"
#include "../compat/compat.h"
#include "../ctl.h"
#include "../log.h"
-#include "../lldpd-structs.h"
const char*
lldpctl_get_default_transport(void)
/* Connect to the remote end */
static int
-sync_connect()
+sync_connect(lldpctl_conn_t *lldpctl)
{
- return ctl_connect(LLDPD_CTL_SOCKET);
+ return ctl_connect(lldpctl->ctlname);
}
/* Synchronously send data to remote end. */
const uint8_t *data, size_t length, void *user_data)
{
struct lldpctl_conn_sync_t *conn = user_data;
- size_t nb;
+ ssize_t nb;
if (conn->fd == -1 &&
- ((conn->fd = sync_connect()) == -1)) {
+ ((conn->fd = sync_connect(lldpctl)) == -1)) {
return LLDPCTL_ERR_CANNOT_CONNECT;
}
return nb;
}
-/* Statiscally receive data from remote end. */
+/* Statically receive data from remote end. */
static ssize_t
sync_recv(lldpctl_conn_t *lldpctl,
const uint8_t *data, size_t length, void *user_data)
{
struct lldpctl_conn_sync_t *conn = user_data;
- size_t nb;
+ ssize_t nb;
+ size_t remain, offset = 0;
if (conn->fd == -1 &&
- ((conn->fd = sync_connect()) == -1)) {
+ ((conn->fd = sync_connect(lldpctl)) == -1)) {
lldpctl->error = LLDPCTL_ERR_CANNOT_CONNECT;
return LLDPCTL_ERR_CANNOT_CONNECT;
}
- while ((nb = read(conn->fd, (void*)data, length)) == -1) {
- if (errno == EAGAIN || errno == EINTR) continue;
- return LLDPCTL_ERR_CALLBACK_FAILURE;
- }
- return nb;
+ remain = length;
+ do {
+ if ((nb = read(conn->fd, (unsigned char*)data + offset, remain)) == -1) {
+ if (errno == EAGAIN || errno == EINTR)
+ continue;
+ return LLDPCTL_ERR_CALLBACK_FAILURE;
+ }
+ remain -= nb;
+ offset += nb;
+ } while (remain > 0 && nb != 0);
+ return offset;
}
-
-
lldpctl_conn_t*
lldpctl_new(lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data)
+{
+ return lldpctl_new_name(lldpctl_get_default_transport(), send, recv, user_data);
+}
+
+lldpctl_conn_t*
+lldpctl_new_name(const char *ctlname, lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data)
{
lldpctl_conn_t *conn = NULL;
struct lldpctl_conn_sync_t *data = NULL;
if ((conn = calloc(1, sizeof(lldpctl_conn_t))) == NULL)
return NULL;
+ conn->ctlname = strdup(ctlname);
+ if (conn->ctlname == NULL) {
+ free(conn);
+ return NULL;
+ }
if (!send && !recv) {
if ((data = malloc(sizeof(struct lldpctl_conn_sync_t))) == NULL) {
+ free(conn->ctlname);
free(conn);
return NULL;
}
lldpctl_release(lldpctl_conn_t *conn)
{
if (conn == NULL) return 0;
+ free(conn->ctlname);
if (conn->send == sync_send) {
struct lldpctl_conn_sync_t *data = conn->user_data;
if (data->fd != -1) close(data->fd);
{
uint8_t *buffer = NULL;
ssize_t rc;
- if (conn->input_buffer_len >= length) return 0;
if ((buffer = malloc(length)) == NULL)
return SET_ERROR(conn, LLDPCTL_ERR_NOMEM);
return rc;
}
-static void
+static int
check_for_notification(lldpctl_conn_t *conn)
{
struct lldpd_neighbor_change *change;
NOTIFICATION,
&p,
&MARSHAL_INFO(lldpd_neighbor_change));
- if (rc != 0) return;
+ if (rc != 0) return rc;
change = p;
/* We have a notification, call the callback */
interface = _lldpctl_new_atom(conn, atom_interface,
change->ifname);
if (interface == NULL) goto end;
- neighbor = _lldpctl_new_atom(conn, atom_port,
+ neighbor = _lldpctl_new_atom(conn, atom_port, 0,
NULL, change->neighbor, NULL);
if (neighbor == NULL) goto end;
conn->watch_cb(conn, type, interface, neighbor, conn->watch_data);
}
free(change->ifname);
free(change);
+
+ /* Indicate if more data remains in the buffer for processing */
+ return (rc);
}
ssize_t
memcpy(conn->input_buffer + conn->input_buffer_len, data, length);
conn->input_buffer_len += length;
- /* Is it a notification? */
- check_for_notification(conn);
+ /* Read all notifications */
+ while(!check_for_notification(conn));
RESET_ERROR(conn);
return conn->input_buffer_len;
}
+int
+lldpctl_process_conn_buffer(lldpctl_conn_t *conn)
+{
+ int rc;
+
+ rc = check_for_notification(conn);
+
+ RESET_ERROR(conn);
+
+ return rc;
+}
+
ssize_t
lldpctl_send(lldpctl_conn_t *conn)
{