static int proc_data_send(struct client *cl, const char *data, int len) { struct dispatch_proc *p = &cl->dispatch.proc; int retlen = 0; int ret; while (len) { ret = write(p->wrfd.fd, data, len); if (ret < 0) { if (errno == EINTR) continue; if (errno == EAGAIN || errno == EWOULDBLOCK) break; /* consume all data */ ret = len; } if (!ret) break; retlen += ret; len -= ret; data += ret; } if (len) uloop_fd_add(&p->wrfd, ULOOP_WRITE); else uloop_fd_delete(&p->wrfd); return retlen; }
int UBusThread::run() { ILOG_TRACE(UBUS_THREAD); uloop_fd_add(&_ubus_fd, ULOOP_READ); uloop_run(); return 0; }
int main(int argc, char **argv) { struct dummy_struct ds; int c; int type = kDNSServiceType_ANY; int flags = 0; int ifindex = 0; memset (&ds, 0, sizeof(ds)); while ((c = getopt(argc, argv, "f:t:i:")) != -1) switch (c) { case 't': type = atoi(optarg); break; case 'i': ifindex = if_nametoindex(optarg); break; case 'f': flags = atoi(optarg); break; } if (argc <= 1) { fprintf(stderr, "Usage: %s [-f <flags>] [-i <if>] [-t <type>] <name>\n", argv[0]); exit(1); } if (DNSServiceQueryRecord(&ds.service, flags, ifindex, argv[1], type, kDNSServiceClass_IN, dummy_callback, NULL) != kDNSServiceErr_NoError) { fprintf(stderr, "Error initializing DNSServiceQueryRecord\n"); exit(1); } if (uloop_init() < 0) { fprintf(stderr, "Error in uloop_init\n"); exit(1); } ds.ufd.fd = DNSServiceRefSockFD(ds.service); printf("FD:%d\n", ds.ufd.fd); ds.ufd.cb = uloop_fd_callback; if (uloop_fd_add(&ds.ufd, ULOOP_READ) < 0) { fprintf(stderr, "Error in uloop_fd_add\n"); exit(1); } printf("Entering event loop\n"); uloop_run(); return 0; }
static void log_handle_reconnect(struct uloop_timeout *timeout) { sender.fd = usock((log_udp) ? (USOCK_UDP) : (USOCK_TCP), log_ip, log_port); if (sender.fd < 0) { fprintf(stderr, "failed to connect: %s\n", strerror(errno)); uloop_timeout_set(&retry, 1000); } else { uloop_fd_add(&sender, ULOOP_READ); syslog(LOG_INFO, "Logread connected to %s:%s\n", log_ip, log_port); } }
bool hncp_io_init(hncp o) { int s; int on = 1; int off = 0; #if 0 /* Could also use usock here; however, it uses getaddrinfo, which * doesn't seem to work when e.g. default routes aren't currently * set up. Too bad. */ char buf[6]; sprintf(buf, "%d", HNCP_PORT); s = usock(USOCK_IPV6ONLY|USOCK_UDP|USOCK_SERVER|USOCK_NONBLOCK, NULL, buf); if (s < 0) return false; #else struct sockaddr_in6 addr; s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s<0) { L_ERR("unable to create IPv6 UDP socket"); return false; } fcntl(s, F_SETFL, O_NONBLOCK); memset(&addr, 0, sizeof(addr)); addr.sin6_family = AF_INET6; addr.sin6_port = htons(HNCP_PORT); const int one = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (bind(s, (struct sockaddr *)&addr, sizeof(addr))<0) { L_ERR("unable to bind to port %d", HNCP_PORT); return false; } #endif if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) { L_ERR("unable to setsockopt IPV6_RECVPKTINFO:%s", strerror(errno)); return false; } if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off)) < 0) { L_ERR("unable to setsockopt IPV6_MULTICAST_LOOP:%s", strerror(errno)); return false; } o->udp_socket = s; o->timeout.cb = _timeout; memset(&o->ufd, 0, sizeof(o->ufd)); o->ufd.fd = o->udp_socket; o->ufd.cb = _fd_callback; uloop_fd_add(&o->ufd, ULOOP_READ); return true; }
void u_tcp_connect() { usfd.stream.write_error = 1; ufd.fd = usock(USOCK_TCP, u_tcp_host, u_tcp_port); if (ufd.fd < 0) { _debug("connection to sysrepo failed"); uloop_timeout_set(&reconnect_timer, 1000); } ufd.cb = connect_cb; uloop_fd_add(&ufd, ULOOP_WRITE | ULOOP_EDGE_TRIGGER); }
static void ustream_fd_set_uloop(struct ustream *s, bool write) { struct ustream_fd *sf = container_of(s, struct ustream_fd, stream); struct ustream_buf *buf; unsigned int flags = ULOOP_EDGE_TRIGGER | ULOOP_ERROR_CB; if (!s->read_blocked && !s->eof) flags |= ULOOP_READ; buf = s->w.head; if (write || (buf && s->w.data_bytes && !s->write_error)) flags |= ULOOP_WRITE; uloop_fd_add(&sf->fd, flags); }
int main(void) { jrpc_server_init(&my_server, HOST, PORT); jrpc_register_procedure(&my_server, say_hello, "sayHello", NULL); jrpc_register_procedure(&my_server, exit_server, "exit", NULL); jrpc_register_procedure(&my_server, foo, "foo", NULL); uloop_init(); uloop_fd_add(&my_server.sock, ULOOP_READ); uloop_run(); jrpc_server_destroy(&my_server); return 0; }
static void reconnect_socket6(struct uloop_timeout *timeout) { struct interface *iface = container_of(timeout, struct interface, reconnect); char mcast_addr[128]; int ttl = 255; int yes = 1; snprintf(mcast_addr, sizeof(mcast_addr), "%s%%%s", (iface->multicast) ? (iface->mcast_addr) : (iface->v6_addrs), iface->name); iface->fd.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_NONBLOCK | USOCK_IPV6ONLY, mcast_addr, "5353"); if (iface->fd.fd < 0) { fprintf(stderr, "failed to add listener %s: %s\n", mcast_addr, strerror(errno)); goto retry; } if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, strlen(iface->name) < 0)) fprintf(stderr, "ioctl failed: SO_BINDTODEVICE\n"); if (setsockopt(iface->fd.fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0) fprintf(stderr, "ioctl failed: IPV6_UNICAST_HOPS\n"); if (setsockopt(iface->fd.fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: IPV6_RECVPKTINFO\n"); if (setsockopt(iface->fd.fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: IPV6_RECVHOPLIMIT\n"); if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: SO_REUSEADDR\n"); if (iface->multicast && interface_socket_setup6(iface)) { iface->fd.fd = -1; goto retry; } uloop_fd_add(&iface->fd, ULOOP_READ); if (iface->multicast) { dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 1); announce_init(iface); } return; retry: uloop_timeout_set(timeout, 1000); }
static int netlink_init(void) { struct { struct nlmsghdr hdr; struct ifaddrmsg msg; } req; struct sockaddr_nl addr; int sock[2]; memset(&addr, 0, sizeof(addr)); memset(&req, 0, sizeof(req)); if ((sock[0] = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { D("couldn't open NETLINK_ROUTE socket"); return -1; } addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_IPV4_IFADDR; if ((bind(sock[0], (struct sockaddr *)&addr, sizeof(addr))) == -1) { D("couldn't bind netlink socket"); return -1; } netlink_event.fd = sock[0]; uloop_fd_add(&netlink_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); if ((sock[1] = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) == -1) { D("couldn't open NETLINK_ROUTE socket"); return -1; } req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; req.hdr.nlmsg_type = RTM_GETADDR; req.msg.ifa_family = AF_INET; if ((send(sock[1], &req, req.hdr.nlmsg_len, 0)) == -1) { D("couldn't send netlink socket"); return -1; } struct uloop_fd dummy_event = { .fd = sock[1] }; netlink_new_msg(&dummy_event, 0); return 0; }
void http_server_init(void) { http_digest_init_nonce_priv_key(); http_s.http_event.cb = http_new_client; http_s.http_event.fd = usock(USOCK_TCP | USOCK_SERVER, "0.0.0.0", config->local->port); uloop_fd_add(&http_s.http_event, ULOOP_READ | ULOOP_EDGE_TRIGGER); DDF("+++ HTTP SERVER CONFIGURATION +++\n"); if (config->local->ip) DDF("ip: '%s'\n", config->local->ip); else DDF("NOT BOUND TO IP\n"); DDF("port: '%s'\n", config->local->port); DDF("--- HTTP SERVER CONFIGURATION ---\n"); log_message(NAME, L_NOTICE, "http server initialized\n"); }
static void reconnect_socket4(struct uloop_timeout *timeout) { struct interface *iface = container_of(timeout, struct interface, reconnect); int yes = 1; iface->fd.fd = usock(USOCK_UDP | USOCK_SERVER | USOCK_NONBLOCK | USOCK_IPV4ONLY, (iface->multicast) ? (iface->mcast_addr) : (iface->v4_addrs), "5353"); if (iface->fd.fd < 0) { fprintf(stderr, "failed to add listener %s: %s\n", iface->mcast_addr, strerror(errno)); goto retry; } if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, strlen(iface->name) < 0)) fprintf(stderr, "ioctl failed: SO_BINDTODEVICE\n"); if (setsockopt(iface->fd.fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: SO_REUSEADDR\n"); if (setsockopt(iface->fd.fd, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: IP_RECVTTL\n"); if (setsockopt(iface->fd.fd, IPPROTO_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0) fprintf(stderr, "ioctl failed: IP_PKTINFO\n"); if (iface->multicast && interface_mcast_setup4(iface)) { iface->fd.fd = -1; goto retry; } uloop_fd_add(&iface->fd, ULOOP_READ); if (iface->multicast) { dns_send_question(iface, "_services._dns-sd._udp.local", TYPE_PTR, 1); announce_init(iface); } return; retry: uloop_timeout_set(timeout, 1000); }
int main(int argc, char **argv) { const char *ubus_socket = UBUS_UNIX_SOCKET; int ret = 0; int ch; signal(SIGPIPE, SIG_IGN); signal(SIGHUP, sighup_handler); openlog("ubusd", LOG_PID, LOG_DAEMON); uloop_init(); while ((ch = getopt(argc, argv, "s:")) != -1) { switch (ch) { case 's': ubus_socket = optarg; break; default: return usage(argv[0]); } } unlink(ubus_socket); umask(0111); server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, ubus_socket, NULL); if (server_fd.fd < 0) { perror("usock"); ret = -1; goto out; } uloop_fd_add(&server_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER); ubusd_acl_load(); uloop_run(); unlink(ubus_socket); out: uloop_done(); return ret; }
/* takes the msgbuf reference */ void ubus_msg_send(struct ubus_client *cl, struct ubus_msg_buf *ub, bool free) { int written; if (!cl->tx_queue[cl->txq_cur]) { written = ubus_msg_writev(cl->sock.fd, ub, 0); if (written >= ub->len + sizeof(ub->hdr)) goto out; if (written < 0) written = 0; cl->txq_ofs = written; /* get an event once we can write to the socket again */ uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER); } ubus_msg_enqueue(cl, ub); out: if (free) ubus_msg_free(ub); }
int main(int argc, char **argv) { const char *ubus_socket = UBUS_UNIX_SOCKET;//定义在cmake中,UBUS_UNIX_SOCKET="/var/run/ubus.sock" int ret = 0; int ch; signal(SIGPIPE, SIG_IGN);//入参:信号类型;处理函数handler。 uloop_init(); while ((ch = getopt(argc, argv, "s:")) != -1) { switch (ch) { case 's': ubus_socket = optarg; break; default: return usage(argv[0]); } } unlink(ubus_socket);//unlink,删除/var/run/ubus.sock文件 umask(0177);//umask,设置用户创建新文件时文件的默认权限。 server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, ubus_socket, NULL); if (server_fd.fd < 0) {//usock,首参为套接字类型,ubus_socket可为"127.0.0.1"或var/run/ubus.sock,最后一个为服务端口号"22"或NULL perror("usock"); ret = -1; goto out; } uloop_fd_add(&server_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER); uloop_run();//调用uloop_run(),ubusd进程不会再退出--->ubusd通过select方法监听套接字/var/run/ubus.sock,接收ubus发出的服务查询/请求,并将服务请求转发给netifd等提供服务的进程。 unlink(ubus_socket); out: uloop_done(); return ret; }
static bool get_next_connection(int fd) { struct ubus_client *cl; int client_fd; client_fd = accept(fd, NULL, 0); if (client_fd < 0) { switch (errno) { case ECONNABORTED: case EINTR: return true; default: return false; } } cl = ubusd_proto_new_client(client_fd, client_cb); if (cl) uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_EDGE_TRIGGER); else close(client_fd); return true; }
int jrpc_server_init(struct jrpc_server *server, char *host, char *port) { char *debug_level_env = getenv("JRPC_DEBUG"); if (debug_level_env == NULL) { server->debug_level = 0; } else { server->debug_level = strtol(debug_level_env, NULL, 10); dlog("JSONRPC-C Debug level %d\n", server->debug_level); } server->sock.cb = server_cb; server->sock.fd = usock(USOCK_TCP | USOCK_SERVER | USOCK_IPV4ONLY | USOCK_NUMERIC, host, port); if (server->sock.fd < 0) { perror("usock"); return 1; } system_fd_set_cloexec(server->sock.fd); uloop_fd_add(&server->sock, ULOOP_READ | ULOOP_EDGE_TRIGGER); return 0; }
static bool get_next_connection(int server_fd, struct jrpc_server *server) { struct jrpc_connection *conn; int fd; struct sockaddr_in a; socklen_t len; memset(&a, 0, sizeof(a)); len = sizeof(struct sockaddr); fd = accept(server_fd, (struct sockaddr *)&a, &len); if (fd < 0) { /* elog("accept[0x%08x] error[%d] error[%d] return false\n", server_fd, fd, errno); */ switch (errno) { case ECONNABORTED: case EINTR: return true; default: return false; } } conn = new_connection(fd, connection_cb); if (conn) { memcpy(&conn->addr, &a, sizeof(a)); system_fd_set_cloexec(conn->sock.fd); conn->server = server; conn->debug_level = server->debug_level; uloop_fd_add(&conn->sock, ULOOP_READ); } else { close(fd); } return true; }
int main(int argc, char *argv[]) { config_init(argc, argv); if (glue_init() != 0) { iotc_error("glue init failed!"); return -1; } if (0 != connection_init()) { iotc_error("socket_init failed!"); return -1; } uloop_init(); uloop_fd_add(&iotc_monitor_uloop_fd, ULOOP_READ); uloop_timeout_set(&g_sendDevOnlineTm, 2000); uloop_run(); uloop_done(); return 0; }
int network_init(struct uci_context *uci) { memset(&net_status, 0, sizeof(struct network_status)); // Initialize the discovered units AVL tree. avl_init(&discovered_units, avl_strcmp, false, NULL); // Initialize multicast group address. inet_pton(AF_INET6, KORUZA_MULTICAST_GROUP, &multicast_group); char *interface = uci_get_string(uci, "koruza.@network[0].interface"); if (!interface) { syslog(LOG_WARNING, "Network interface not configured. Skipping network initialization."); return 0; } net_status.interface = strdup(interface); free(interface); // Discover interface IPv4 address. timer_address_update.cb = network_update_local_address; network_update_local_address(&timer_address_update); // Prepare multicast socket, listen for updates. ad_socket.fd = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); if (ad_socket.fd < 0) { syslog(LOG_ERR, "Failed to setup autodiscovery socket."); return -1; } if (setsockopt(ad_socket.fd, SOL_SOCKET, SO_BINDTODEVICE, net_status.interface, strlen(net_status.interface)) != 0) { syslog(LOG_ERR, "Failed to bind autodiscovery socket to configured interface."); close(ad_socket.fd); return -1; } struct sockaddr_in6 address; memset(&address, 0, sizeof(address)); address.sin6_family = AF_INET6; address.sin6_port = htons(10424); if (bind(ad_socket.fd, (struct sockaddr*) &address, sizeof(address)) != 0) { syslog(LOG_ERR, "Failed to bind autodiscovery socket."); close(ad_socket.fd); return -1; } // Subscribe to multicast messages. struct ipv6_mreq mreq; memcpy(&mreq.ipv6mr_multiaddr, &multicast_group, sizeof(multicast_group)); mreq.ipv6mr_interface = 0; if (setsockopt(ad_socket.fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) != 0) { syslog(LOG_ERR, "Failed to join multicast group."); close(ad_socket.fd); return -1; } // Set hop limit for sent multicast messages. int hops = 1; if (setsockopt(ad_socket.fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof(hops)) != 0) { syslog(LOG_ERR, "Failed to configure hop limit."); close(ad_socket.fd); return -1; } // Add socket to uloop. ad_socket.cb = network_message_received; uloop_fd_add(&ad_socket, ULOOP_READ); // Setup announce timer. timer_announce.cb = network_announce_ourselves; uloop_timeout_set(&timer_announce, KORUZA_ANNOUNCE_INTERVAL); syslog(LOG_INFO, "Initialized network on interface %s (%s).", net_status.interface, net_status.ip_address); net_status.ready = 1; // Setup any staticly configured peers. char *peer_ip = uci_get_string(uci, "koruza.@network[0].peer"); if (peer_ip) { struct network_device device; device.version = 0; device.id = "STATIC"; device.ip_address = peer_ip; if (network_add_device(&device) != 0) { syslog(LOG_WARNING, "Unable to add static network peer."); } free(peer_ip); } return 0; }
static int ubus_msg_writev(int fd, struct ubus_msg_buf *ub, int offset) { static struct iovec iov[2]; static struct { struct cmsghdr h; int fd; } fd_buf = { .h = { .cmsg_len = sizeof(fd_buf), .cmsg_level = SOL_SOCKET, .cmsg_type = SCM_RIGHTS, }, }; struct msghdr msghdr = { .msg_iov = iov, .msg_iovlen = ARRAY_SIZE(iov), .msg_control = &fd_buf, .msg_controllen = sizeof(fd_buf), }; fd_buf.fd = ub->fd; if (ub->fd < 0) { msghdr.msg_control = NULL; msghdr.msg_controllen = 0; } if (offset < sizeof(ub->hdr)) { iov[0].iov_base = ((char *) &ub->hdr) + offset; iov[0].iov_len = sizeof(ub->hdr) - offset; iov[1].iov_base = (char *) ub->data; iov[1].iov_len = ub->len; return sendmsg(fd, &msghdr, 0); } else { offset -= sizeof(ub->hdr); return write(fd, ((char *) ub->data) + offset, ub->len - offset); } } static void ubus_msg_enqueue(struct ubus_client *cl, struct ubus_msg_buf *ub) { if (cl->tx_queue[cl->txq_tail]) return; cl->tx_queue[cl->txq_tail] = ubus_msg_ref(ub); cl->txq_tail = (cl->txq_tail + 1) % ARRAY_SIZE(cl->tx_queue); } /* takes the msgbuf reference */ void ubus_msg_send(struct ubus_client *cl, struct ubus_msg_buf *ub, bool free) { int written; if (!cl->tx_queue[cl->txq_cur]) { written = ubus_msg_writev(cl->sock.fd, ub, 0); if (written >= ub->len + sizeof(ub->hdr)) goto out; if (written < 0) written = 0; cl->txq_ofs = written; /* get an event once we can write to the socket again */ uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER); } ubus_msg_enqueue(cl, ub); out: if (free) ubus_msg_free(ub); }
static void client_cb(struct uloop_fd *sock, unsigned int events) { struct ubus_client *cl = container_of(sock, struct ubus_client, sock); struct ubus_msg_buf *ub; static struct iovec iov; static struct { struct cmsghdr h; int fd; } fd_buf = { .h = { .cmsg_type = SCM_RIGHTS, .cmsg_level = SOL_SOCKET, .cmsg_len = sizeof(fd_buf), } }; struct msghdr msghdr = { .msg_iov = &iov, .msg_iovlen = 1, }; /* first try to tx more pending data */ while ((ub = ubus_msg_head(cl))) { int written; written = ubus_msg_writev(sock->fd, ub, cl->txq_ofs); if (written < 0) { switch(errno) { case EINTR: case EAGAIN: break; default: goto disconnect; } break; } cl->txq_ofs += written; if (cl->txq_ofs < ub->len + sizeof(ub->hdr)) break; ubus_msg_dequeue(cl); } /* prevent further ULOOP_WRITE events if we don't have data * to send anymore */ if (!ubus_msg_head(cl) && (events & ULOOP_WRITE)) uloop_fd_add(sock, ULOOP_READ | ULOOP_EDGE_TRIGGER); retry: if (!sock->eof && cl->pending_msg_offset < sizeof(cl->hdrbuf)) { int offset = cl->pending_msg_offset; int bytes; fd_buf.fd = -1; iov.iov_base = ((char *) &cl->hdrbuf) + offset; iov.iov_len = sizeof(cl->hdrbuf) - offset; if (cl->pending_msg_fd < 0) { msghdr.msg_control = &fd_buf; msghdr.msg_controllen = sizeof(fd_buf); } else { msghdr.msg_control = NULL; msghdr.msg_controllen = 0; } bytes = recvmsg(sock->fd, &msghdr, 0); if (bytes < 0) goto out; if (fd_buf.fd >= 0) cl->pending_msg_fd = fd_buf.fd; cl->pending_msg_offset += bytes; if (cl->pending_msg_offset < sizeof(cl->hdrbuf)) goto out; if (blob_pad_len(&cl->hdrbuf.data) > UBUS_MAX_MSGLEN) goto disconnect; cl->pending_msg = ubus_msg_new(NULL, blob_raw_len(&cl->hdrbuf.data), false); if (!cl->pending_msg) goto disconnect; memcpy(&cl->pending_msg->hdr, &cl->hdrbuf.hdr, sizeof(cl->hdrbuf.hdr)); memcpy(cl->pending_msg->data, &cl->hdrbuf.data, sizeof(cl->hdrbuf.data)); } ub = cl->pending_msg; if (ub) { int offset = cl->pending_msg_offset - sizeof(ub->hdr); int len = blob_raw_len(ub->data) - offset; int bytes = 0; if (len > 0) { bytes = read(sock->fd, (char *) ub->data + offset, len); if (bytes <= 0) goto out; } if (bytes < len) { cl->pending_msg_offset += bytes; goto out; } /* accept message */ ub->fd = cl->pending_msg_fd; cl->pending_msg_fd = -1; cl->pending_msg_offset = 0; cl->pending_msg = NULL; ubusd_proto_receive_message(cl, ub); goto retry; } out: if (!sock->eof || ubus_msg_head(cl)) return; disconnect: handle_client_disconnect(cl); } static bool get_next_connection(int fd) { struct ubus_client *cl; int client_fd; client_fd = accept(fd, NULL, 0); if (client_fd < 0) { switch (errno) { case ECONNABORTED: case EINTR: return true; default: return false; } } cl = ubusd_proto_new_client(client_fd, client_cb); if (cl) uloop_fd_add(&cl->sock, ULOOP_READ | ULOOP_EDGE_TRIGGER); else close(client_fd); return true; } static void server_cb(struct uloop_fd *fd, unsigned int events) { bool next; do { next = get_next_connection(fd->fd); } while (next); }
int main(int argc, char **argv) { int opt, rc = 0; while ((opt = getopt(argc, argv, "hv")) != -1) { switch (opt) { case 'v': conf.verbosity++; break; case 'h': default: return usage(argv[0]); } } conf.flx_ufd.fd = open(FLX_DEV, O_RDWR); if (conf.flx_ufd.fd < 0) { perror(FLX_DEV); rc = 1; goto finish; } if (!configure_tty(conf.flx_ufd.fd)) { fprintf(stderr, "%s: Failed to configure tty params\n", FLX_DEV); rc = 2; goto finish; } if (!config_init()) { rc = 3; goto oom; } if (!config_load_all()) { rc = 4; goto finish; } conf.ubus_ctx = ubus_connect(NULL); if (!conf.ubus_ctx) { fprintf(stderr, "Failed to connect to ubus\n"); rc = 5; goto finish; } #ifdef WITH_YKW conf.ykw = ykw_new(YKW_DEFAULT_THETA); if (conf.ykw == NULL) { rc = 6; goto oom; } #endif mosquitto_lib_init(); snprintf(conf.mqtt.id, MQTT_ID_LEN, MQTT_ID_TPL, getpid()); conf.mosq = mosquitto_new(conf.mqtt.id, conf.mqtt.clean_session, &conf); if (!conf.mosq) { switch (errno) { case ENOMEM: rc = 7; goto oom; case EINVAL: fprintf(stderr, "mosq_new: Invalid id and/or clean_session.\n"); rc = 8; goto finish; } } rc = mosquitto_loop_start(conf.mosq); switch (rc) { case MOSQ_ERR_INVAL: fprintf(stderr, "mosq_loop_start: Invalid input parameters.\n"); goto finish; case MOSQ_ERR_NOT_SUPPORTED: fprintf(stderr, "mosq_loop_start: No threading support.\n"); goto finish; }; rc = mosquitto_connect_async(conf.mosq, conf.mqtt.host, conf.mqtt.port, conf.mqtt.keepalive); switch (rc) { case MOSQ_ERR_INVAL: fprintf(stderr, "mosq_connect_async: Invalid input parameters.\n"); goto finish; case MOSQ_ERR_ERRNO: perror("mosq_connect_async"); goto finish; } uloop_init(); uloop_fd_add(&conf.flx_ufd, ULOOP_READ); uloop_timeout_set(&conf.timeout, CONFIG_ULOOP_TIMEOUT); ubus_add_uloop(conf.ubus_ctx); ubus_register_event_handler(conf.ubus_ctx, &conf.ubus_ev_sighup, CONFIG_UBUS_EV_SIGHUP); ubus_register_event_handler(conf.ubus_ctx, &conf.ubus_ev_shift_calc, CONFIG_UBUS_EV_SHIFT_CALC); uloop_run(); uloop_done(); goto finish; oom: fprintf(stderr, "error: Out of memory.\n"); finish: mosquitto_disconnect(conf.mosq); mosquitto_loop_stop(conf.mosq, false); mosquitto_destroy(conf.mosq); mosquitto_lib_cleanup(); ykw_free(conf.ykw); if (conf.ubus_ctx != NULL) { ubus_free(conf.ubus_ctx); } close(conf.flx_ufd.fd); uci_free_context(conf.uci_ctx); return rc; }
static void client_cb(struct uloop_fd *sock, unsigned int events) { struct ubus_client *cl = container_of(sock, struct ubus_client, sock); struct ubus_msg_buf *ub; /* first try to tx more pending data */ while ((ub = ubus_msg_head(cl))) { int written; written = ubus_msg_writev(sock->fd, ub, cl->txq_ofs); if (written < 0) { switch(errno) { case EINTR: case EAGAIN: break; default: goto disconnect; } break; } cl->txq_ofs += written; if (cl->txq_ofs < ub->len + sizeof(ub->hdr)) break; ubus_msg_dequeue(cl); } /* prevent further ULOOP_WRITE events if we don't have data * to send anymore */ if (!ubus_msg_head(cl) && (events & ULOOP_WRITE)) uloop_fd_add(sock, ULOOP_READ | ULOOP_EDGE_TRIGGER); retry: if (!sock->eof && cl->pending_msg_offset < sizeof(cl->hdrbuf)) { int offset = cl->pending_msg_offset; int bytes; bytes = read(sock->fd, (char *)&cl->hdrbuf + offset, sizeof(cl->hdrbuf) - offset); if (bytes < 0) goto out; cl->pending_msg_offset += bytes; if (cl->pending_msg_offset < sizeof(cl->hdrbuf)) goto out; if (blob_pad_len(&cl->hdrbuf.data) > UBUS_MAX_MSGLEN) goto disconnect; cl->pending_msg = ubus_msg_new(NULL, blob_raw_len(&cl->hdrbuf.data), false); if (!cl->pending_msg) goto disconnect; memcpy(&cl->pending_msg->hdr, &cl->hdrbuf.hdr, sizeof(cl->hdrbuf.hdr)); memcpy(cl->pending_msg->data, &cl->hdrbuf.data, sizeof(cl->hdrbuf.data)); } ub = cl->pending_msg; if (ub) { int offset = cl->pending_msg_offset - sizeof(ub->hdr); int len = blob_raw_len(ub->data) - offset; int bytes = 0; if (len > 0) { bytes = read(sock->fd, (char *) ub->data + offset, len); if (bytes <= 0) goto out; } if (bytes < len) { cl->pending_msg_offset += bytes; goto out; } /* accept message */ cl->pending_msg_offset = 0; cl->pending_msg = NULL; ubusd_proto_receive_message(cl, ub); goto retry; } out: if (!sock->eof || ubus_msg_head(cl)) return; disconnect: handle_client_disconnect(cl); }
static int rpc_rrdns_lookup(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { int port = 53, limit = RRDNS_DEF_LIMIT, timeout = RRDNS_DEF_TIMEOUT; struct blob_attr *tb[__RPC_L_MAX]; struct rrdns_context *rctx; const char *server = NULL; blobmsg_parse(rpc_lookup_policy, __RPC_L_MAX, tb, blob_data(msg), blob_len(msg)); if (tb[RPC_L_PORT]) port = blobmsg_get_u16(tb[RPC_L_PORT]); if (tb[RPC_L_LIMIT]) limit = blobmsg_get_u32(tb[RPC_L_LIMIT]); if (tb[RPC_L_TIMEOUT]) timeout = blobmsg_get_u32(tb[RPC_L_TIMEOUT]); if (tb[RPC_L_SERVER]) server = blobmsg_get_string(tb[RPC_L_SERVER]); if (!tb[RPC_L_ADDRS]) return UBUS_STATUS_INVALID_ARGUMENT; if (port <= 0) return UBUS_STATUS_INVALID_ARGUMENT; if (limit <= 0 || limit > RRDNS_MAX_LIMIT) return UBUS_STATUS_INVALID_ARGUMENT; if (timeout <= 0 || timeout > RRDNS_MAX_TIMEOUT) return UBUS_STATUS_INVALID_ARGUMENT; if (!server || !*server) server = rrdns_find_nameserver(); if (!server) return UBUS_STATUS_NOT_FOUND; rctx = calloc(1, sizeof(*rctx)); if (!rctx) return UBUS_STATUS_UNKNOWN_ERROR; rctx->socket.fd = usock(USOCK_UDP, server, usock_port(port)); if (rctx->socket.fd < 0) { free(rctx); return UBUS_STATUS_UNKNOWN_ERROR; } rctx->context = ctx; rctx->addr_cur = blobmsg_data(tb[RPC_L_ADDRS]); rctx->addr_rem = blobmsg_data_len(tb[RPC_L_ADDRS]); avl_init(&rctx->request_ids, rrdns_cmp_id, false, NULL); avl_init(&rctx->request_addrs, rrdns_cmp_addr, false, NULL); rctx->timeout.cb = rrdns_handle_timeout; uloop_timeout_set(&rctx->timeout, timeout); rctx->socket.cb = rrdns_handle_response; uloop_fd_add(&rctx->socket, ULOOP_READ); blob_buf_init(&rctx->blob, 0); while (limit--) rrdns_next_query(rctx); ubus_defer_request(ctx, req, &rctx->request); return UBUS_STATUS_OK; }