diff --git a/src/server/request.c b/src/server/request.c index dd1a58c1..d1dc41cd 100644 --- a/src/server/request.c +++ b/src/server/request.c @@ -11,41 +11,41 @@ // ////////////////////////////////////////////////////////////////////////////// /* - * This file is part of MiniGUI, a mature cross-platform windowing + * This file is part of MiniGUI, a mature cross-platform windowing * and Graphics User Interface (GUI) support system for embedded systems * and smart IoT devices. - * + * * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. * Copyright (C) 1998~2002, WEI Yongming - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * Or, - * + * * As this program is a library, any link to this program must follow * GNU General Public License version 3 (GPLv3). If you cannot accept * GPLv3, you need to be licensed from FMSoft. - * + * * If you have got a commercial license of this program, please use it * under the terms and conditions of the commercial license. - * + * * For more information about the commercial license, please refer to * . */ /* ** request.c: handle request of clients. -** +** ** Current maintainer: Wei Yongming. ** ** Create date: 2000/12/21 @@ -82,7 +82,7 @@ struct GlobalRes ReleaseProc release_proc; }; -static void add_global_res (int cli, void* key, +static void add_global_res (int cli, void* key, void* res, ReleaseProc release_proc) { MG_Client* client = mgClients + cli; @@ -155,19 +155,60 @@ void __mg_release_global_res (int cli) } } -int GUIAPI ServerSendReply (int clifd, const void* reply, int len) +int GUIAPI ServerSendReplyEx (int clifd, + const void* reply, int len, int fd_to_send) { - MSG reply_msg = {HWND_INVALID, 0}; if (!mgIsServer) return SOCKERR_IO; - /* send a reply message to indicate this is a reply of request */ - if (sock_write (clifd, &reply_msg, sizeof (MSG)) < 0) - return SOCKERR_IO; + { + MSG msg = {HWND_INVALID, 0}; - if (sock_write (clifd, reply, len) < 0) - return SOCKERR_IO; - return SOCKERR_OK; + /* send a reply message to indicate this is a reply of request */ + if (sock_write (clifd, &msg, sizeof (MSG)) < 0) + return SOCKERR_IO; + } + +#if 0 + { + if (sock_write (clifd, reply, len) < 0) + return SOCKERR_IO; + + return SOCKERR_OK; + } +#else /* use sendmsg */ + { + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmsg = NULL; + + iov[0].iov_base = (void*)reply; + iov[0].iov_len = len; + + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + + if (fd_to_send >= 0) { + cmsg = alloca (CMSG_LEN (sizeof (int))); + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN (sizeof (int)); + memcpy (CMSG_DATA (cmsg), &fd_to_send, sizeof (int)); + + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_LEN (sizeof (int)); + } + else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + } + + return sock_sendmsg (clifd, &msg, 0); + } +#endif } static int load_cursor (int cli, int clifd, void* buff, size_t len) @@ -178,7 +219,7 @@ static int load_cursor (int cli, int clifd, void* buff, size_t len) #ifdef _MGHAVE_CURSOR if (hcsr) { - add_global_res (cli, (void*) hcsr, + add_global_res (cli, (void*) hcsr, (void*)hcsr, (ReleaseProc)DestroyCursor); } #endif @@ -195,7 +236,7 @@ static int create_cursor (int cli, int clifd, void* buff, size_t len) and_bits = (BYTE*)(tmp + 6); xor_bits = and_bits + tmp [5]; - hcsr = CreateCursor (tmp [0], tmp [1], tmp [2], tmp [3], + hcsr = CreateCursor (tmp [0], tmp [1], tmp [2], tmp [3], and_bits, xor_bits, tmp [4]); #ifdef _MGHAVE_CURSOR @@ -324,7 +365,7 @@ static int join_layer (int cli, int clifd, void* buff, size_t len) JOINEDCLIENTINFO joined_info = {INV_LAYER_HANDLE}; info = (JOINLAYERINFO*) buff; - + if (info->layer_name [0] == '\0') { strcpy (info->layer_name, mgTopmostLayer->name); nr_layers ++; @@ -467,22 +508,22 @@ static int register_hook (int cli, int clifd, void* buff, size_t len) static int set_ime_stat (int cli, int clifd, void* buff, size_t len) { int ret, data; - + memcpy(&data, buff, sizeof(int)); - ret = SendMessage (HWND_DESKTOP, MSG_IME_SETSTATUS, + ret = SendMessage (HWND_DESKTOP, MSG_IME_SETSTATUS, HISWORD(data), LOSWORD(data)); - return ServerSendReply (clifd, &ret, sizeof (int)); + return ServerSendReply (clifd, &ret, sizeof (int)); } static int get_ime_stat (int cli, int clifd, void* buff, size_t len) { int ret, data; - + memcpy(&data, buff, sizeof(int)); - + ret = SendMessage (HWND_DESKTOP, MSG_IME_GETSTATUS, (WPARAM)data, 0); - return ServerSendReply (clifd, &ret , sizeof (int)); + return ServerSendReply (clifd, &ret , sizeof (int)); } static int set_ime_targetinfo (int cli, int clifd, void* buff, size_t len) @@ -514,43 +555,43 @@ static int handle_mlshadow_req (int cli, int clifd, void* buff, size_t len) op_id = buff; switch(*op_id) { - case MLSOP_ID_GET_MASTERINFO: + case MLSOP_ID_GET_MASTERINFO: { - MLSHADOW_REPLY_MASTER_INFO reply; + MLSHADOW_REPLY_MASTER_INFO reply; MLSHADOW_Server(buff, &reply); ServerSendReply (clifd, &reply, sizeof(reply)); - break; + break; } case MLSOP_ID_CREATE_SURFACE: { - MLSHADOW_REPLY_SURFACE_CREATE reply; + MLSHADOW_REPLY_SURFACE_CREATE reply; MLSHADOW_Server(buff, &reply); - add_global_res (cli, (void*)reply.surface_key, + add_global_res (cli, (void*)reply.surface_key, (void*)reply.surface_key, (ReleaseProc)srvMLSHADOW_DelSurface); ServerSendReply (clifd, &reply, sizeof(reply)); break; } case MLSOP_ID_GET_SLAVEINFO: { - MLSHADOW_REPLY_SLAVE_GETINFO reply; - MLSHADOW_Server(buff, &reply); - ServerSendReply (clifd, &reply, sizeof(reply)); - break; - } - case MLSOP_ID_SET_SLAVEINFO: - { - BOOL reply; + MLSHADOW_REPLY_SLAVE_GETINFO reply; MLSHADOW_Server(buff, &reply); ServerSendReply (clifd, &reply, sizeof(reply)); break; - } - case MLSOP_ID_DESTROY_SLAVE: + } + case MLSOP_ID_SET_SLAVEINFO: { BOOL reply; MLSHADOW_Server(buff, &reply); ServerSendReply (clifd, &reply, sizeof(reply)); break; - } + } + case MLSOP_ID_DESTROY_SLAVE: + { + BOOL reply; + MLSHADOW_Server(buff, &reply); + ServerSendReply (clifd, &reply, sizeof(reply)); + break; + } } return 0; } @@ -586,7 +627,7 @@ static int req_hw_surface (int cli, int clifd, void* buff, size_t len) allocated->offset = reply.offset; allocated->bucket = reply.bucket; - add_global_res (cli, allocated->bucket, + add_global_res (cli, allocated->bucket, allocated, (ReleaseProc)release_HWS); } } @@ -601,51 +642,54 @@ static int req_hw_surface (int cli, int clifd, void* buff, size_t len) extern int clipboard_op (int cli, int clifd, void* buff, size_t len); #endif -static REQ_HANDLER handlers [MAX_REQID] = +static struct req_request { + void* handler; + int version; +} handlers [MAX_REQID] = { - load_cursor, - create_cursor, - destroy_cursor, - clip_cursor, - get_clip_cursor, - set_cursor, - get_current_cursor, - show_cursor, - set_cursor_pos, - layer_info, - join_layer, - layer_op, - zorder_op, - im_live, - open_ime_wnd, - set_ime_stat, - get_ime_stat, - register_hook, - req_hw_surface, + { load_cursor, 0 }, + { create_cursor, 0 }, + { destroy_cursor, 0 }, + { clip_cursor, 0 }, + { get_clip_cursor, 0 }, + { set_cursor, 0 }, + { get_current_cursor, 0 }, + { show_cursor, 0 }, + { set_cursor_pos, 0 }, + { layer_info, 0 }, + { join_layer, 0 }, + { layer_op, 0 }, + { zorder_op, 0 }, + { im_live, 0 }, + { open_ime_wnd, 0 }, + { set_ime_stat, 0 }, + { get_ime_stat, 0 }, + { register_hook, 0 }, + { req_hw_surface, 0 }, #ifdef _MGHAVE_CLIPBOARD - clipboard_op, + { clipboard_op, 0 }, #else - NULL, + { NULL, 0 }, #endif #ifdef _MGGAL_MLSHADOW - handle_mlshadow_req, + { handle_mlshadow_req, 0 }, #else - NULL, + { NULL, 0 }, #endif - change_zorder_maskrect, + { change_zorder_maskrect, 0 }, #ifdef _MGGAL_NEXUS - nexus_client_get_surface, + { nexus_client_get_surface, 0 }, #else - NULL, + { NULL, 0 }, #endif #ifdef _MGGAL_SIGMA8654 - sigma8654_client_get_surface, + { sigma8654_client_get_surface, 0 }, #else - NULL, + { NULL, 0 }, #endif - get_ime_targetinfo, - set_ime_targetinfo, - copy_cursor, + { get_ime_targetinfo, 0 }, + { set_ime_targetinfo, 0 }, + { copy_cursor, 0 }, }; BOOL GUIAPI RegisterRequestHandler (int req_id, REQ_HANDLER your_handler) @@ -653,7 +697,18 @@ BOOL GUIAPI RegisterRequestHandler (int req_id, REQ_HANDLER your_handler) if (req_id <= MAX_SYS_REQID || req_id > MAX_REQID) return FALSE; - handlers [req_id - 1] = your_handler; + handlers[req_id - 1].handler = your_handler; + handlers[req_id - 1].version = 0; + return TRUE; +} + +BOOL GUIAPI RegisterRequestHandlerV1 (int req_id, REQ_HANDLER_V1 your_handler) +{ + if (req_id <= MAX_SYS_REQID || req_id > MAX_REQID) + return FALSE; + + handlers[req_id - 1].handler = your_handler; + handlers[req_id - 1].version = 1; return TRUE; } @@ -662,7 +717,33 @@ REQ_HANDLER GUIAPI GetRequestHandler (int req_id) if (req_id <= 0 || req_id > MAX_REQID) return NULL; - return handlers [req_id - 1]; + if (handlers[req_id - 1].version == 0) + return handlers [req_id - 1].handler; + + return NULL; +} + +REQ_HANDLER_V1 GUIAPI GetRequestHandlerV1 (int req_id) +{ + if (req_id <= 0 || req_id > MAX_REQID) + return NULL; + + if (handlers[req_id - 1].version == 1) + return handlers [req_id - 1].handler; + + return NULL; +} + +void* GUIAPI GetRequestHandlerEx (int req_id, int* version) +{ + if (req_id <= 0 || req_id > MAX_REQID) + return NULL; + + if (version) { + *version = handlers [req_id - 1].version; + } + + return handlers [req_id - 1].handler; } static char _request_data_buff [1024]; @@ -671,14 +752,23 @@ int __mg_handle_request (int clifd, int req_id, int cli) { int n; char* buff; + size_t req_data_len, ex_data_len; size_t len_data; + int fd_received = -1; - if ((n = sock_read (clifd, &len_data, sizeof (size_t))) == SOCKERR_IO) + if ((n = sock_read (clifd, &req_data_len, sizeof (size_t))) == SOCKERR_IO) return SOCKERR_IO; else if (n == SOCKERR_CLOSED) { goto error; } + if ((n = sock_read (clifd, &ex_data_len, sizeof (size_t))) == SOCKERR_IO) + return SOCKERR_IO; + else if (n == SOCKERR_CLOSED) { + goto error; + } + + len_data = req_data_len + ex_data_len; if (len_data <= sizeof (_request_data_buff)) { buff = _request_data_buff; } @@ -688,16 +778,65 @@ int __mg_handle_request (int clifd, int req_id, int cli) return SOCKERR_INVARG; } +#if 0 if ((n = sock_read (clifd, buff, len_data)) == SOCKERR_IO) return SOCKERR_IO; else if (n == SOCKERR_CLOSED) { goto error; } +#else /* use recvmsg */ + { + struct iovec iov[2]; + struct msghdr msg; + struct cmsghdr *cmsg = NULL; + int newfd = -1; - if (req_id > MAX_REQID || req_id <= 0 || handlers [req_id - 1] == NULL) + iov[0].iov_base = buff; + iov[0].iov_len = req_data_len; + + iov[1].iov_base = buff + req_data_len; + iov[1].iov_len = ex_data_len; + + msg.msg_iov = iov; + msg.msg_iovlen = 2; + msg.msg_name = NULL; + msg.msg_namelen = 0; + + cmsg = alloca (CMSG_LEN (sizeof (int))); + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_LEN (sizeof (int)); + + if ((n = sock_recvmsg (clifd, &msg, 0)) == SOCKERR_IO) { + return SOCKERR_IO; + } + else if (n == SOCKERR_CLOSED) { + goto error; + } + + if (msg.msg_controllen == CMSG_LEN (sizeof (int))) { + memcpy (&fd_received, CMSG_DATA(cmsg), sizeof (int)); + } + } +#endif + + if (req_id > MAX_REQID || req_id <= 0 || + handlers [req_id - 1].handler == NULL) return SOCKERR_INVARG; - n = handlers [req_id - 1] (cli, clifd, buff, len_data); + if (handlers [req_id - 1].version == 1) { + REQ_HANDLER_V1 handler = handlers [req_id - 1].handler; + n = handler (cli, clifd, buff, len_data, fd_received); + } + else { + REQ_HANDLER handler = handlers [req_id - 1].handler; + + if (fd_received >= 0) { + close (fd_received); + _WRN_PRINTF ("A file descriptor received, but the request handler is version 0.\n"); + } + + n = handler (cli, clifd, buff, len_data); + } if (len_data > sizeof (_request_data_buff)) free (buff); @@ -715,4 +854,3 @@ error: return SOCKERR_CLOSED; } -