}
-static int socket_initialize(ECS_State *cs, QemuOpts *opts) {
- int fd = -1;
- Error *local_err = NULL;
-
- fd = inet_listen_opts(opts, 0, &local_err);
- if (0 > fd || error_is_set(&local_err)) {
- qerror_report_err(local_err);
- error_free(local_err);
- return -1;
- }
-
- INFO("Listen fd is %d\n", fd);
-
- qemu_set_nonblock(fd);
-
- cs->listen_fd = fd;
-
-#ifdef CONFIG_LINUX
- epoll_init(cs);
-#else
- FD_ZERO(&cs->reads);
- FD_SET(fd, &cs->reads);
-#endif
-
- make_keep_alive_msg();
-
- cs->alive_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, alive_checker, cs);
-
- timer_mod(cs->alive_timer,
- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
-
- return 0;
-}
-
#ifdef CONFIG_LINUX
static int ecs_loop(ECS_State *cs) {
int i, nfds;
#endif
+static int socket_initialize(ECS_State *cs) {
+ LOG_INFO("Listen fd is %d\n", emul_vm_base_socket);
+ g_assert(emul_vm_base_socket >= 0);
+
+ cs->listen_fd = emul_vm_base_socket;
+
+#ifdef CONFIG_LINUX
+ epoll_init(cs);
+#else
+ FD_ZERO(&cs->reads);
+ FD_SET(cs->listen_fd, &cs->reads);
+#endif
+
+ make_keep_alive_msg();
+
+ cs->alive_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, alive_checker, cs);
+
+ timer_mod(cs->alive_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + get_ticks_per_sec() * TIMER_ALIVE_S);
+
+ return 0;
+}
+
static void* ecs_initialize(void* args) {
int ret = 1;
ECS_State *cs = NULL;
QemuOpts *opts = NULL;
Error *local_err = NULL;
Monitor* mon = NULL;
- char host_port[16];
- int port = 0;
INFO("ecs starts initializing.\n");
ERR("ECS_State allocation failed.\n");
return NULL;
}
- port = get_emul_ecs_port();
- INFO("ecs port: %d\n", port);
- sprintf(host_port, "%d", port);
- qemu_opt_set(opts, "port", host_port);
- ret = socket_initialize(cs, opts);
+ cs->listen_fd = -1;
+ ret = socket_initialize(cs);
+
if (ret < 0) {
ERR("Socket initialization is failed.\n");
ecs_close(cs);
MULTI_DEBUG_CHANNEL(qemu, sdb);
-#ifdef _WIN32
-#include "qemu/main-loop.h"
-
-static void socket_close_handler( void* _fd )
-{
- int fd = (int)_fd;
- int ret;
- char buff[64];
-
- /* we want to drain the read side of the socket before closing it */
- do {
- ret = recv( fd, buff, sizeof(buff), 0 );
- } while (ret < 0 && WSAGetLastError() == WSAEINTR);
-
- if (ret < 0 && WSAGetLastError() == EWOULDBLOCK)
- return;
-
- qemu_set_fd_handler( fd, NULL, NULL, NULL );
- closesocket( fd );
-}
-
-void socket_close( int fd )
-{
- int old_errno = errno;
-
- shutdown( fd, SD_BOTH );
- /* we want to drain the socket before closing it */
- qemu_set_fd_handler( fd, socket_close_handler, NULL, (void*)fd );
-
- errno = old_errno;
-}
-
-#else /* !_WIN32 */
-
-#include <unistd.h>
+#define BUF_SIZE 64
-void socket_close( int fd )
-{
- int old_errno = errno;
-
- shutdown( fd, SHUT_RDWR );
- close( fd );
-
- errno = old_errno;
-}
-
-#endif /* !_WIN32 */
-
-int inet_strtoip(const char* str, uint32_t *ip)
-{
- int comp[4];
-
- if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
- return -1;
-
- if ((unsigned)comp[0] >= 256 ||
- (unsigned)comp[1] >= 256 ||
- (unsigned)comp[2] >= 256 ||
- (unsigned)comp[3] >= 256)
- return -1;
-
- *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
- (comp[2] << 8) | comp[3]);
- return 0;
-}
+int emul_vm_base_socket;
int check_port_bind_listen(uint32_t port)
{
struct sockaddr_in addr;
- int s = 0;
int ret = -1;
- socklen_t addrlen = sizeof(addr);
- memset(&addr, 0, addrlen);
-
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = INADDR_ANY;
- s = qemu_socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0) {
- INFO("failed to create a socket\n");
+ ret = qemu_socket(PF_INET, SOCK_STREAM, 0);
+ if (ret < 0) {
+ LOG_SEVERE("socket creation failed.\n");
return -1;
}
-#ifndef _WIN32
- int opt = 1;
- ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&opt, sizeof(int));
- if (ret < 0) {
- INFO("setsockopt failure\n");
- close(s);
+ qemu_set_nonblock(ret);
+
+ if (socket_set_fast_reuse(ret) != 0) {
+ LOG_SEVERE("It cannot be reach here.\n");
+ closesocket(ret);
return -1;
}
-#endif
- if ((bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) ||
- (listen(s, 1) < 0)) {
- /* failure */
- ret = -1;
- INFO("port(%d) listen failure\n", port);
- } else {
- /* success */
- ret = 1;
- INFO("port(%d) listen success\n", port);
+ if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
+ LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno);
+ closesocket(ret);
+ return -1;
}
-#ifdef _WIN32
- closesocket(s);
-#else
- close(s);
-#endif
+ if (listen(ret, 1) != 0) {
+ LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno);
+ closesocket(ret);
+ return -1;
+ }
return ret;
}
-#define ECS_INDEX 3
-#define SDB_GUEST_PORT 26101
-void set_base_port(void)
+static int prepare_network_port(uint32_t base_port)
{
- int tries = 10;
- int success = 0;
- uint32_t port = 26100;
- int base_port;
-
- base_port = get_emul_vm_base_port();
-
- if (base_port == 0) {
-
- for ( ; tries > 0; tries--, port += 10 ) {
- if (check_port_bind_listen(port + ECS_INDEX) < 0)
- continue;
+ int ret = -1;
+ char buf[64] = {0,};
+ if ((ret = check_port_bind_listen(base_port + ECS_TCP_INDEX)) < 0) {
+ LOG_INFO("TCP port %"PRIu32" is aleady occupied.\n",
+ base_port + ECS_TCP_INDEX);
- success = 1;
- break;
- }
+ return -1;
+ }
- if (!success) {
- INFO( "it seems too many emulator instances are running on this machine. Aborting\n" );
- exit(1);
- }
+ g_assert(ret >= 0);
- base_port = port;
- INFO( "emulator base port is %d\n", base_port);
+ sprintf(buf, "tcp:%d::26101", base_port + SDB_TCP_INDEX);
+ if (net_slirp_redir((char*)buf) < 0) {
+ LOG_WARNING("failed to redirect rule %s", buf);
+ return -1;
}
+ // save ecs socket fd as global variable
+ // FIXME: should not use global variable.
+ emul_vm_base_socket = ret;
- set_emul_vm_base_port(base_port);
+ return ret;
}
-void sdb_setup(void)
-{
- int tries = 10;
- int success = 0;
- char buf[64] = {0,};
- int number;
+static void start_sdb_noti_server(int server_port);
- number = get_device_serial_number();
+void init_sdb_and_vm_base_port(void)
+{
+ uint32_t port = -1;
- for ( ; tries > 0; tries--, number += 10 ) {
- sprintf(buf, "tcp:%d::%d", number, SDB_GUEST_PORT);
- if (net_slirp_redir((char*)buf) < 0)
+ for (port = START_VM_BASE_PORT ; port < END_VM_BASE_PORT; port += 10) {
+ if (prepare_network_port(port) < 0) {
continue;
+ }
- INFO( "SDBD established on port %d\n", number);
- success = 1;
break;
}
- INFO("redirect [%s] success\n", buf);
- if (!success) {
- INFO( "it seems too many emulator instances are running on this machine. Aborting\n" );
+ if (port >= END_VM_BASE_PORT) {
+ error_report("It seems too many emulator instances are "
+ "running on this machine. Aborting.");
exit(1);
}
+ LOG_INFO("Emulator base port is %"PRIu32".\n", port);
+
+ start_sdb_noti_server(port + SDB_UDP_NOTI_PORT_INDEX);
+ start_sdb_noti_server(port + SDB_UDP_SENSOR_INDEX);
- INFO( "Port(%d/tcp) listen for SDB\n", number);
+ set_emul_vm_base_port(port);
}
/*
struct sockaddr_in sock_addr;
int s, slen = sizeof(sock_addr);
int serial_len = 0;
- char buf[64];
+ char buf[BUF_SIZE];
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){
- INFO("socket creation error! %d\n", errno);
+ if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) == -1){
+ LOG_INFO("socket creation error! %d\n", errno);
return;
}
sock_addr.sin_addr = (client->addr).sin_addr;
if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) {
- INFO("connect error! remove this client.\n");
+ LOG_INFO("connect error! remove this client.\n");
remove_sdb_client(client);
- close(s);
+ closesocket(s);
return;
}
// send message "[4 digit message length]host:sync:emulator-26101:[0|1]"
sprintf(buf, "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state);
- INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr));
+ LOG_INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr));
if (send(s, buf, sizeof(buf), 0) == -1)
{
- INFO("send error! remove this client.\n");
+ LOG_INFO("send error! remove this client.\n");
remove_sdb_client(client);
}
- close(s);
+ closesocket(s);
}
void notify_all_sdb_clients(int state)