Ubus
OpenWrt system message/RPC bus.
ubusd.c File Reference
#include <sys/socket.h>
#include "ubusd.h"

Go to the source code of this file.

Macros

#define USES_EXTERNAL_BUFFER   ~0U
 

Functions

static struct ubus_msg_bufubus_msg_ref (struct ubus_msg_buf *ub)
 
struct ubus_msg_bufubus_msg_new (void *data, int len, bool shared)
 
void ubus_msg_free (struct ubus_msg_buf *ub)
 
ssize_t ubus_msg_writev (int fd, struct ubus_msg_buf *ub, size_t offset)
 
void ubus_msg_list_free (struct ubus_msg_buf_list *ubl)
 
static void ubus_msg_enqueue (struct ubus_client *cl, struct ubus_msg_buf *ub)
 
void ubus_msg_send (struct ubus_client *cl, struct ubus_msg_buf *ub)
 

Macro Definition Documentation

◆ USES_EXTERNAL_BUFFER

#define USES_EXTERNAL_BUFFER   ~0U

Definition at line 21 of file ubusd.c.

Function Documentation

◆ ubus_msg_enqueue()

static void ubus_msg_enqueue ( struct ubus_client cl,
struct ubus_msg_buf ub 
)
static

Definition at line 143 of file ubusd.c.

144 {
145  struct ubus_msg_buf_list *ubl;
146 
147  if (cl->txq_len + ub->len > UBUS_CLIENT_MAX_TXQ_LEN)
148  return;
149 
150  ubl = calloc(1, sizeof(struct ubus_msg_buf_list));
151  if (!ubl)
152  return;
153 
154  INIT_LIST_HEAD(&ubl->list);
155  ubl->msg = ubus_msg_ref(ub);
156 
157  list_add_tail(&ubl->list, &cl->tx_queue);
158  cl->txq_len += ub->len;
159 }
unsigned int txq_len
Definition: ubusd.h:65
struct list_head tx_queue
Definition: ubusd.h:63
struct ubus_msg_buf * msg
Definition: ubusd.h:41
struct list_head list
Definition: ubusd.h:40
int len
Definition: ubusd.h:36
static struct ubus_msg_buf * ubus_msg_ref(struct ubus_msg_buf *ub)
Definition: ubusd.c:23
#define UBUS_CLIENT_MAX_TXQ_LEN
Definition: ubusd.h:27
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ubus_msg_free()

void ubus_msg_free ( struct ubus_msg_buf ub)

Definition at line 67 of file ubusd.c.

68 {
69  switch (ub->refcount) {
70  case 1:
72  if (ub->fd >= 0)
73  close(ub->fd);
74 
75  free(ub);
76  break;
77  default:
78  ub->refcount--;
79  break;
80  }
81 }
uint32_t refcount
Definition: ubusd.h:32
int fd
Definition: ubusd.h:35
#define USES_EXTERNAL_BUFFER
Definition: ubusd.c:21
Here is the caller graph for this function:

◆ ubus_msg_list_free()

void ubus_msg_list_free ( struct ubus_msg_buf_list ubl)

Definition at line 136 of file ubusd.c.

137 {
138  list_del_init(&ubl->list);
139  ubus_msg_free(ubl->msg);
140  free(ubl);
141 }
void ubus_msg_free(struct ubus_msg_buf *ub)
Definition: ubusd.c:67
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ubus_msg_new()

struct ubus_msg_buf* ubus_msg_new ( void *  data,
int  len,
bool  shared 
)

Definition at line 39 of file ubusd.c.

40 {
41  struct ubus_msg_buf *ub;
42  int buflen = sizeof(*ub);
43 
44  if (!shared)
45  buflen += len;
46 
47  ub = calloc(1, buflen);
48  if (!ub)
49  return NULL;
50 
51  ub->fd = -1;
52 
53  if (shared) {
55  ub->data = data;
56  } else {
57  ub->refcount = 1;
58  ub->data = (void *) (ub + 1);
59  if (data)
60  memcpy(ub + 1, data, len);
61  }
62 
63  ub->len = len;
64  return ub;
65 }
struct blob_attr * data
Definition: ubusd.h:34
Here is the caller graph for this function:

◆ ubus_msg_ref()

static struct ubus_msg_buf* ubus_msg_ref ( struct ubus_msg_buf ub)
static

Definition at line 23 of file ubusd.c.

