int multirom_ui(struct multirom_status *s, struct multirom_rom **to_boot) { if(multirom_init_fb(s->rotation) < 0) return UI_EXIT_BOOT_ROM; fb_freeze(1); mrom_status = s; exit_ui_code = -1; selected_rom = NULL; active_msgbox = NULL; multirom_ui_setup_colors(s->colors, &CLR_PRIMARY, &CLR_SECONDARY); themes_info = multirom_ui_init_themes(); if((cur_theme = multirom_ui_select_theme(themes_info, fb_width, fb_height)) == NULL) { fb_freeze(0); ERROR("Couldn't find theme for resolution %dx%d!\n", fb_width, fb_height); fb_add_text(0, 0, WHITE, SIZE_SMALL, "Couldn't find theme for resolution %dx%d!\nPress POWER to reboot.", fb_width, fb_height); fb_draw(); fb_clear(); fb_close(); start_input_thread(); while(wait_for_key() != KEY_POWER); stop_input_thread(); return UI_EXIT_REBOOT; } workers_start(); multirom_ui_init_header(); multirom_ui_switch(TAB_INTERNAL); add_touch_handler(&multirom_ui_touch_handler, NULL); start_input_thread(); keyaction_enable(1); keyaction_set_destroy_msgbox_handle(multirom_ui_destroy_msgbox); multirom_set_brightness(s->brightness); fb_freeze(0); if(s->auto_boot_rom && s->auto_boot_seconds > 0) multirom_ui_auto_boot(); else fb_draw(); while(1) { pthread_mutex_lock(&exit_code_mutex); if(exit_ui_code != -1) { pthread_mutex_unlock(&exit_code_mutex); break; } if(loop_act & LOOP_UPDATE_USB) { multirom_find_usb_roms(mrom_status); if(themes_info->data->selected_tab == TAB_USB) multirom_ui_tab_rom_update_usb(themes_info->data->tab_data); loop_act &= ~(LOOP_UPDATE_USB); } if(loop_act & LOOP_START_PONG) { loop_act &= ~(LOOP_START_PONG); keyaction_enable(0); input_push_context(); fb_push_context(); pong(); fb_pop_context(); input_pop_context(); keyaction_enable(1); } if(loop_act & LOOP_CHANGE_CLR) { fb_freeze(1); multirom_ui_setup_colors(s->colors, &CLR_PRIMARY, &CLR_SECONDARY); // force redraw tab int tab = themes_info->data->selected_tab; themes_info->data->selected_tab = -1; multirom_ui_destroy_tab(tab); multirom_ui_switch(tab); fb_freeze(0); fb_draw(); loop_act &= ~(LOOP_CHANGE_CLR); } pthread_mutex_unlock(&exit_code_mutex); usleep(100000); } keyaction_enable(0); keyaction_clear(); rm_touch_handler(&multirom_ui_touch_handler, NULL); fb_create_msgbox(500*DPI_MUL, 250*DPI_MUL, CLR_PRIMARY); switch(exit_ui_code) { case UI_EXIT_BOOT_ROM: *to_boot = selected_rom; fb_msgbox_add_text(-1, 40*DPI_MUL, SIZE_BIG, "Booting ROM..."); fb_msgbox_add_text(-1, -1, SIZE_NORMAL, selected_rom->name); break; case UI_EXIT_REBOOT: case UI_EXIT_REBOOT_RECOVERY: case UI_EXIT_REBOOT_BOOTLOADER: fb_msgbox_add_text(-1, -1, SIZE_BIG, "Rebooting..."); break; case UI_EXIT_SHUTDOWN: fb_msgbox_add_text(-1, -1, SIZE_BIG, "Shutting down..."); break; } fb_draw(); fb_freeze(1); cur_theme->destroy(themes_info->data); int i; for(i = 0; i < TAB_COUNT; ++i) { button_destroy(themes_info->data->tab_btns[i]); themes_info->data->tab_btns[i] = NULL; } stop_input_thread(); multirom_ui_destroy_tab(themes_info->data->selected_tab); multirom_ui_free_themes(themes_info); themes_info = NULL; workers_stop(); fb_clear(); #if MR_DEVICE_HOOKS >= 2 mrom_hook_before_fb_close(); #endif fb_close(); return exit_ui_code; }
void accept_thread(void *asdf) { sigset_t sigs_to_block; int e, n; struct pollfd *acceptpfd = NULL; struct listen_t **acceptpl = NULL; int listen_n = 0; int poll_n = 0; struct listen_t *l; pthreads_profiling_reset("accept"); sigemptyset(&sigs_to_block); sigaddset(&sigs_to_block, SIGALRM); sigaddset(&sigs_to_block, SIGINT); sigaddset(&sigs_to_block, SIGTERM); sigaddset(&sigs_to_block, SIGQUIT); sigaddset(&sigs_to_block, SIGHUP); sigaddset(&sigs_to_block, SIGURG); sigaddset(&sigs_to_block, SIGPIPE); sigaddset(&sigs_to_block, SIGUSR1); sigaddset(&sigs_to_block, SIGUSR2); pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL); /* start the accept thread, which will start server threads */ hlog(LOG_INFO, "Accept thread starting..."); /* we allocate a worker structure to be used within the accept thread * for parsing incoming UDP packets and passing them on to the dupecheck * thread. */ udp_worker = worker_alloc(); udp_worker->id = 81; /* we also need a client structure to be used with incoming * HTTP position uploads */ udp_pseudoclient = pseudoclient_setup(81); udp_pseudoclient->flags |= CLFLAGS_UDPSUBMIT; accept_reconfiguring = 1; while (!accept_shutting_down) { if (accept_reconfiguring) { accept_reconfiguring = 0; listen_n -= close_removed_listeners(); /* start listening on the sockets */ listen_n += open_missing_listeners(); if (listen_n < 1) { hlog(LOG_CRIT, "Failed to listen on any ports."); exit(2); } /* reconfiguration must scan old clients against ACL */ rescan_client_acls(); /* how many are we polling */ poll_n = 0; for (l = listen_list; (l); l = l->next) if (!l->corepeer) poll_n++; hlog(LOG_DEBUG, "Generating polling list for %d/%d listeners...", poll_n, listen_n); /* array of FDs for poll() */ if (acceptpfd) hfree(acceptpfd); acceptpfd = hmalloc(poll_n * sizeof(*acceptpfd)); /* array of listeners */ if (acceptpl) hfree(acceptpl); acceptpl = hmalloc(poll_n * sizeof(*acceptpl)); n = 0; for (l = listen_list; (l); l = l->next) { /* The accept thread does not poll() UDP sockets for core peers. * Worker 0 takes care of that, and processes the incoming packets. */ if (l->corepeer) { hlog(LOG_DEBUG, "... %d: fd %d (%s) - not polled, is corepeer", n, (l->udp) ? l->udp->fd : l->fd, l->addr_s); continue; } int fd; if (l->udp) { l->udp->polled = 1; fd = l->udp->fd; } else { fd = l->fd; } hlog(LOG_DEBUG, "... %d: fd %d (%s)", n, fd, l->addr_s); acceptpfd[n].fd = fd; acceptpfd[n].events = POLLIN|POLLPRI|POLLERR|POLLHUP; acceptpl[n] = l; n++; } hlog(LOG_INFO, "Accept thread ready."); /* stop the dupechecking and uplink threads while adjusting * the amount of workers... they walk the worker list, and * might get confused when workers are stopped or started. */ if (workers_running != workers_configured) { uplink_stop(); dupecheck_stop(); workers_start(); dupecheck_start(); uplink_start(); } /* * generate UDP peer clients */ peerip_clients_close(); if (peerip_config) peerip_clients_config(); /* accept liveupgrade clients */ if (liveupgrade_status) accept_liveupgrade_accept(); } /* check for new connections */ e = poll(acceptpfd, poll_n, 200); if (e == 0) continue; if (e < 0) { if (errno == EINTR) continue; hlog(LOG_ERR, "poll() on accept failed: %s (continuing)", strerror(errno)); continue; } /* now, which socket was that on? */ for (n = 0; n < poll_n; n++) { l = acceptpl[n]; if (!(l) || (l->udp ? l->udp->fd : l->fd) != acceptpfd[n].fd) { hlog(LOG_CRIT, "accept_thread: polling list and listener list do mot match!"); exit(1); } if (acceptpfd[n].revents) { if (l->udp) accept_udp_recv(l); /* receive UDP packets */ else do_accept(l); /* accept a single connection */ } } } if (accept_shutting_down == 2) worker_shutdown_clients = cJSON_CreateArray(); hlog(LOG_DEBUG, "Accept thread shutting down listening sockets and worker threads..."); uplink_stop(); close_listeners(); dupecheck_stop(); http_shutting_down = 1; workers_stop(accept_shutting_down); hfree(acceptpfd); hfree(acceptpl); acceptpfd = NULL; acceptpl = NULL; /* free up the pseudo-client */ client_free(udp_pseudoclient); udp_pseudoclient = NULL; /* free up the pseudo-worker structure, after dupecheck is long dead */ worker_free_buffers(udp_worker); hfree(udp_worker); udp_worker = NULL; }