5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/socket.h>
31 #include <arpa/inet.h>
35 #include <connman/log.h>
37 #include "vici-client.h"
40 #define VICI_REQUEST_TIMEOUT 5000
44 VICI_SECTION_START = 1,
52 enum vici_packet_type {
54 VICI_CMD_RESPONSE = 1,
56 VICI_EVENT_REGISTER = 3,
57 VICI_EVENT_UNREGISTER = 4,
58 VICI_EVENT_CONFIRM = 5,
59 VICI_EVENT_UNKNOWN = 6,
63 static const char *vici_cmd_str[] = {
77 unsigned int allocated;
84 unsigned int rcv_pkt_size;
94 unsigned int rcv_pkt_size;
97 vici_request_reply_cb reply_cb;
98 vici_event_cb event_cb;
99 void *reply_user_data;
100 void *event_user_data;
103 struct _VICISection {
107 GHashTable *subsection;
110 static void remove_list(gpointer data)
115 g_slist_free_full((GSList *)data, g_free);
118 void vici_destroy_section(VICISection* section)
120 g_free(section->name);
121 g_hash_table_destroy(section->kvs);
122 g_hash_table_destroy(section->kvls);
123 g_hash_table_destroy(section->subsection);
127 static void free_section(gpointer data)
129 VICISection* section = (VICISection*)data;
130 vici_destroy_section(section);
133 VICISection* vici_create_section(const char* name)
135 VICISection* section;
137 section = g_try_new0(VICISection, 1);
139 connman_error("Failed to create section");
144 section->name = g_strdup(name);
145 section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
146 section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, remove_list);
147 section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section);
151 int add_subsection(const char* name, VICISection* child, VICISection* section)
153 if (section == NULL || name == NULL || child == NULL) {
154 connman_error("invalid parameter");
158 g_hash_table_insert(section->subsection, g_strdup(name), child);
162 static int add_kvl_to_section(const char* key, const char* value, VICISection* section)
165 if (section == NULL || key == NULL || value == NULL) {
166 connman_error("invalid parameter");
170 list = g_hash_table_lookup(section->kvls, key);
172 list = g_slist_alloc();
174 list = g_slist_prepend(list, g_strdup(value));
175 g_hash_table_replace(section->kvls, g_strdup(key), list);
179 static int add_kv_to_section(const char* key, const char* value, VICISection* section)
181 if (section == NULL || key == NULL || value == NULL) {
182 connman_error("invalid parameter");
186 g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
190 static VICISection* get_subsection(VICISection* section, const char* name)
192 VICISection* sub = g_hash_table_lookup(section->subsection, name);
194 sub = vici_create_section(name);
195 add_subsection(name, sub, section);
200 int vici_add_kv(VICISection* section, const char* key,
201 const char* value, const char* subsection)
203 VICISection* target = section;
204 DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
206 if (section == NULL || key == NULL) {
207 connman_error("invalid parameter");
212 target = get_subsection(section, subsection);
214 add_kv_to_section(key, value, target);
218 int vici_add_kvl(VICISection* section, const char* key,
219 const char* value, const char* subsection)
221 VICISection* target = section;
223 DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
224 if (section == NULL || key == NULL) {
225 connman_error("invalid parameter");
230 target = get_subsection(section, subsection);
232 if (g_strcmp0(subsection, "children") == 0)
233 target = get_subsection(target, "net");
235 add_kvl_to_section(key, value, target);
239 static void add_list_to_section(char *key, GSList *list, VICISection *section)
241 if (section == NULL || key == NULL || list == NULL)
244 g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy_deep(list, (GCopyFunc)g_strdup, NULL));
248 int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection)
250 VICISection* target = section;
252 DBG("key: %s, subsection: %s", key, subsection);
253 if (section == NULL || key == NULL) {
254 connman_error("invalid parameter");
259 target = get_subsection(section, subsection);
261 if (g_strcmp0(subsection, "children") == 0)
262 target = get_subsection(target, "net");
264 add_list_to_section(key, list, target);
268 static char *load_cert_from_path(const char *path)
273 size_t file_size = 0;
274 char *file_buff = NULL;
276 fp = fopen(path, "rb");
278 connman_error("fopen failed");
284 connman_error("fp is not a valid stream");
289 if (fstat(fd, &st) != 0) {
290 connman_error("fstat failed");
295 file_size = st.st_size;
296 file_buff = g_try_malloc0(sizeof(char)*st.st_size);
297 if (file_buff == NULL) {
298 connman_error("g_try_malloc0 failed\n");
303 if (fread(file_buff, 1, file_size, fp) != file_size) {
304 connman_error("file size not matched\n");
313 int vici_add_cert_kv(VICISection *section, const char *key,
314 const char *value, const char *subsection)
320 DBG("value is null");
324 cert = load_cert_from_path(value);
328 ret = vici_add_kv(section, key, (const char *)cert, subsection);
333 int vici_add_cert_kvl(VICISection *section, const char *key,
334 const char *value, const char *subsection)
339 cert = load_cert_from_path(value);
343 ret = vici_add_kvl(section, key, (const char *)cert, subsection);
348 static void *add_element(struct request *r, enum vici_element type,
354 if (r->used + size + 1 > r->allocated) {
355 newlen = r->allocated;
356 while (newlen < r->used + size + 1) {
359 new = realloc(r->sndbuf, newlen);
365 r->allocated = newlen;
367 r->sndbuf[r->used++] = type;
368 ret = r->sndbuf + r->used;
373 static void section_start(struct request *r, const char *name)
379 pos = add_element(r, VICI_SECTION_START, 1 + nlen);
382 memcpy(pos + 1, name, nlen);
386 static void section_end(struct request *r)
388 add_element(r, VICI_SECTION_END, 0);
391 static void key_value(struct request *r, const char *name,
392 const void *buf, unsigned int buflen)
399 pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
402 memcpy(pos + 1, name, nlen);
403 vlen = htons(buflen);
404 memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
405 memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
410 static void list_start(struct request *r, const char *name)
416 pos = add_element(r, VICI_LIST_START, 1 + nlen);
419 memcpy(pos + 1, name, nlen);
423 static void list_item(struct request *r, const void *buf,
429 pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
431 vlen = htons(buflen);
432 memcpy(pos, &vlen, sizeof(vlen));
433 memcpy(pos + sizeof(vlen), buf, buflen);
437 static void list_end(struct request *r)
439 add_element(r, VICI_LIST_END, 0);
442 static void destroy_vici_request(gpointer data)
444 struct request *req = (struct request *)data;
452 static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
455 struct request *req = NULL;
457 if (cmd >= VICI_CMD_MAX || !rp)
460 req = g_try_new0(struct request, 1);
462 connman_error("g_try_new0 failed");
467 req->used += strlen(vici_cmd_str[cmd]);
468 req->allocated = MIN(32, req->used);
469 req->sndbuf = g_try_new0(char, req->allocated);
471 connman_error("g_try_new0 failed");
476 req->sndbuf[0] = type;
477 req->sndbuf[1] = req->used - 2; /* except for type and name length */
478 memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2);
479 req->hdr_len = req->used;
487 static void write_section_kvs(VICISection *section, struct request *req)
492 if (section == NULL || req == NULL)
495 g_hash_table_iter_init (&iter, section->kvs);
496 while (g_hash_table_iter_next (&iter, &key, &value)) {
499 key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
505 static void write_list_item(gpointer data, gpointer user_data)
507 struct request *req = NULL;
510 if (!data || !user_data)
513 value = (char *)data;
514 req = (struct request *)user_data;
515 list_item(req, value, strlen(value));
520 static void write_section_kvls(VICISection *section, struct request *req)
525 if (section == NULL || req == NULL)
528 g_hash_table_iter_init (&iter, section->kvls);
529 while (g_hash_table_iter_next (&iter, &key, &value)) {
533 list_start(req, key);
534 g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
541 static void write_section(struct request *req, VICISection *section)
546 if (req == NULL || section == NULL)
550 section_start(req, section->name);
552 write_section_kvs(section, req);
553 write_section_kvls(section, req);
555 g_hash_table_iter_init(&iter, section->subsection);
556 while (g_hash_table_iter_next (&iter, &key, &value)) {
559 write_section(req, (VICISection *)value);
567 static int check_socket(int sock)
573 p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
574 res = poll((struct pollfd *) &p_fd, 1, 1);
577 connman_error("Polling error from socket\n");
579 } else if (res == 0) {
580 connman_error( "poll timeout. socket is busy\n");
584 if (p_fd.revents & POLLERR) {
585 connman_error("Error! POLLERR from socket[%d]\n", sock);
587 } else if (p_fd.revents & POLLHUP) {
588 connman_error("Error! POLLHUP from socket[%d]\n", sock);
590 } else if (p_fd.revents & POLLNVAL) {
591 connman_error("Error! POLLNVAL from socket[%d]\n", sock);
593 } else if (p_fd.revents & POLLIN) {
595 } else if (p_fd.revents & POLLOUT) {
600 connman_error("Unknown poll event [%d]\n", p_fd.revents);
604 static int write_socket(int sock, char *data, int data_len)
607 int left_len = data_len;
611 if (sock < SOCK_FD_MIN || !data || data_len < 0)
614 res = check_socket(sock);
622 wbytes = write(sock, ptr, left_len);
624 connman_error("Failed to write data into socket[%d].\n", sock);
626 }else if (wbytes < left_len) {
629 } else if (wbytes == left_len) {
632 connman_error("Unknown error occurred.\n");
643 int send_vici_command(struct request *req, VICIClient *vici_client)
645 unsigned int size = 0;
649 if (req == NULL || vici_client == NULL) {
650 connman_error("request is NULL\n");
653 sock_fd = vici_client->client_sock_fd;
655 size = htonl(req->used);
656 res = write_socket(sock_fd, (char *)&size, sizeof(size));
658 connman_error("failed to send size with network byte order\n");
662 res = write_socket(sock_fd, req->sndbuf, req->used);
664 connman_error("failed to send pkt\n");
668 if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN)
669 vici_client->request_list = g_slist_append(vici_client->request_list, req);
674 static void print_vici_element(int elem_type, char *value, int sections)
680 case VICI_SECTION_START:
681 for (i = 0; i < sections - 1; i++)
683 DBG("%s = {\n", value);
685 case VICI_SECTION_END:
686 for (i = 0; i < sections; i++)
691 for (i = 0; i < sections; i++)
695 case VICI_LIST_START:
696 for (i = 0; i < sections; i++)
698 DBG("%s = [", value);
712 static void debug_vici_message(char *buf, unsigned int size)
715 unsigned int pos = 0;
720 if (buf == NULL || size == 0)
729 case VICI_SECTION_START:
733 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
738 case VICI_SECTION_END:
750 g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
752 pos += (key_len + 1);
753 value_len = buf[pos];
755 g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
759 case VICI_LIST_START:
763 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
772 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
781 print_vici_element(type, temp, sections);
786 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
793 *key = g_strndup((const gchar *)&buf[pos], key_len);
795 value_len = buf[pos];
797 *value = g_strndup((const gchar *)&buf[pos], value_len);
802 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
804 gboolean success = FALSE;
805 unsigned int pos = 0;
813 if (type == VICI_KEY_VALUE) {
816 pos = extract_key_value(buf, pos, &key, &value);
817 DBG("pos : %d size : %d\n", pos, size);
819 /* TODO :remove this after debug */
820 DBG("key : %s value : %s\n", key, value);
821 if (g_strcmp0(key, "success") == 0)
822 (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
824 if (g_strcmp0(key, "errmsg"))
825 *err = g_strdup(value);
833 static int handle_vici_result(gboolean success, int cmd, char * err)
842 case VICI_CMD_LOAD_CONN:
845 case VICI_CMD_LOAD_SHARED:
848 case VICI_CMD_LOAD_CERT:
851 case VICI_CMD_LOAD_AUTH:
854 case VICI_CMD_LOAD_KEY:
857 case VICI_CMD_INITIATE:
860 case VICI_CMD_TERMINATE:
867 DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
871 static int process_vici_response(struct request * req)
874 gboolean success = FALSE;
880 if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
883 //TODO: remove below when there's no further problem.
884 debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
886 success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
887 ret = handle_vici_result(success, req->cmd, err);
892 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
894 struct request *req = NULL;
897 DBG("%s", vici_cmd_str[cmd]);
898 ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
900 connman_error("error on create_request\n");
904 write_section(req, root);
905 //TODO: remove below when there's no further problem.
906 debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
908 ret = send_vici_command(req, vici_client);
910 destroy_vici_request(req);
911 connman_error("error on send_command\n");
918 int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
920 struct request *req = NULL;
923 DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
924 ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
926 connman_error("error on create_request\n");
930 ret = send_vici_command(req, vici_client);
932 connman_error("error on send_command\n");
935 destroy_vici_request(req);
936 vici_client->event_cb = cb;
937 vici_client->event_user_data = user_data;
943 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
947 sock = g_io_channel_unix_get_fd(source);
948 if (sock < SOCK_FD_MIN)
951 if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
952 connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
953 //TODO: handle the breaking socket
959 static int read_socket(int sock, char *data, unsigned int data_len)
962 int total_rbytes = 0;
964 if (sock < SOCK_FD_MIN || !data || data_len <= 0)
967 while (data_len > 0) {
969 rbytes = read(sock, data, data_len);
973 total_rbytes += rbytes;
981 static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
986 if (vici_client->rcv_pkt_size == 0) {
987 unsigned int pkt_size = 0;
988 if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
991 vici_client->rcv_pkt_size = ntohl(pkt_size);
992 /* TODO :REMOVE THIS AFTER DEBUG */
993 DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
996 DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
998 buf = g_try_malloc0(vici_client->rcv_pkt_size);
1002 if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
1006 vici_client->rcvbuf = buf;
1012 static struct request *pop_vici_request(VICIClient *vici_client)
1014 GSList *list = NULL;
1019 list = vici_client->request_list;
1026 static void process_vici_reply(VICIClient *vici_client)
1028 struct request *req;
1034 /* get first request */
1035 req = pop_vici_request(vici_client);
1039 req->rcvbuf = vici_client->rcvbuf;
1040 req->rcv_pkt_size = vici_client->rcv_pkt_size;
1042 ret = process_vici_response(req);
1043 vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1044 destroy_vici_request(req);
1046 /* TODO :remove this after debug */
1047 DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1049 if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
1050 vici_client->reply_cb(ret, vici_client->reply_user_data);
1054 static int extract_event_name(char *buf, unsigned int size, char *temp)
1058 name_len = buf[pos];
1060 DBG("event len: %d", name_len);
1061 while(pos < size && pos - 2 < name_len) {
1062 temp[pos - 2] = buf[pos];
1066 DBG("event name: %s", temp);
1070 static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
1075 while (pos < size) {
1079 if (type == VICI_KEY_VALUE) {
1082 pos = extract_key_value(buf, pos, &key, &value);
1083 if (g_strcmp0(search_key, key) == 0) {
1095 static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
1099 state = vici_get_value(buf, 0, size, "state");
1100 if (g_strcmp0(state, "ESTABLISHED") == 0) {
1102 vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
1103 } else if (g_strcmp0(state, "DELETING") == 0) {
1105 vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
1107 DBG("Unknown event");
1113 static void process_vici_event(VICIClient *vici_client)
1116 unsigned int size = 0;
1117 unsigned int pos = 0;
1118 char temp[256] = {0,};
1119 if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
1122 buf = vici_client->rcvbuf;
1123 size = vici_client->rcv_pkt_size;
1125 pos = extract_event_name(buf, size, temp);
1126 /* TODO: remove below after debug */
1128 if (g_strcmp0(temp, "child-updown") == 0)
1129 process_child_updown(vici_client, buf + pos -1, size - pos);
1132 static void process_vici_packet(VICIClient *vici_client, char *buf)
1135 if (!vici_client || !buf)
1138 if (buf[0] == VICI_CMD_RESPONSE) {
1139 DBG("VICI_CMD_RESPONSE\n");
1140 process_vici_reply(vici_client);
1141 } else if (buf[0] == VICI_EVENT_CONFIRM) {
1142 DBG("VICI_EVENT_CONFIRM\n");
1143 } else if (buf[0] == VICI_EVENT) {
1145 process_vici_event(vici_client);
1147 DBG("Not handled [%u]", buf[0]);
1152 static gboolean process_vici_msg(GIOChannel *source,
1153 GIOCondition condition,
1156 VICIClient *vici_client = NULL;
1159 vici_client = (VICIClient *)user_data;
1163 sock = get_socket_from_source(source, condition);
1168 if(recv_vici_pkt(sock, vici_client) < 0)
1171 if (!vici_client->rcvbuf) {
1175 process_vici_packet(vici_client, vici_client->rcvbuf);
1176 g_free(vici_client->rcvbuf);
1177 vici_client->rcvbuf = NULL;
1178 vici_client->rcv_pkt_size = 0;
1183 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1185 memset(addr, 0, sizeof(*addr));
1186 addr->sun_family = AF_UNIX;
1187 strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1189 addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1191 return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1194 static int connect_socket(const char *uri)
1196 struct sockaddr_un addr;
1199 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1201 connman_error("socket() failed");
1205 len = str_to_socket_addr(uri, &addr);
1207 connman_error("str_to_socket_addr failed");
1212 if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1213 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1221 static int initialize_vici_source(VICIClient *vici_client)
1223 GIOChannel *vici_channel;
1228 vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
1229 if (vici_client->client_sock_fd < 0) {
1230 connman_error("connect_socket failed");
1234 vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
1235 if (!vici_channel) {
1236 connman_error("g_io_channel_unix_new failed");
1237 close(vici_client->client_sock_fd);
1241 vici_client->client_watch = g_io_add_watch_full(vici_channel,
1243 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1244 (GIOFunc)process_vici_msg,
1245 (gpointer)vici_client,
1247 g_io_channel_unref(vici_channel);
1251 int vici_initialize(VICIClient **vici_client)
1255 *vici_client = g_try_new0(VICIClient, 1);
1256 if (!*vici_client) {
1257 connman_error("out of memory");
1261 ret = initialize_vici_source(*vici_client);
1263 g_free(*vici_client);
1271 void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
1273 vici_client->reply_cb = reply_cb;
1274 vici_client->reply_user_data = user_data;
1277 int vici_deinitialize(VICIClient *vici_client)
1279 if (vici_client->client_watch > 0) {
1280 g_source_remove(vici_client->client_watch);
1281 vici_client->client_watch = 0;
1284 close(vici_client->client_sock_fd);
1285 g_slist_free_full(vici_client->request_list, destroy_vici_request);
1286 g_free(vici_client->rcvbuf);
1287 g_free(vici_client);