24 {
25  struct ubus_msg_buf *new_ub;
26  if (ub->refcount == USES_EXTERNAL_BUFFER) {
27  new_ub = ubus_msg_new(ub->data, ub->len, false);
28  if (!new_ub)
29  return NULL;
30  memcpy(&new_ub->hdr, &ub->hdr, sizeof(struct ubus_msghdr));
31  new_ub->fd = ub->fd;
32  return new_ub;
33  }
34 
35  ub->refcount++;
36  return ub;
37 }
struct ubus_msghdr hdr
Definition: ubusd.h:33
struct ubus_msg_buf * ubus_msg_new(void *data, int len, bool shared)
Definition: ubusd.c:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ubus_msg_send()

void ubus_msg_send ( struct ubus_client cl,
struct ubus_msg_buf ub 
)

Definition at line 162 of file ubusd.c.

163 {
164  ssize_t written;
165 
166  if (ub->hdr.type != UBUS_MSG_MONITOR)
167  ubusd_monitor_message(cl, ub, true);
168 
169  if (list_empty(&cl->tx_queue)) {
170  written = ubus_msg_writev(cl->sock.fd, ub, 0);
171 
172  if (written < 0)
173  written = 0;
174 
175  if (written >= (ssize_t) (ub->len + sizeof(ub->hdr)))
176  return;
177 
178  cl->txq_ofs = written;
179  cl->txq_len = -written;
180 
181  /* get an event once we can write to the socket again */
182  uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
183  }
184  ubus_msg_enqueue(cl, ub);
185 }
unsigned int txq_ofs
Definition: ubusd.h:64
struct uloop_fd sock
Definition: ubusd.h:52
uint8_t type
Definition: ubusmsg.h:31
static void ubus_msg_enqueue(struct ubus_client *cl, struct ubus_msg_buf *ub)
Definition: ubusd.c:143
ssize_t ubus_msg_writev(int fd, struct ubus_msg_buf *ub, size_t offset)
Definition: ubusd.c:83
void ubusd_monitor_message(struct ubus_client *cl, struct ubus_msg_buf *ub, bool send)
Definition: ubusd_monitor.c:77
@ UBUS_MSG_MONITOR
Definition: ubusmsg.h:73
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ubus_msg_writev()

ssize_t ubus_msg_writev ( int  fd,
struct ubus_msg_buf ub,
size_t  offset 
)

Definition at line 83 of file ubusd.c.

84 {
85  uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
86  static struct iovec iov[2];
87  struct msghdr msghdr = { 0 };
88  struct ubus_msghdr hdr;
89  struct cmsghdr *cmsg;
90  ssize_t ret;
91  int *pfd;
92 
93  msghdr.msg_iov = iov;
94  msghdr.msg_iovlen = ARRAY_SIZE(iov);
95  msghdr.msg_control = fd_buf;
96  msghdr.msg_controllen = sizeof(fd_buf);
97 
98  cmsg = CMSG_FIRSTHDR(&msghdr);
99  cmsg->cmsg_type = SCM_RIGHTS;
100  cmsg->cmsg_level = SOL_SOCKET;
101  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
102 
103  pfd = (int *) CMSG_DATA(cmsg);
104  msghdr.msg_controllen = cmsg->cmsg_len;
105 
106  *pfd = ub->fd;
107  if (ub->fd < 0 || offset) {
108  msghdr.msg_control = NULL;
109  msghdr.msg_controllen = 0;
110  }
111 
112  if (offset < sizeof(ub->hdr)) {
113  hdr.version = ub->hdr.version;
114  hdr.type = ub->hdr.type;
115  hdr.seq = cpu_to_be16(ub->hdr.seq);
116  hdr.peer = cpu_to_be32(ub->hdr.peer);
117 
118  iov[0].iov_base = ((char *) &hdr) + offset;
119  iov[0].iov_len = sizeof(hdr) - offset;
120  iov[1].iov_base = (char *) ub->data;
121  iov[1].iov_len = ub->len;
122  } else {
123  offset -= sizeof(ub->hdr);
124  iov[0].iov_base = ((char *) ub->data) + offset;
125  iov[0].iov_len = ub->len - offset;
126  msghdr.msg_iovlen = 1;
127  }
128 
129  do {
130  ret = sendmsg(fd, &msghdr, 0);
131  } while (ret < 0 && errno == EINTR);
132 
133  return ret;
134 }
uint32_t peer
Definition: ubusmsg.h:33
uint8_t version
Definition: ubusmsg.h:30
uint16_t seq
Definition: ubusmsg.h:32
Here is the caller graph for this function: