4 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
7 * MunKyu Im <munkyu.im@samsung.com>
8 * Jinhyung Choi <jinh0.choi@samsung.com>
9 * SeokYeon Hwnag <syeon.hwang@samsung.com>
10 * Sangho Park <sangho.p@samsung.com>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include "net_helper.h"
33 #include "qemu/osdep.h"
34 #include "qemu/sockets.h"
35 #include "net/slirp.h"
36 #include "block/nbd.h"
37 #include "qemu/error-report.h"
40 #include "emulator_common.h"
41 #include "emul_state.h"
43 #include "hw/virtio/maru_virtio_input.h"
44 #include "hw/maru_pm.h"
46 #include "new_debug_ch.h"
48 DECLARE_DEBUG_CHANNEL(net_helper);
52 #define MAX_USER_NAME_LEN 36
54 int emul_vm_base_socket;
55 static bool sdb_daemon_is_initialized = false;
56 static QemuThread thread_id;
58 int inet_strtoip(const char* str, uint32_t *ip)
62 if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
65 if ((unsigned)comp[0] >= 256 ||
66 (unsigned)comp[1] >= 256 ||
67 (unsigned)comp[2] >= 256 ||
68 (unsigned)comp[3] >= 256)
71 *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
72 (comp[2] << 8) | comp[3]);
76 int check_port_bind_listen(uint32_t port)
78 struct sockaddr_in addr;
80 addr.sin_family = AF_INET;
81 addr.sin_port = htons(port);
82 addr.sin_addr.s_addr = INADDR_ANY;
84 ret = qemu_socket(PF_INET, SOCK_STREAM, 0);
86 LOG_SEVERE("socket creation failed.\n");
90 qemu_set_nonblock(ret);
92 if (socket_set_fast_reuse(ret) != 0) {
93 LOG_SEVERE("It cannot be reach here.\n");
98 if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
99 LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno);
104 if (listen(ret, 1) != 0) {
105 LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno);
113 static int prepare_network_port(uint32_t base_port)
117 /* no need to redir if network is tap */
118 if (!is_netclient_tap_attached()) {
119 if (!hostfwd_try_add(0, NULL, base_port + SDB_TCP_INDEX,
120 NULL, SDB_GUEST_PORT)) {
121 LOG_INFO("TCP port %"PRIu32" is aleady occupied",
122 base_port + SDB_TCP_INDEX);
127 if (!hostfwd_try_add(0, NULL, base_port + GDB_TCP_INDEX,
128 NULL, GDB_GUEST_PORT)) {
129 LOG_INFO("TCP port %"PRIu32" is aleady occupied",
130 base_port + GDB_TCP_INDEX);
131 hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX);
137 if ((ret = check_port_bind_listen(base_port + ECS_TCP_INDEX)) < 0) {
138 LOG_INFO("TCP port %"PRIu32" is aleady occupied",
139 base_port + ECS_TCP_INDEX);
141 if (!is_netclient_tap_attached()) {
142 hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX);
143 hostfwd_try_remove(0, NULL, base_port + GDB_TCP_INDEX);
151 // save ecs socket fd as global variable
152 // FIXME: should not use global variable.
153 emul_vm_base_socket = ret;
158 static void start_sdb_noti_server(int server_port);
160 void init_sdb_and_vm_base_port(void)
164 for (port = START_VM_BASE_PORT ; port < END_VM_BASE_PORT; port += 10) {
165 if (prepare_network_port(port) < 0) {
172 if (port >= END_VM_BASE_PORT) {
173 error_report("It seems too many emulator instances are "
174 "running on this machine. Aborting.");
178 LOG_INFO("Emulator base port is %"PRIu32".\n", port);
180 start_sdb_noti_server(port + SDB_UDP_NOTI_PORT_INDEX);
186 * SDB Notification server
189 #define RECV_BUF_SIZE 32
190 typedef struct SDB_Noti_Server {
192 GIOChannel *server_chan;
196 typedef struct SDB_Client {
198 struct sockaddr_in addr;
199 char serial[RECV_BUF_SIZE];
201 QTAILQ_ENTRY(SDB_Client) next;
204 static QTAILQ_HEAD(SDB_ClientHead, SDB_Client)
205 clients = QTAILQ_HEAD_INITIALIZER(clients);
207 static SDB_Noti_Server *current_server;
208 static QemuMutex mutex_clients;
209 static QemuMutex mutex_request;
211 static void remove_sdb_client(SDB_Client* client)
213 if (client == NULL) {
217 qemu_mutex_lock(&mutex_clients);
219 QTAILQ_REMOVE(&clients, client, next);
221 qemu_mutex_unlock(&mutex_clients);
226 static void send_to_sdb_client(SDB_Client* client, int state)
228 struct sockaddr_in sock_addr;
229 int s, slen = sizeof(sock_addr);
233 if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) == -1){
234 LOG_INFO("socket creation error! %d\n", errno);
238 memset(&sock_addr, 0, sizeof(sock_addr));
240 sock_addr.sin_family = AF_INET;
241 sock_addr.sin_port = htons(client->port);
242 sock_addr.sin_addr = (client->addr).sin_addr;
244 if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) {
245 LOG_INFO("connect error! remove this client.\n");
246 remove_sdb_client(client);
251 memset(buf, 0, sizeof(buf));
253 serial_len = strlen(client->serial);
255 // send message "[4 digit message length]host:sync:emulator-26101:[0|1]"
256 snprintf(buf, sizeof(buf), "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state);
258 LOG_INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr));
260 if (send(s, buf, sizeof(buf), 0) == -1)
262 LOG_INFO("send error! remove this client.\n");
263 remove_sdb_client(client);
269 void notify_all_sdb_clients(int state)
271 qemu_mutex_lock(&mutex_clients);
272 SDB_Client *client, *next;
274 QTAILQ_FOREACH_SAFE(client, &clients, next, next)
276 send_to_sdb_client(client, state);
278 qemu_mutex_unlock(&mutex_clients);
282 static void add_sdb_client(struct sockaddr_in* addr, int port, const char* serial)
284 SDB_Client *cli = NULL;
285 SDB_Client *client = NULL, *next;
288 LOG_INFO("SDB_Client client's address is EMPTY.\n");
290 } else if (serial == NULL || strlen(serial) <= 0) {
291 LOG_INFO("SDB_Client client's serial is EMPTY.\n");
293 } else if (strlen(serial) > RECV_BUF_SIZE) {
294 LOG_INFO("SDB_Client client's serial is too long. %s\n", serial);
298 qemu_mutex_lock(&mutex_clients);
299 QTAILQ_FOREACH_SAFE(cli, &clients, next, next)
301 if (!strcmp(serial, cli->serial) && !strcmp(inet_ntoa(addr->sin_addr), inet_ntoa((cli->addr).sin_addr))) {
302 LOG_INFO("Client cannot be duplicated.\n");
303 qemu_mutex_unlock(&mutex_clients);
307 qemu_mutex_unlock(&mutex_clients);
309 client = g_malloc0(sizeof(SDB_Client));
310 if (NULL == client) {
311 LOG_INFO("SDB_Client allocation failed.\n");
315 memcpy(&client->addr, addr, sizeof(struct sockaddr_in));
317 strncpy(client->serial, serial, sizeof(client->serial));
318 client->serial[sizeof(client->serial) - 1] = 0;
320 qemu_mutex_lock(&mutex_clients);
322 QTAILQ_INSERT_TAIL(&clients, client, next);
324 qemu_mutex_unlock(&mutex_clients);
326 LOG_INFO("Added new sdb client. ip: %s, port: %d, serial: %s\n", inet_ntoa((client->addr).sin_addr), client->port, client->serial);
328 send_to_sdb_client(client, runstate_check(RUN_STATE_SUSPENDED));
331 #define SDB_SERVER_PORT 26097
332 static void register_sdb_server(char* readbuf, struct sockaddr_in* client_addr)
339 ret = strtok(readbuf, token);
341 LOG_INFO("command is not found.");
345 serial = strtok(NULL, token);
346 if (serial == NULL) {
347 LOG_INFO("serial is not found.");
351 port = SDB_SERVER_PORT;
353 add_sdb_client(client_addr, port, serial);
358 #define POWER_KEY 116
359 static void wakeup_guest(void)
361 // FIXME: Temporarily working model.
362 // It must be fixed as the way it works.
363 maru_hwkey_event(PRESS, POWER_KEY);
364 maru_hwkey_event(RELEASE, POWER_KEY);
367 static void suspend_lock_state(int state)
369 ecs_suspend_lock_state(state);
372 static bool is_ready(void)
375 char state_name[BUF_SIZE] = { 0, };
377 const char *sdb_path = "../../../../../tools/sdb";
378 const char *bin_dir = get_bin_path();
379 char *cmd_get_state = g_strdup_printf("\"%s%s\" -s emulator-%d get-state 2> /dev/null",
380 bin_dir, sdb_path, get_vm_device_serial_number());
382 const char *sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
383 const char *bin_dir = get_bin_path();
384 char *cmd_get_state = g_strdup_printf("\"%s%s\" -s emulator-%d get-state 2> NUL",
385 bin_dir, sdb_path, get_vm_device_serial_number());
387 fp = popen(cmd_get_state, "r");
389 LOG_WARNING("Failed to run command\n");
390 g_free(cmd_get_state);
394 if (fgets(state_name, sizeof(state_name), fp)) {
395 g_strstrip(state_name);
396 if (strncmp(state_name, "device", 6) == 0) {
397 g_free(cmd_get_state);
399 LOG_INFO("device is ready to get command");
404 g_free(cmd_get_state);
409 static void *get_user_home_path(void *args)
412 char user_name[MAX_USER_NAME_LEN] = { 0, } ;
414 int sleep_time = 500; // msec
416 const char *sdb_path = "../../../../../tools/sdb";
418 const char *sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
420 const char *bin_dir = get_bin_path();
422 qemu_mutex_lock(&mutex_request);
424 if (get_platform_default_home()) {
425 qemu_mutex_unlock(&mutex_request);
429 char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> /dev/null",
430 bin_dir, sdb_path, get_vm_device_serial_number());
431 char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> /dev/null",
432 bin_dir, sdb_path, get_vm_device_serial_number());
434 char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> NUL",
435 bin_dir, sdb_path, get_vm_device_serial_number());
436 char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> NUL",
437 bin_dir, sdb_path, get_vm_device_serial_number());
440 if (trial >= MAX_TRIAL) {
448 usleep(sleep_time * 1000);
454 //FIXME: (sdb) cannot check sdb root status
455 fp = popen(cmd_root_off, "r");
457 LOG_WARNING("Failed to run command\n");
458 g_free(cmd_root_off);
462 if (cmd_root_off != NULL) {
463 g_free(cmd_root_off);
468 fp = popen(cmd_get_home, "r");
470 LOG_WARNING("Failed to run command\n");
474 if (fgets(user_name, sizeof(user_name), fp)) {
475 g_strstrip(user_name);
476 if (strlen(user_name) > 0) {
477 char *path = g_strdup_printf("/home/%s/", user_name);
478 set_platform_default_home(path);
487 g_free(cmd_get_home);
489 if (!get_platform_default_home()) {
490 set_platform_default_home("/tmp/");
493 LOG_INFO("platform_default_user_home: %s\n", get_platform_default_home());
495 qemu_mutex_unlock(&mutex_request);
500 static void command_handler(char* readbuf, struct sockaddr_in* client_addr)
502 char command[RECV_BUF_SIZE];
503 memset(command, '\0', sizeof(command));
505 parse_val(readbuf, 0x0a, command);
507 LOG_TRACE("----------------------------------------\n");
508 LOG_TRACE("command:%s\n", command);
509 if (strcmp(command, "2\n" ) == 0) {
510 sdb_daemon_is_initialized = true;
511 if (!get_platform_default_home()) {
512 qemu_thread_create(&thread_id, "get_platform_default_home",
513 get_user_home_path, NULL, QEMU_THREAD_DETACHED);
515 } else if (strcmp(command, "5\n") == 0) {
516 register_sdb_server(readbuf, client_addr);
517 set_sdb_connection(true);
518 } else if (strcmp(command, "6\n") == 0) {
520 } else if (strcmp(command, "7\n") == 0) {
521 suspend_lock_state(SUSPEND_LOCK);
522 } else if (strcmp(command, "8\n") == 0) {
523 suspend_lock_state(SUSPEND_UNLOCK);
525 LOG_INFO("!!! unknown command : %s\n", command);
527 LOG_TRACE("========================================\n");
530 static void close_clients(void)
532 qemu_mutex_lock(&mutex_clients);
533 SDB_Client * client, *next;
535 QTAILQ_FOREACH_SAFE(client, &clients, next, next)
537 QTAILQ_REMOVE(&clients, client, next);
545 qemu_mutex_unlock(&mutex_clients);
548 static void close_server(void)
550 if (current_server == NULL) {
556 if (current_server->server_fd > 0) {
557 if (current_server->server_tag) {
558 g_source_remove(current_server->server_tag);
559 current_server->server_tag = 0;
561 if (current_server->server_chan) {
562 g_io_channel_unref(current_server->server_chan);
564 closesocket(current_server->server_fd);
567 g_free(current_server);
569 qemu_mutex_destroy(&mutex_clients);
572 static gboolean sdb_noti_read(GIOChannel *channel, GIOCondition cond, void *opaque)
575 struct sockaddr_in client_addr;
576 socklen_t client_len = sizeof(client_addr);
577 char readbuf[RECV_BUF_SIZE + 1];
578 SDB_Noti_Server *server = opaque;
580 memset(&readbuf, 0, sizeof(readbuf));
582 recv_cnt = recvfrom(server->server_fd, readbuf, RECV_BUF_SIZE, 0,
583 (struct sockaddr*) &client_addr, &client_len);
586 command_handler((char*)readbuf, &client_addr);
587 } else if (recv_cnt == 0) {
588 LOG_INFO("noti server recvfrom returned 0.\n");
591 errno = WSAGetLastError();
593 LOG_TRACE("recvfrom error case (it can be from non-blocking socket): %d", errno);
599 static int create_UDP_server(SDB_Noti_Server *server, int port)
601 struct sockaddr_in server_addr;
604 if ((server->server_fd = qemu_socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
605 LOG_INFO("create listen socket error:%d\n", errno);
609 memset(&server_addr, '\0', sizeof(server_addr));
610 server_addr.sin_family = PF_INET;
611 server_addr.sin_addr.s_addr = INADDR_ANY;
612 server_addr.sin_port = htons(port);
614 qemu_set_nonblock(server->server_fd);
616 if (qemu_setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
617 LOG_INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno);
621 if (bind(server->server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
622 LOG_INFO("sdb noti server bind error: %d", errno);
629 static GIOChannel *io_channel_from_socket(int fd)
638 chan = g_io_channel_win32_new_socket(fd);
640 chan = g_io_channel_unix_new(fd);
643 g_io_channel_set_encoding(chan, NULL, NULL);
644 g_io_channel_set_buffered(chan, FALSE);
649 static void sdb_noti_server_notify_exit(Notifier *notifier, void *data)
651 LOG_INFO("shutdown sdb notification server.\n");
655 static Notifier sdb_noti_server_exit = { .notify = sdb_noti_server_notify_exit };
657 static void start_sdb_noti_server(int server_port)
659 SDB_Noti_Server *server;
662 LOG_INFO("start sdb noti server thread.\n");
664 server = g_malloc0(sizeof(SDB_Noti_Server));
665 if (server == NULL) {
666 LOG_INFO("SDB Notification server allocation is failed.\n");
670 ret = create_UDP_server(server, server_port);
672 LOG_INFO("failed to create UDP server\n");
679 qemu_mutex_init(&mutex_clients);
680 qemu_mutex_init(&mutex_request);
682 server->server_chan = io_channel_from_socket(server->server_fd);
683 server->server_tag = g_io_add_watch(server->server_chan, G_IO_IN, sdb_noti_read, server);
685 current_server = server;
687 LOG_INFO("success to bind port[127.0.0.1:%d/udp] for sdb noti server in host \n", server_port);
689 emulator_add_exit_notifier(&sdb_noti_server_exit);
692 bool is_sdb_daemon_initialized(void)
694 return sdb_daemon_is_initialized;