/* ======================================= 主程序 ======================================= */ int main (int argc, char *argv[]) { CR_NOUSE(argc); CR_NOUSE(argv); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_CUI)) return (QST_ERROR); SetConsoleTitleA(WIN_TITLE); sint_t x1, y1; uint_t ww, hh; /* 初始化窗口 */ s_hcui = GetStdHandle(STD_OUTPUT_HANDLE); if (s_hcui == INVALID_HANDLE_VALUE) return (QST_ERROR); s_hwnd = GetConsoleWindow(); if (s_hwnd == NULL) return (QST_ERROR); misc_desk_init(WIN_ICONF, &x1, &y1, &ww, &hh, QSRV_DEF_WIDTH, QSRV_DEF_HEIGHT); misc_cui_setwin(s_hwnd, s_hcui, x1, y1, ww, hh); sINIu* ini; uint_t temp; ansi_t* text; int16u port = QST_DEF_PORT; ansi_t* addr = QST_DEF_ADDR; uint_t count = QST_DEF_CLIENT; /* 读取参数 */ text = file_load_as_strA(QST_CFG_STARTUP); if (text != NULL) { ini = ini_parseU(text); mem_free(text); text = NULL; if (ini != NULL) { text = ini_key_stringU("serv::bind", ini); if (text != NULL) addr = text; temp = ini_key_intxU("serv::port", QST_DEF_PORT, ini); if (temp > 1024 && temp < 32768) port = (int16u)temp; temp = ini_key_intxU("serv::count", QST_DEF_CLIENT, ini); if (temp > 0 && temp <= QST_MAX_CLIENT) count = temp; ini_closeU(ini); } } socket_t serv; sQstWork* work; /* 建立工作单元组 */ work = qst_wrk_create(count); if (work == NULL) return (QST_ERROR); /* 初始化网络 */ if (!socket_init()) return (QST_ERROR); serv = server_tcp_open(addr, port); TRY_FREE(text); if (serv == NULL) return (QST_ERROR); /* 初始化锁 */ mtlock_init(&s_qst_lck_shw); mtlock_init(&s_qst_lck_wrk); int16u logo_color; /* 建立颜色值 */ logo_color = cui_make_attr(0, CR_CUI_TEXT_LIGHT | CR_CUI_TEXT_GREEN | CR_CUI_TEXT_RED | CR_CUI_TEXT_BLUE); s_qst_clr_cin = cui_make_attr(0, CR_CUI_TEXT_LIGHT | CR_CUI_TEXT_GREEN | CR_CUI_TEXT_RED); s_qst_clr_say = cui_make_attr(0, CR_CUI_TEXT_LIGHT | CR_CUI_TEXT_GREEN); s_qst_clr_out = cui_make_attr(0, CR_CUI_TEXT_LIGHT | CR_CUI_TEXT_RED); /* 工作循环 */ cui_set_color(logo_color); printf("######################################\n"); printf("## QUESTLAB BROADCAST SERVER ##\n"); printf("######################################\n"); while (!s_quit) { ansi_t* ptr; bool_t okay; ansi_t* name; socket_t netw; /* 接受一个客户端 */ netw = server_tcp_accept(serv); if (netw == NULL) continue; /* 接收客户端名称 */ socket_set_timeout(netw, -1, QST_TCP_TOUT); name = netw_cmd_recv(netw); if (name == NULL) { socket_close(netw); continue; } /* 客户端名称过滤 */ if (str_lenA(name) > QST_MAX_NAME) { netw_ack_send(netw, FALSE); netw_cli_close(netw); mem_free(name); continue; } ptr = name; okay = TRUE; while (*ptr != NIL) { if (is_cntrlA(*ptr++)) { okay = FALSE; break; } } if (!okay) { netw_ack_send(netw, FALSE); netw_cli_close(netw); mem_free(name); continue; } /* 启动一个工作单元 */ if (!qst_wrk_wakeup(work, name, netw, qst_srv_main)) { netw_cli_close(netw); mem_free(name); continue; } } return (QST_OKAY); }
/* ======================================= WinMain 程序入口 ======================================= */ int WINAPI WinMain ( __CR_IN__ HINSTANCE curt_app, __CR_IN__ HINSTANCE prev_app, __CR_IN__ LPSTR cmd_line, __CR_IN__ int cmd_show ) { CR_NOUSE(prev_app); CR_NOUSE(cmd_line); CR_NOUSE(cmd_show); /* 只允许一个例程 */ if (misc_is_running(EXE_XNAME)) return (QST_ERROR); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_GUI)) return (QST_ERROR); mem_zero(&s_wrk_ctx, sizeof(s_wrk_ctx)); sint_t x1, y1; uint_t ww, hh; /* 生成一个可变大小的窗口 */ mtlock_init(&s_wrk_ctx.lock); qst_load_cfg(&s_wrk_ctx.cfgs); misc_desk_init(WIN_ICONF, &x1, &y1, &ww, &hh, QV2D_DEF_WIDTH, QV2D_DEF_HEIGHT); if (ww < QV2D_DEF_WIDTH) ww = QV2D_DEF_WIDTH; if (hh < QV2D_DEF_HEIGHT) hh = QV2D_DEF_HEIGHT; s_wrk_ctx.hwnd = (HWND)window_open(curt_app, (void_t*)WindowProc, x1, y1, ww, hh, WIN_TITLE, WIN_CLASS, (ansi_t*)101, CR_WSTYLE_NORMAL); if (s_wrk_ctx.hwnd == NULL) return (QST_ERROR); SetWindowLongPtr(s_wrk_ctx.hwnd, GWL_STYLE, GetWindowLongPtr(s_wrk_ctx.hwnd, GWL_STYLE) & (~WS_MAXIMIZEBOX)); iGFX2* draw; sIMAGE* imgs; /* 创建 GDI 绘制对象 (只支持32位色屏幕) */ draw = (iGFX2*)create_gdi_canvas(s_wrk_ctx.hwnd, 0, 0, FALSE); if (draw == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } imgs = CR_VCALL(draw)->lock(draw); if (imgs == NULL || imgs->fmt != CR_ARGB8888) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } CR_VCALL(draw)->unlock(draw); CR_VCALL(draw)->clear(draw, s_wrk_ctx.cfgs.bkcolor, 0); s_wrk_ctx.draw = draw; /* 初始化网络 */ if (!socket_init()) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } s_wrk_ctx.netw = netw_cli_open(EXE_XNAME); if (s_wrk_ctx.netw == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } /* 读取需要超时, 不然线程无法退出 */ socket_set_timeout(s_wrk_ctx.netw, -1, QST_TCP_TOUT); thrd_t thrd; /* 生成工作线程 */ s_wrk_ctx.send = TRUE; s_wrk_ctx.quit = FALSE; s_wrk_ctx.cur_busy = LoadCursor(NULL, IDC_WAIT); s_wrk_ctx.cur_free = LoadCursor(NULL, IDC_ARROW); s_wrk_ctx.res_loader = res_loader_get(); if (s_wrk_ctx.res_loader->init != NULL) s_wrk_ctx.res_loader->init(s_wrk_ctx.netw, NULL); qst_load_filter(&s_wrk_ctx); thrd = thread_new(0, qst_v2d_main, &s_wrk_ctx, FALSE); if (thrd == NULL) { window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); return (QST_ERROR); } /* 消息循环 */ while (!s_wrk_ctx.quit) { MSG msg; if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { s_wrk_ctx.quit = TRUE; break; } TranslateMessage(&msg); DispatchMessage(&msg); } else { qst_do_keyboard(&s_wrk_ctx); } } thread_wait(thrd); thread_del(thrd); window_kill(s_wrk_ctx.hwnd, curt_app, WIN_CLASS); netw_cli_close(s_wrk_ctx.netw); return (QST_OKAY); }
/* --------------------------------------- 工作线程 --------------------------------------- */ static uint_t STDCALL qst_srv_main ( __CR_IN__ void_t* param ) { uint_t self, count; sQstWork* ctx = (sQstWork*)param; sQstWork* tot = (sQstWork*)ctx->self; /* 工作循环 */ self = ctx->id; count = ctx->cnt; for (;;) { ansi_t* shell; ansi_t* string; /* 接收一条命令 */ /* 一有错误表示非法客户端, 直接踢 */ string = netw_cmd_recv_ex(ctx->netw); if (string == NULL) break; _ENTER_SHOW_SAY_ printf("[%s] say: %s\n", ctx->name, string); _LEAVE_SHOW_SAY_ /* 广播这条消息 */ mtlock_acquire(&s_qst_lck_wrk); for (uint_t idx = 0; idx < count; idx++) { /* 跳过自己和空闲的单元 */ if (idx == self || tot[idx].over) continue; netw_cmd_send(tot[idx].netw, string); } mtlock_release(&s_qst_lck_wrk); /* 处理一些公共指令 */ shell = cmd_shl_get(string); mem_free(string); if (shell == NULL) continue; if (str_cmpA(shell, "app:exit") == 0 || str_cmpA(shell, "qsrv:app:exit") == 0) { thread_sleep(1000); exit(0); } if (str_cmpA(shell, "win:load") == 0) qst_srv_win_load(); else if (str_cmpA(shell, "win:save") == 0) qst_srv_win_save(); else if (str_cmpA(shell, "win:show") == 0 || str_cmpA(shell, "qsrv:win:show") == 0) qst_srv_win_show(); mem_free(shell); } /* 显示已经断线 */ _ENTER_SHOW_OUT_ printf("[%s] is offline.\n", ctx->name); _LEAVE_SHOW_OUT_ /* 释放资源 */ mem_free(ctx->name); ctx->name = NULL; mtlock_acquire(&s_qst_lck_wrk); netw_cli_close(ctx->netw); ctx->netw = NULL; ctx->over = TRUE; mtlock_release(&s_qst_lck_wrk); return (QST_OKAY); }
/* ======================================= WinMain 程序入口 ======================================= */ int WINAPI WinMain ( __CR_IN__ HINSTANCE curt_app, __CR_IN__ HINSTANCE prev_app, __CR_IN__ LPSTR cmd_line, __CR_IN__ int cmd_show ) { uint_t argc; ansi_t** argv; CR_NOUSE(prev_app); CR_NOUSE(cmd_show); /* 只允许一个例程 */ if (misc_is_running(EXE_XNAME)) return (QST_ERROR); /* 建立 CrHack 系统 */ if (!set_app_type(CR_APP_GUI)) return (QST_ERROR); mem_zero(&s_wrk_ctx, sizeof(s_wrk_ctx)); int qt_argc; /* 获取命令行参数, 不包括进程文件名 */ argv = misc_get_param(cmd_line, &argc); qt_argc = (int)argc; QApplication qt_app(qt_argc, argv); qt_app.setApplicationName("QstComm"); qt_app.setOrganizationName("QuestLAB"); sint_t x1, y1; uint_t ww, hh; /* 生成一个可变大小的窗口 */ mtlock_init(&s_wrk_ctx.lock); qst_load_cfg(&s_wrk_ctx.cfgs); misc_desk_init(WIN_ICONF, &x1, &y1, &ww, &hh, QCOM_DEF_WIDTH, QCOM_DEF_HEIGHT); if (ww < QCOM_DEF_WIDTH) ww = QCOM_DEF_WIDTH; if (hh < QCOM_DEF_HEIGHT) hh = QCOM_DEF_HEIGHT; RECT w_rect; sint_t fw, fh; QMainWindow qt_win; /* Qt 里的宽高都不包括边框 需要自己用 Win32 API 获取 */ qt_win.setWindowFlags(qt_win.windowFlags() & (~Qt::WindowMaximizeButtonHint)); qt_win.move(x1, y1); qt_win.resize(ww, hh); s_wrk_ctx.hwnd = (HWND)qt_win.winId(); if (!GetWindowRect(s_wrk_ctx.hwnd, &w_rect)) return (QST_ERROR); fw = w_rect.right - w_rect.left - ww; fh = w_rect.bottom - w_rect.top - hh; qt_win.setMinimumSize(QCOM_DEF_WIDTH - fw, QCOM_DEF_HEIGHT - fh); qt_win.resize(ww - fw, hh - fh); QWidget* cent = new QWidget (&qt_win); CTextEdit* edit = new CTextEdit (cent); QHBoxLayout* hori = new QHBoxLayout (cent); /* 创建窗体里的控件 */ hori->setSpacing(6); hori->setContentsMargins(8, 8, 8, 8); hori->addWidget(edit); qt_win.setCentralWidget(cent); CTextOper oper(&qt_win, edit); s_wrk_ctx.oper = (void_t*)(&oper); SetClassLongPtr(s_wrk_ctx.hwnd, GCLP_HICON, (LONG_PTR) LoadIconA(curt_app, (ansi_t*)101)); /* 初始化 ANSI 上下文 */ if (!qst_csi_init()) return (QST_ERROR); qst_set_viewer(&s_wrk_ctx); /* 初始化网络 */ if (!socket_init()) return (QST_ERROR); s_wrk_ctx.netw = netw_cli_open(EXE_XNAME); if (s_wrk_ctx.netw == NULL) return (QST_ERROR); /* 读取需要超时, 不然线程无法退出 */ socket_set_timeout(s_wrk_ctx.netw, -1, QST_TCP_TOUT); thrd_t thrd; /* 生成工作线程 */ s_wrk_ctx.quit = FALSE; s_wrk_ctx.comm.quit = FALSE; s_wrk_ctx.comm.text = TRUE; s_wrk_ctx.comm.rtype = "text"; s_wrk_ctx.comm.stype = "text"; s_wrk_ctx.comm.title = NULL; s_wrk_ctx.comm.render = qst_txt_show; s_wrk_ctx.page = get_sys_codepage(); qst_update_title(&s_wrk_ctx); thrd = thread_new(0, qst_com_main, &s_wrk_ctx, FALSE); if (thrd == NULL) return (QST_ERROR); sio_init(); /* 开始 Qt 流程 */ qt_win.show(); qt_app.exec(); /* 关闭线程直接退出 */ if (!s_wrk_ctx.quit) s_wrk_ctx.quit = TRUE; thread_wait(thrd); thread_del(thrd); netw_cli_close(s_wrk_ctx.netw); sio_free(); qst_csi_free(); return (QST_OKAY); }