net: add checking device state before run command
[sdk/emulator/qemu.git] / tizen / src / util / net_helper.c
1 /*
2  * Net helper
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact:
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>
11  *
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.
16  *
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.
21  *
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.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include "net_helper.h"
32
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"
38
39 #include "emulator.h"
40 #include "emulator_common.h"
41 #include "emul_state.h"
42
43 #include "hw/virtio/maru_virtio_input.h"
44 #include "hw/maru_pm.h"
45 #include "ecs/ecs.h"
46 #include "new_debug_ch.h"
47
48 DECLARE_DEBUG_CHANNEL(net_helper);
49
50 #define BUF_SIZE 64
51 #define MAX_TRIAL 20
52 #define MAX_USER_NAME_LEN 36
53
54 int emul_vm_base_socket;
55 static bool sdb_daemon_is_initialized = false;
56 static QemuThread thread_id;
57
58 int inet_strtoip(const char*  str, uint32_t  *ip)
59 {
60     int  comp[4];
61
62     if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
63         return -1;
64
65     if ((unsigned)comp[0] >= 256 ||
66             (unsigned)comp[1] >= 256 ||
67             (unsigned)comp[2] >= 256 ||
68             (unsigned)comp[3] >= 256)
69         return -1;
70
71     *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
72             (comp[2] << 8)  |  comp[3]);
73     return 0;
74 }
75
76 int check_port_bind_listen(uint32_t port)
77 {
78     struct sockaddr_in addr;
79     int ret = -1;
80     addr.sin_family = AF_INET;
81     addr.sin_port = htons(port);
82     addr.sin_addr.s_addr = INADDR_ANY;
83
84     ret = qemu_socket(PF_INET, SOCK_STREAM, 0);
85     if (ret < 0) {
86         LOG_SEVERE("socket creation failed.\n");
87         return -1;
88     }
89
90     qemu_set_nonblock(ret);
91
92     if (socket_set_fast_reuse(ret) != 0) {
93         LOG_SEVERE("It cannot be reach here.\n");
94         closesocket(ret);
95         return -1;
96     }
97
98     if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
99         LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno);
100         closesocket(ret);
101         return -1;
102     }
103
104     if (listen(ret, 1) != 0) {
105         LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno);
106         closesocket(ret);
107         return -1;
108     }
109
110     return ret;
111 }
112
113 static int prepare_network_port(uint32_t base_port)
114 {
115     int ret = -1;
116
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);
123
124             return -1;
125         }
126
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);
132
133             return -1;
134         }
135     }
136
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);
140
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);
144         }
145
146         return -1;
147     }
148
149     g_assert(ret >= 0);
150
151     // save ecs socket fd as global variable
152     // FIXME: should not use global variable.
153     emul_vm_base_socket = ret;
154
155     return ret;
156 }
157
158 static void start_sdb_noti_server(int server_port);
159
160 void init_sdb_and_vm_base_port(void)
161 {
162     uint32_t port = -1;
163
164     for (port = START_VM_BASE_PORT ; port < END_VM_BASE_PORT; port += 10) {
165         if (prepare_network_port(port) < 0) {
166             continue;
167         }
168
169         break;
170     }
171
172     if (port >= END_VM_BASE_PORT) {
173         error_report("It seems too many emulator instances are "
174                 "running on this machine. Aborting.");
175         exit(1);
176     }
177
178     LOG_INFO("Emulator base port is %"PRIu32".\n", port);
179
180     start_sdb_noti_server(port + SDB_UDP_NOTI_PORT_INDEX);
181
182     vm_base_port = port;
183 }
184
185 /*
186  * SDB Notification server
187  */
188
189 #define RECV_BUF_SIZE 32
190 typedef struct SDB_Noti_Server {
191     int server_fd;
192     GIOChannel *server_chan;
193     guint server_tag;
194 } SDB_Noti_Server;
195
196 typedef struct SDB_Client {
197     int port;
198     struct sockaddr_in addr;
199     char serial[RECV_BUF_SIZE];
200
201     QTAILQ_ENTRY(SDB_Client) next;
202 } SDB_Client;
203
204 static QTAILQ_HEAD(SDB_ClientHead, SDB_Client)
205 clients = QTAILQ_HEAD_INITIALIZER(clients);
206
207 static SDB_Noti_Server *current_server;
208 static QemuMutex mutex_clients;
209 static QemuMutex mutex_request;
210
211 static void remove_sdb_client(SDB_Client* client)
212 {
213     if (client == NULL) {
214         return;
215     }
216
217     qemu_mutex_lock(&mutex_clients);
218
219     QTAILQ_REMOVE(&clients, client, next);
220
221     qemu_mutex_unlock(&mutex_clients);
222
223     g_free(client);
224 }
225
226 static void send_to_sdb_client(SDB_Client* client, int state)
227 {
228     struct sockaddr_in sock_addr;
229     int s, slen = sizeof(sock_addr);
230     int serial_len = 0;
231     char buf[BUF_SIZE];
232
233     if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) == -1){
234           LOG_INFO("socket creation error! %d\n", errno);
235           return;
236     }
237
238     memset(&sock_addr, 0, sizeof(sock_addr));
239
240     sock_addr.sin_family = AF_INET;
241     sock_addr.sin_port = htons(client->port);
242     sock_addr.sin_addr = (client->addr).sin_addr;
243
244     if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) {
245         LOG_INFO("connect error! remove this client.\n");
246         remove_sdb_client(client);
247         closesocket(s);
248         return;
249     }
250
251     memset(buf, 0, sizeof(buf));
252
253     serial_len = strlen(client->serial);
254
255     // send message "[4 digit message length]host:sync:emulator-26101:[0|1]"
256     sprintf(buf, "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state);
257
258     LOG_INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr));
259
260     if (send(s, buf, sizeof(buf), 0) == -1)
261     {
262         LOG_INFO("send error! remove this client.\n");
263         remove_sdb_client(client);
264     }
265
266     closesocket(s);
267 }
268
269 void notify_all_sdb_clients(int state)
270 {
271     qemu_mutex_lock(&mutex_clients);
272     SDB_Client *client, *next;
273
274     QTAILQ_FOREACH_SAFE(client, &clients, next, next)
275     {
276         send_to_sdb_client(client, state);
277     }
278     qemu_mutex_unlock(&mutex_clients);
279
280 }
281
282 static void add_sdb_client(struct sockaddr_in* addr, int port, const char* serial)
283 {
284     SDB_Client *cli = NULL;
285     SDB_Client *client = NULL, *next;
286
287     if (addr == NULL) {
288         LOG_INFO("SDB_Client client's address is EMPTY.\n");
289         return;
290     } else if (serial == NULL || strlen(serial) <= 0) {
291         LOG_INFO("SDB_Client client's serial is EMPTY.\n");
292         return;
293     } else if (strlen(serial) > RECV_BUF_SIZE) {
294         LOG_INFO("SDB_Client client's serial is too long. %s\n", serial);
295         return;
296     }
297
298     qemu_mutex_lock(&mutex_clients);
299     QTAILQ_FOREACH_SAFE(cli, &clients, next, next)
300     {
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);
304             return;
305         }
306     }
307     qemu_mutex_unlock(&mutex_clients);
308
309     client = g_malloc0(sizeof(SDB_Client));
310     if (NULL == client) {
311         LOG_INFO("SDB_Client allocation failed.\n");
312         return;
313     }
314
315     memcpy(&client->addr, addr, sizeof(struct sockaddr_in));
316     client->port = port;
317     strcpy(client->serial, serial);
318
319     qemu_mutex_lock(&mutex_clients);
320
321     QTAILQ_INSERT_TAIL(&clients, client, next);
322
323     qemu_mutex_unlock(&mutex_clients);
324
325     LOG_INFO("Added new sdb client. ip: %s, port: %d, serial: %s\n", inet_ntoa((client->addr).sin_addr), client->port, client->serial);
326
327     send_to_sdb_client(client, runstate_check(RUN_STATE_SUSPENDED));
328 }
329
330 static int parse_val(char* buff, unsigned char data, char* parsbuf)
331 {
332     int count = 0;
333
334     while (1) {
335         if (count > 12) {
336             return -1;
337         }
338
339         if (buff[count] == data) {
340             count++;
341             strncpy(parsbuf, buff, count);
342             return count;
343         }
344
345         count++;
346     }
347
348     return 0;
349 }
350
351 #define SDB_SERVER_PORT 26097
352 static void register_sdb_server(char* readbuf, struct sockaddr_in* client_addr)
353 {
354     int port = 0;
355     char token[] = "\n";
356     char* ret = NULL;
357     char* serial = NULL;
358
359     ret = strtok(readbuf, token);
360     if (ret == NULL) {
361         LOG_INFO("command is not found.");
362         return;
363     }
364
365     serial = strtok(NULL, token);
366     if (serial == NULL) {
367         LOG_INFO("serial is not found.");
368         return;
369     }
370
371     port = SDB_SERVER_PORT;
372
373     add_sdb_client(client_addr, port, serial);
374 }
375
376 #define PRESS     1
377 #define RELEASE   2
378 #define POWER_KEY 116
379 static void wakeup_guest(void)
380 {
381     // FIXME: Temporarily working model.
382     // It must be fixed as the way it works.
383     maru_hwkey_event(PRESS, POWER_KEY);
384     maru_hwkey_event(RELEASE, POWER_KEY);
385 }
386
387 static void suspend_lock_state(int state)
388 {
389     ecs_suspend_lock_state(state);
390 }
391
392 static bool is_ready(void)
393 {
394     FILE *fp;
395     char state_name[BUF_SIZE] = { 0, };
396 #ifndef CONFIG_WIN32
397     const char *sdb_path = "../../../../../tools/sdb";
398     const char *bin_dir = get_bin_path();
399     char *cmd_get_state = g_strdup_printf("\"%s%s\" -s emulator-%d get-state 2> /dev/null",
400             bin_dir, sdb_path, get_vm_device_serial_number());
401 #else
402     const char *sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
403     const char *bin_dir = get_bin_path();
404     char *cmd_get_state = g_strdup_printf("\"%s%s\" -s emulator-%d get-state 2> NUL",
405             bin_dir, sdb_path, get_vm_device_serial_number());
406 #endif
407     fp = popen(cmd_get_state, "r");
408     if (fp == NULL) {
409         LOG_WARNING("Failed to run command\n");
410         g_free(cmd_get_state);
411         return false;
412     }
413
414     if (fgets(state_name, sizeof(state_name), fp)) {
415         g_strstrip(state_name);
416         if (strncmp(state_name, "device", 6) == 0) {
417             g_free(cmd_get_state);
418             pclose(fp);
419             LOG_INFO("device is ready to get command");
420             return true;
421         }
422     }
423
424     g_free(cmd_get_state);
425     pclose(fp);
426     return false;
427 }
428
429 static void *get_user_home_path(void *args)
430 {
431     FILE *fp;
432     char user_name[MAX_USER_NAME_LEN] = { 0, } ;
433     int trial = 0;
434     int sleep_time = 500; // msec
435 #ifndef CONFIG_WIN32
436     const char *sdb_path = "../../../../../tools/sdb";
437 #else
438     const char *sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
439 #endif
440     const char *bin_dir = get_bin_path();
441
442     qemu_mutex_lock(&mutex_request);
443
444     if (get_platform_default_home()) {
445         return NULL;
446     }
447 #ifndef CONFIG_WIN32
448     char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> /dev/null",
449             bin_dir, sdb_path, get_vm_device_serial_number());
450     char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> /dev/null",
451             bin_dir, sdb_path, get_vm_device_serial_number());
452 #else
453     char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> NUL",
454             bin_dir, sdb_path, get_vm_device_serial_number());
455     char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> NUL",
456             bin_dir, sdb_path, get_vm_device_serial_number());
457 #endif
458     while (true) {
459         if (trial >= MAX_TRIAL) {
460             sleep_time = 2000;
461         } else {
462             trial++;
463         }
464 #ifdef CONFIG_WIN32
465         Sleep(sleep_time);
466 #else
467         usleep(sleep_time * 1000);
468 #endif
469          if (!is_ready()) {
470              continue;
471          }
472
473         //FIXME: (sdb) cannot check sdb root status
474         fp = popen(cmd_root_off, "r");
475         if (fp == NULL) {
476             LOG_WARNING("Failed to run command\n");
477             g_free(cmd_root_off);
478             break;
479         }
480         g_free(cmd_root_off);
481         pclose(fp);
482
483         fp = popen(cmd_get_home, "r");
484         if (fp == NULL) {
485             LOG_WARNING("Failed to run command\n");
486             break;
487         }
488
489         if (fgets(user_name, sizeof(user_name), fp)) {
490             g_strstrip(user_name);
491             if (strlen(user_name) > 0) {
492                 char *path = g_strdup_printf("/home/%s/", user_name);
493                 set_platform_default_home(path);
494                 g_free(path);
495                 pclose(fp);
496                 break;
497             }
498         }
499
500         pclose(fp);
501     }
502     g_free(cmd_get_home);
503
504     if (!get_platform_default_home()) {
505         set_platform_default_home("/tmp/");
506     }
507
508     LOG_INFO("platform_default_user_home: %s\n", get_platform_default_home());
509
510     qemu_mutex_unlock(&mutex_request);
511
512     return NULL;
513 }
514
515 static void command_handler(char* readbuf, struct sockaddr_in* client_addr)
516 {
517     char command[RECV_BUF_SIZE];
518     memset(command, '\0', sizeof(command));
519
520     parse_val(readbuf, 0x0a, command);
521
522     LOG_TRACE("----------------------------------------\n");
523     LOG_TRACE("command:%s\n", command);
524     if (strcmp(command, "2\n" ) == 0) {
525         sdb_daemon_is_initialized = true;
526         if (!get_platform_default_home()) {
527             qemu_thread_create(&thread_id, "get_platform_default_home",
528                     get_user_home_path, NULL, QEMU_THREAD_DETACHED);
529         }
530     } else if (strcmp(command, "5\n") == 0) {
531         register_sdb_server(readbuf, client_addr);
532         set_sdb_connection(true);
533     } else if (strcmp(command, "6\n") == 0) {
534         wakeup_guest();
535     } else if (strcmp(command, "7\n") == 0) {
536         suspend_lock_state(SUSPEND_LOCK);
537     } else if (strcmp(command, "8\n") == 0) {
538         suspend_lock_state(SUSPEND_UNLOCK);
539     } else {
540         LOG_INFO("!!! unknown command : %s\n", command);
541     }
542     LOG_TRACE("========================================\n");
543 }
544
545 static void close_clients(void)
546 {
547     qemu_mutex_lock(&mutex_clients);
548     SDB_Client * client, *next;
549
550     QTAILQ_FOREACH_SAFE(client, &clients, next, next)
551     {
552         QTAILQ_REMOVE(&clients, client, next);
553
554         if (NULL != client)
555         {
556             g_free(client);
557         }
558     }
559
560     qemu_mutex_unlock(&mutex_clients);
561 }
562
563 static void close_server(void)
564 {
565     if (current_server == NULL) {
566         return;
567     }
568
569     close_clients();
570
571     if (current_server->server_fd > 0) {
572         if (current_server->server_tag) {
573             g_source_remove(current_server->server_tag);
574             current_server->server_tag = 0;
575         }
576         if (current_server->server_chan) {
577             g_io_channel_unref(current_server->server_chan);
578         }
579         closesocket(current_server->server_fd);
580     }
581
582     g_free(current_server);
583
584     qemu_mutex_destroy(&mutex_clients);
585 }
586
587 static gboolean sdb_noti_read(GIOChannel *channel, GIOCondition cond, void *opaque)
588 {
589     int recv_cnt = 0;
590     struct sockaddr_in client_addr;
591     socklen_t client_len = sizeof(client_addr);
592     char readbuf[RECV_BUF_SIZE + 1];
593     SDB_Noti_Server *server = opaque;
594
595     memset(&readbuf, 0, sizeof(readbuf));
596
597     recv_cnt = recvfrom(server->server_fd, readbuf, RECV_BUF_SIZE, 0,
598                         (struct sockaddr*) &client_addr, &client_len);
599
600     if (recv_cnt > 0) {
601         command_handler((char*)readbuf, &client_addr);
602     } else if (recv_cnt == 0) {
603         LOG_INFO("noti server recvfrom returned 0.\n");
604     } else {
605 #ifdef _WIN32
606         errno = WSAGetLastError();
607 #endif
608         LOG_TRACE("recvfrom error case (it can be from non-blocking socket): %d", errno);
609     }
610
611     return TRUE;
612 }
613
614 static int create_UDP_server(SDB_Noti_Server *server, int port)
615 {
616     struct sockaddr_in server_addr;
617     int opt = 1;
618
619     if ((server->server_fd = qemu_socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
620         LOG_INFO("create listen socket error:%d\n", errno);
621         return -1;
622     }
623
624     memset(&server_addr, '\0', sizeof(server_addr));
625     server_addr.sin_family = PF_INET;
626     server_addr.sin_addr.s_addr = INADDR_ANY;
627     server_addr.sin_port = htons(port);
628
629     qemu_set_nonblock(server->server_fd);
630
631     if (qemu_setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
632         LOG_INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno);
633         return -1;
634     }
635
636     if (bind(server->server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
637         LOG_INFO("sdb noti server bind error: %d", errno);
638         return -1;
639     }
640
641     return 0;
642 }
643
644 static GIOChannel *io_channel_from_socket(int fd)
645 {
646     GIOChannel *chan;
647
648     if (fd == -1) {
649         return NULL;
650     }
651
652 #ifdef _WIN32
653     chan = g_io_channel_win32_new_socket(fd);
654 #else
655     chan = g_io_channel_unix_new(fd);
656 #endif
657
658     g_io_channel_set_encoding(chan, NULL, NULL);
659     g_io_channel_set_buffered(chan, FALSE);
660
661     return chan;
662 }
663
664 static void sdb_noti_server_notify_exit(Notifier *notifier, void *data)
665 {
666     LOG_INFO("shutdown sdb notification server.\n");
667     close_server();
668 }
669
670 static Notifier sdb_noti_server_exit = { .notify = sdb_noti_server_notify_exit };
671
672 static void start_sdb_noti_server(int server_port)
673 {
674     SDB_Noti_Server *server;
675     int ret;
676
677     LOG_INFO("start sdb noti server thread.\n");
678
679     server = g_malloc0(sizeof(SDB_Noti_Server));
680     if (server == NULL) {
681         LOG_INFO("SDB Notification server allocation is failed.\n");
682         return;
683     }
684
685     ret = create_UDP_server(server, server_port);
686     if (ret < 0) {
687         LOG_INFO("failed to create UDP server\n");
688         close_server();
689         return;
690     }
691
692     qemu_mutex_init(&mutex_clients);
693     qemu_mutex_init(&mutex_request);
694
695     server->server_chan = io_channel_from_socket(server->server_fd);
696     server->server_tag = g_io_add_watch(server->server_chan, G_IO_IN, sdb_noti_read, server);
697
698     current_server = server;
699
700     LOG_INFO("success to bind port[127.0.0.1:%d/udp] for sdb noti server in host \n", server_port);
701
702     emulator_add_exit_notifier(&sdb_noti_server_exit);
703 }
704
705 bool is_sdb_daemon_initialized(void)
706 {
707     return sdb_daemon_is_initialized;
708 }