diff options
Diffstat (limited to 'winsup/cygserver/client.cc')
-rw-r--r-- | winsup/cygserver/client.cc | 541 |
1 files changed, 0 insertions, 541 deletions
diff --git a/winsup/cygserver/client.cc b/winsup/cygserver/client.cc deleted file mode 100644 index d8f7ac5..0000000 --- a/winsup/cygserver/client.cc +++ /dev/null @@ -1,541 +0,0 @@ -/* client.cc - - Copyright 2001, 2002, 2003 Red Hat Inc. - - Written by Egor Duda <deo@logos-m.ru> - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -/* to allow this to link into cygwin and the .dll, a little magic is needed. */ -#ifdef __OUTSIDE_CYGWIN__ -#include "woutsup.h" -#else -#include "winsup.h" -#endif - -#include <assert.h> -#include <stdio.h> -#include <unistd.h> - -#include "cygerrno.h" -#include "cygserver_msg.h" -#include "cygserver_sem.h" -#include "cygserver_shm.h" - -#include "cygserver.h" -#include "transport.h" - -int cygserver_running = CYGSERVER_UNKNOWN; // Nb: inherited by children. - -bool allow_server = false; // Nb: inherited by children. - -client_request_get_version::client_request_get_version () - : client_request (CYGSERVER_REQUEST_GET_VERSION, &version, sizeof (version)) -{ - msglen (0); // No parameters for request. - - // verbose: syscall_printf ("created"); -} - -/* - * client_request_get_version::check_version () - * - * The major version and API version numbers must match exactly. An - * older than expected minor version number is accepted (as long as - * the first numbers match, that is). - */ - -#ifdef __INSIDE_CYGWIN__ - -bool -client_request_get_version::check_version () const -{ - const bool ok = (version.major == CYGWIN_SERVER_VERSION_MAJOR - && version.api == CYGWIN_SERVER_VERSION_API - && version.minor <= CYGWIN_SERVER_VERSION_MINOR); - - if (!ok) - syscall_printf (("incompatible version of cygwin server: " - "client version %d.%d.%d.%d, " - "server version %ld.%ld.%ld.%ld"), - CYGWIN_SERVER_VERSION_MAJOR, - CYGWIN_SERVER_VERSION_API, - CYGWIN_SERVER_VERSION_MINOR, - CYGWIN_SERVER_VERSION_PATCH, - version.major, - version.api, - version.minor, - version.patch); - - return ok; -} - -client_request_attach_tty::client_request_attach_tty (DWORD nmaster_pid, - HANDLE nfrom_master, - HANDLE nto_master) - : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req)) -{ - req.pid = GetCurrentProcessId (); - req.master_pid = nmaster_pid; - req.from_master = nfrom_master; - req.to_master = nto_master; - - syscall_printf (("created: pid = %lu, master_pid = %lu, " - "from_master = %lu, to_master = %lu"), - req.pid, req.master_pid, req.from_master, req.to_master); -} -#endif /* __INSIDE_CYGWIN__ */ - -/* - * client_request_attach_tty::send () - * - * Wraps the base method to provide error handling support. If the - * reply contains a body but is flagged as an error, close any handles - * that have been returned by cygserver and then discard the message - * body, i.e. the client either sees a successful result with handles - * or an unsuccessful result with no handles. - */ - -void -client_request_attach_tty::send (transport_layer_base * const conn) -{ - client_request::send (conn); - - if (msglen () && error_code ()) - { - if (from_master ()) - CloseHandle (from_master ()); - if (to_master ()) - CloseHandle (to_master ()); - msglen (0); - } -} - -client_request::header_t::header_t (const request_code_t request_code, - const size_t msglen) - : msglen (msglen), - request_code (request_code) -{ - assert (request_code >= 0 && request_code < CYGSERVER_REQUEST_LAST); -} - -// FIXME: also check write and read result for -1. - -void -client_request::send (transport_layer_base * const conn) -{ - assert (conn); - assert (!(msglen () && !_buf)); // i.e., msglen () implies _buf - assert (msglen () <= _buflen); - - { - const ssize_t count = conn->write (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("request header write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen ()) - { - const ssize_t count = conn->write (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("request body write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("request sent (%ld + %ld bytes)", - // sizeof (_header), msglen ()); - - { - const ssize_t count = conn->read (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("reply header read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen () && !_buf) - { - system_printf ("no client buffer for reply body: %ld bytes needed", - msglen ()); - error_code (EINVAL); - return; - } - - if (msglen () > _buflen) - { - system_printf (("client buffer too small for reply body: " - "have %ld bytes and need %ld"), - _buflen, msglen ()); - error_code (EINVAL); - return; - } - - if (msglen ()) - { - const ssize_t count = conn->read (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("reply body read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("reply received (%ld + %ld bytes)", - // sizeof (_header), msglen ()); -} - -#ifdef __OUTSIDE_CYGWIN__ - -client_request_attach_tty::client_request_attach_tty () - : client_request (CYGSERVER_REQUEST_ATTACH_TTY, &req, sizeof (req)) -{ -} - -/* - * client_request::handle_request () - * - * A server-side method. - * - * This is a factory method for the client_request subclasses. It - * reads the incoming request header and, based on its request code, - * creates an instance of the appropriate class. - * - * FIXME: If the incoming packet is malformed, the server drops it on - * the floor. Should it try and generate some sort of reply for the - * client? As it is, the client will simply get a broken connection. - * - * FIXME: also check write and read result for -1. - */ - -/* static */ void -client_request::handle_request (transport_layer_base *const conn, - process_cache *const cache) -{ - // verbose: debug_printf ("about to read"); - - header_t header; - - { - const ssize_t count = conn->read (&header, sizeof (header)); - - if (count != sizeof (header)) - { - syscall_printf (("request header read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, sizeof (header), - errno, GetLastError ()); - return; - } - - // verbose: debug_printf ("got header (%ld)", count); - } - - client_request *req = NULL; - - switch (header.request_code) - { - case CYGSERVER_REQUEST_GET_VERSION: - req = new client_request_get_version; - break; - case CYGSERVER_REQUEST_SHUTDOWN: - req = new client_request_shutdown; - break; - case CYGSERVER_REQUEST_ATTACH_TTY: - req = new client_request_attach_tty; - break; - case CYGSERVER_REQUEST_MSG: - req = new client_request_msg; - break; - case CYGSERVER_REQUEST_SEM: - req = new client_request_sem; - break; - case CYGSERVER_REQUEST_SHM: - req = new client_request_shm; - break; - default: - syscall_printf ("unknown request code %d received: request ignored", - header.request_code); - return; - } - - assert (req); - - req->msglen (header.msglen); - req->handle (conn, cache); - - delete req; -} - -/* - * client_request::handle () - * - * A server-side method. - * - * At this point, the header of an incoming request has been read and - * an appropriate client_request object constructed. This method has - * to read the request body into its buffer, if there is such a body, - * then perform the request and send back the results to the client. - * - * FIXME: If the incoming packet is malformed, the server drops it on - * the floor. Should it try and generate some sort of reply for the - * client? As it is, the client will simply get a broken connection. - * - * FIXME: also check write and read result for -1. - */ - -void -client_request::handle (transport_layer_base *const conn, - process_cache *const cache) -{ - if (msglen () && !_buf) - { - system_printf ("no buffer for request body: %ld bytes needed", - msglen ()); - error_code (EINVAL); - return; - } - - if (msglen () > _buflen) - { - system_printf (("buffer too small for request body: " - "have %ld bytes and need %ld"), - _buflen, msglen ()); - error_code (EINVAL); - return; - } - - if (msglen ()) - { - const ssize_t count = conn->read (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("request body read failure: " - "only %ld bytes received of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("request received (%ld + %ld bytes)", - // sizeof (_header), msglen ()); - - error_code (0); // Overwrites the _header.request_code field. - - /* - * This is not allowed to fail. We must return ENOSYS at a minimum - * to the client. - */ - serve (conn, cache); - - { - const ssize_t count = conn->write (&_header, sizeof (_header)); - - if (count != sizeof (_header)) - { - assert (errno); - error_code (errno); - syscall_printf (("reply header write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, sizeof (_header), - errno, GetLastError ()); - return; - } - } - - if (msglen ()) - { - const ssize_t count = conn->write (_buf, msglen ()); - - if (count == -1 || (size_t) count != msglen ()) - { - assert (errno); - error_code (errno); - syscall_printf (("reply body write failure: " - "only %ld bytes sent of %ld, " - "error = %d(%lu)"), - count, msglen (), - errno, GetLastError ()); - return; - } - } - - // verbose: syscall_printf ("reply sent (%ld + %ld bytes)", - // sizeof (_header), msglen ()); -} - -/* The server side implementation of make_request. Very simple. */ -int -client_request::make_request () -{ - transport_layer_base *const transport = create_server_transport (); - assert (transport); - if (transport->connect () == -1) - { - if (errno) - error_code (errno); - else - error_code (ENOSYS); - delete transport; - return -1; - } - send (transport); - delete transport; - return 0; -} -#endif /* __OUTSIDE_CYGWIN__ */ - -client_request::client_request (request_code_t const id, - void * const buf, - size_t const buflen) - : _header (id, buflen), - _buf (buf), - _buflen (buflen) -{ - assert ((!_buf && !_buflen) || (_buf && _buflen)); -} - -client_request::~client_request () -{} - -#ifdef __INSIDE_CYGWIN__ -int -client_request::make_request () -{ - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - if (cygserver_running == CYGSERVER_UNKNOWN) - cygserver_init (); - - assert (cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - /* Don't retry every request if the server's not there */ - if (cygserver_running == CYGSERVER_UNAVAIL) - { - syscall_printf ("cygserver un-available"); - error_code (ENOSYS); - return -1; - } - - transport_layer_base *const transport = create_server_transport (); - - assert (transport); - - if (transport->connect () == -1) - { - if (errno) - error_code (errno); - else - error_code (ENOSYS); - delete transport; - return -1; - } - - // verbose: debug_printf ("connected to server %p", transport); - - send (transport); - - delete transport; - - return 0; -} - -bool -check_cygserver_available () -{ - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_UNAVAIL); - - cygserver_running = CYGSERVER_OK; // For make_request (). - - client_request_get_version req; - - /* This indicates that we failed to connect to cygserver at all but - * that's fine as cygwin doesn't need it to be running. - */ - if (req.make_request () == -1) - return false; - - /* We connected to the server but something went wrong after that - * (in sending the message, in cygserver itself, or in receiving the - * reply). - */ - if (req.error_code ()) - { - syscall_printf ("failure in cygserver version request: %d", - req.error_code ()); - syscall_printf ("process will continue without cygserver support"); - return false; - } - - return req.check_version (); -} - -void -cygserver_init () -{ - if (!allow_server) - { - syscall_printf ("cygserver use disabled in client"); - cygserver_running = CYGSERVER_UNAVAIL; - return; - } - - assert (cygserver_running == CYGSERVER_UNKNOWN \ - || cygserver_running == CYGSERVER_OK \ - || cygserver_running == CYGSERVER_UNAVAIL); - - if (cygserver_running == CYGSERVER_OK) - return; - - if (!check_cygserver_available ()) - cygserver_running = CYGSERVER_UNAVAIL; -} -#endif /* __INSIDE_CYGWIN__ */ |