diff --git a/client/ipcclient.cbp b/client/ipcclient.cbp index a47d0af..70ada5a 100644 --- a/client/ipcclient.cbp +++ b/client/ipcclient.cbp @@ -47,6 +47,8 @@ + + diff --git a/client/src/core/windows/pop.cc b/client/src/core/windows/pop.cc new file mode 100644 index 0000000..194eaf9 --- /dev/null +++ b/client/src/core/windows/pop.cc @@ -0,0 +1,118 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +/** + * @file src/os/windows/request.cc + * + * @brief Implements WIN32 request methods. + * + * @author perry.werneck@gmail.com + * + */ + + #include + + using std::string; + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + IPC::Request & IPC::Request::pop(std::string &value) { + DataBlock * block = getNextBlock(); + + if(block->type != IPC::Request::String) + throw std::runtime_error("Invalid format"); + + const char *ptr = (const char *) (block+1); + + in.current += (strlen(ptr)+1+sizeof(DataBlock)); + + value.assign(ptr); + + return *this; + } + + IPC::Request & IPC::Request::Request::pop(int &value) { + + DataBlock * block = getNextBlock(); + + switch(block->type) { + case IPC::Request::Int16: + value = * ((int16_t *) (block+1)); + in.current += sizeof(int16_t) + sizeof(DataBlock); + break; + + case IPC::Request::Int32: + value = * ((int32_t *) (block+1)); + in.current += sizeof(int32_t) + sizeof(DataBlock); + break; + + case IPC::Request::Int64: + value = * ((int64_t *) (block+1)); + in.current += sizeof(int64_t) + sizeof(DataBlock); + break; + + default: + throw std::runtime_error("Invalid format"); + } + + return *this; + } + + IPC::Request & IPC::Request::Request::pop(unsigned int &value) { + + DataBlock * block = getNextBlock(); + + switch(block->type) { + case IPC::Request::Uint16: + value = * ((uint16_t *) (block+1)); + in.current += sizeof(uint16_t) + sizeof(DataBlock); + break; + + case IPC::Request::Uint32: + value = * ((uint32_t *) (block+1)); + in.current += sizeof(uint32_t) + sizeof(DataBlock); + break; + + case IPC::Request::Uint64: + value = * ((uint64_t *) (block+1)); + in.current += sizeof(uint64_t) + sizeof(DataBlock); + break; + + default: + throw std::runtime_error("Invalid format"); + } + + return *this; + } + + } + + diff --git a/client/src/core/windows/push.cc b/client/src/core/windows/push.cc new file mode 100644 index 0000000..315f652 --- /dev/null +++ b/client/src/core/windows/push.cc @@ -0,0 +1,80 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +/** + * @file + * + * @brief Implements WIN32 request "push" methods. + * + * @author perry.werneck@gmail.com + * + */ + + #include + + using std::string; + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + IPC::Request & IPC::Request::push(const char *arg) { + (*this->outvalues)++; + pushBlock(arg, strlen(arg)+1)->type = IPC::Request::String; + return *this; + } + + IPC::Request & IPC::Request::push(const bool arg) { + (*this->outvalues)++; + uint8_t value = (uint8_t) (arg ? 0xff : 0); + pushBlock(&value, sizeof(value))->type = IPC::Request::Boolean; + return *this; + } + + IPC::Request & IPC::Request::push(const uint8_t arg) { + (*this->outvalues)++; + pushBlock(&arg, sizeof(arg))->type = IPC::Request::Uchar; + return *this; + } + + IPC::Request & IPC::Request::push(const int32_t arg) { + (*this->outvalues)++; + pushBlock(&arg, sizeof(arg))->type = IPC::Request::Int32; + return *this; + } + + IPC::Request & IPC::Request::push(const uint32_t arg) { + (*this->outvalues)++; + pushBlock(&arg, sizeof(arg))->type = IPC::Request::Uint32; + return *this; + } + + } + + diff --git a/client/src/core/windows/request.cc b/client/src/core/windows/request.cc index b5c33e4..eb41978 100644 --- a/client/src/core/windows/request.cc +++ b/client/src/core/windows/request.cc @@ -44,6 +44,39 @@ namespace TN3270 { + #define PIPE_BUFFER_LENGTH 8192 + + IPC::Request::Request(HANDLE hPipe, const char *name, uint16_t type) { + + this->hPipe = hPipe; + + // Create buffers + in.length = PIPE_BUFFER_LENGTH; + in.used = 0; + in.block = new uint8_t[in.length]; + + out.length = PIPE_BUFFER_LENGTH; + out.used = 0; + out.block = new uint8_t[out.length]; + + // Add name + strcpy((char *) out.block, name); + out.used += strlen((char *) name) + 1; + + // Add type + debug("Request type stored @",out.used); + + *((uint16_t *) (out.block + out.used)) = type; + out.used += sizeof(uint16_t); + + // Add argument counter. + this->outvalues = (uint16_t *) (out.block + out.used); + out.used += sizeof(uint16_t); + + *this->outvalues = 0; + + } + IPC::Request::~Request() { delete[] ((uint8_t *) in.block); @@ -78,107 +111,14 @@ } - IPC::Request & IPC::Request::push(const char *arg) { - pushBlock(arg, strlen(arg)+1)->type = IPC::Request::String; - return *this; - } - - IPC::Request & IPC::Request::push(const bool arg) { - uint8_t value = (uint8_t) (arg ? 0xff : 0); - pushBlock(&value, sizeof(value))->type = IPC::Request::Boolean; - return *this; - } - - IPC::Request & IPC::Request::push(const uint8_t arg) { - pushBlock(&arg, sizeof(arg))->type = IPC::Request::Uchar; - return *this; - } - - IPC::Request & IPC::Request::push(const int32_t arg) { - pushBlock(&arg, sizeof(arg))->type = IPC::Request::Int32; - return *this; - } - - IPC::Request & IPC::Request::push(const uint32_t arg) { - pushBlock(&arg, sizeof(arg))->type = IPC::Request::Uint32; - return *this; - } - - IPC::Request & IPC::Request::pop(std::string &value) { - DataBlock * block = getNextBlock(); - - if(block->type != IPC::Request::String) - throw std::runtime_error("Invalid format"); - - const char *ptr = (const char *) (block+1); - - in.current += (strlen(ptr)+1+sizeof(DataBlock)); - - value.assign(ptr); - - return *this; - } - - IPC::Request & IPC::Request::Request::pop(int &value) { - - DataBlock * block = getNextBlock(); - - switch(block->type) { - case IPC::Request::Int16: - value = * ((int16_t *) (block+1)); - in.current += sizeof(int16_t) + sizeof(DataBlock); - break; - - case IPC::Request::Int32: - value = * ((int32_t *) (block+1)); - in.current += sizeof(int32_t) + sizeof(DataBlock); - break; - - case IPC::Request::Int64: - value = * ((int64_t *) (block+1)); - in.current += sizeof(int64_t) + sizeof(DataBlock); - break; - - default: - throw std::runtime_error("Invalid format"); - } - - return *this; - } - - IPC::Request & IPC::Request::Request::pop(unsigned int &value) { - - DataBlock * block = getNextBlock(); - - switch(block->type) { - case IPC::Request::Uint16: - value = * ((uint16_t *) (block+1)); - in.current += sizeof(uint16_t) + sizeof(DataBlock); - break; - - case IPC::Request::Uint32: - value = * ((uint32_t *) (block+1)); - in.current += sizeof(uint32_t) + sizeof(DataBlock); - break; - - case IPC::Request::Uint64: - value = * ((uint64_t *) (block+1)); - in.current += sizeof(uint64_t) + sizeof(DataBlock); - break; - - default: - throw std::runtime_error("Invalid format"); - } - - return *this; - } - IPC::Request & IPC::Request::call() { #ifdef DEBUG // lib3270_trace_data(NULL,"Request block",(const char *) this->out.block, this->out.used); #endif // DEBUG + debug("Sending request with ", *this->outvalues, " elements"); + in.current = 0; if(!TransactNamedPipe( diff --git a/client/src/host/string.cc b/client/src/host/string.cc index 6cc3193..e0f82dd 100644 --- a/client/src/host/string.cc +++ b/client/src/host/string.cc @@ -46,16 +46,16 @@ std::string TN3270::Host::toString() const { return this->session->toString(); } -std::string TN3270::Host::toString(int baddr, size_t len, char lf) const { +std::string TN3270::Host::toString(int baddr, int len, char lf) const { this->session->waitForReady(this->timeout); return this->session->toString(baddr,len,lf); } -std::string TN3270::Host::toString(unsigned int row, unsigned int col, size_t sz, char lf) const { +std::string TN3270::Host::toString(unsigned int row, unsigned int col, int len, char lf) const { this->session->waitForReady(this->timeout); - return this->session->toString(row,col,sz,lf); + return this->session->toString(row,col,len,lf); } diff --git a/client/src/include/ipc-client-internals.h b/client/src/include/ipc-client-internals.h index 0377158..60e1c1d 100644 --- a/client/src/include/ipc-client-internals.h +++ b/client/src/include/ipc-client-internals.h @@ -180,7 +180,6 @@ /// @brief PW3270 IPC Request/Response. class Request { private: - Request(const IPC::Session &session); #ifdef _WIN32 /// @brief Pipe Handle. @@ -223,6 +222,9 @@ /// @brief Get next argument. DataBlock * getNextBlock() const; + /// @brief Pointer to number of variants in the output buffer. + uint16_t * outvalues; + #else struct { DBusMessage * in; @@ -234,6 +236,12 @@ #endif // _WIN32 + protected: + +#ifdef _WIN32 + Request(HANDLE hPipe, const char *name, uint16_t type); +#endif // _WIN32 + public: /// @brief Create a method call. diff --git a/client/src/session/remote/actions.cc b/client/src/session/remote/actions.cc index 812a3df..55b7147 100644 --- a/client/src/session/remote/actions.cc +++ b/client/src/session/remote/actions.cc @@ -71,8 +71,10 @@ .push(url) .call(); + /* if(seconds) this->waitForReady(seconds); + */ } diff --git a/client/src/session/remote/windows/request.cc b/client/src/session/remote/windows/request.cc index 7a4763b..b224fc1 100644 --- a/client/src/session/remote/windows/request.cc +++ b/client/src/session/remote/windows/request.cc @@ -44,44 +44,10 @@ namespace TN3270 { - #define PIPE_BUFFER_LENGTH 8192 - - IPC::Request::Request(const Session &session) { - - this->hPipe = session.hPipe; - - in.length = PIPE_BUFFER_LENGTH; - in.used = 0; - in.block = new uint8_t[in.length]; - - out.length = PIPE_BUFFER_LENGTH; - out.used = 0; - out.block = new uint8_t[out.length]; - + IPC::Request::Request(const Session &session, const char *method) : Request(session.hPipe, method, 3) { } - IPC::Request::Request(const Session &session, const char *method) : Request(session) { - - // Add name - strcpy((char *) out.block, method); - out.used += strlen((char *) method) + 1; - - // Add ID - *((uint16_t *) (out.block + out.used)) = (uint16_t) 3; - out.used += sizeof(uint16_t); - - } - - IPC::Request::Request(const Session &session, bool isSet, const char *property) : Request(session) { - - // Add name - strcpy((char *) out.block, property); - out.used += strlen((char *) property) + 1; - - // Add ID (SetProperty = 2, getProperty = 1) - *((uint16_t *) (out.block + out.used)) = (uint16_t) (isSet ? 2 : 1); - out.used += sizeof(uint16_t); - + IPC::Request::Request(const Session &session, bool isSet, const char *property) : Request(session.hPipe, property, (isSet ? 2 : 1)) { } } diff --git a/client/src/testprogram/testprogram.cc b/client/src/testprogram/testprogram.cc index 748cbc0..711baa6 100644 --- a/client/src/testprogram/testprogram.cc +++ b/client/src/testprogram/testprogram.cc @@ -98,6 +98,8 @@ host.connect(nullptr); + /* + cout << "Wait for unlock returns " << host.getKeyboardLockState() << std::endl << "Connection state is " << toCharString(host.getConnectionState()) << std::endl @@ -123,6 +125,7 @@ host.pfkey(3); // host.disconnect(); + */ } catch(const std::exception &e) { diff --git a/common/src/include/lib3270/ipc.h b/common/src/include/lib3270/ipc.h index 6f2cc2b..b2258b6 100644 --- a/common/src/include/lib3270/ipc.h +++ b/common/src/include/lib3270/ipc.h @@ -423,8 +423,8 @@ Host & pop(std::string &text); std::string toString() const; - std::string toString(int baddr, size_t len = -1, char lf = '\n') const; - std::string toString(unsigned int row, unsigned int col, size_t len = -1, char lf = '\n') const; + std::string toString(int baddr, int len = -1, char lf = '\n') const; + std::string toString(unsigned int row, unsigned int col, int len = -1, char lf = '\n') const; template Host & push(T value) { diff --git a/server/src/core/methods/methods.c b/server/src/core/methods/methods.c index cdd5416..8d1d06f 100644 --- a/server/src/core/methods/methods.c +++ b/server/src/core/methods/methods.c @@ -73,7 +73,7 @@ int ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *req size_t ix; H3270 * hSession = ipc3270_get_session(object); - debug("%s(%s)",__FUNCTION__,method_name); + debug("%s(%s,request=%p,response=%p)",__FUNCTION__,method_name,request,response); lib3270_trace_event(hSession,"Method %s called on session %c\n",method_name,lib3270_get_session_id(hSession)); @@ -83,6 +83,8 @@ int ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *req int rc = methods[ix].call(object,request,response,error); + debug("rc=%d",rc); + if(rc) ipc3270_set_error(object,rc,error); diff --git a/server/src/core/methods/wait.c b/server/src/core/methods/wait.c index 0a065c4..99c19e6 100644 --- a/server/src/core/methods/wait.c +++ b/server/src/core/methods/wait.c @@ -61,7 +61,7 @@ int ipc3270_method_wait_for_keyboard_unlock(GObject *session, GVariant *request, guint seconds = 1; g_variant_get(request, "(u)", &seconds); - ipc3270_response_append_int32(response, (int32_t) lib3270_wait_for_keyboard_unlock(ipc3270_get_session(session),seconds)); + ipc3270_response_append_int32(response, (gint32) lib3270_wait_for_keyboard_unlock(ipc3270_get_session(session),seconds)); return 0; } diff --git a/server/src/core/windows/inout.c b/server/src/core/windows/inout.c index 93d9cd8..13ccea5 100644 --- a/server/src/core/windows/inout.c +++ b/server/src/core/windows/inout.c @@ -232,6 +232,8 @@ GVariant * ipc3270_unpack(const unsigned char *packet, int *id) { packet += strlen((const char *) packet)+1; // Get Packet ID or error code. + debug("Request type is %u",(unsigned int) *((guint16 *) packet)); + if(id) { *id = (int) *((guint16 *) packet); } @@ -291,6 +293,7 @@ GVariant * ipc3270_unpack(const unsigned char *packet, int *id) { break; default: + g_message("Unexpected format for argument %d: \"%c\"",ix,descrs[ix+1]); errno = EINVAL; return NULL; } diff --git a/server/src/core/windows/pipesource.c b/server/src/core/windows/pipesource.c index dd57f0b..ffe27f6 100644 --- a/server/src/core/windows/pipesource.c +++ b/server/src/core/windows/pipesource.c @@ -106,34 +106,46 @@ static void process_input(IPC3270_PIPE_SOURCE *source, DWORD cbRead) { debug("Received packet \"%s\" with %u bytes", request_name, (unsigned int) cbRead); g_autoptr (GError) error = NULL; - g_autoptr (GVariant) parameters = ipc3270_unpack(source->buffer, &request_type); g_autoptr (GVariant) response = NULL; + g_autoptr (GVariant) parameters = ipc3270_unpack(source->buffer, &request_type); - // Process query - switch(request_type) { - case 1: // getProperty - response = ipc3270_get_property(source->object, request_name, &error); - break; + if(parameters) { - case 2: // setProperty - ipc3270_set_property(source->object, request_name, parameters, &error); - response = g_variant_new_int32(0); - break; + // Process query + switch(request_type) { + case 1: // getProperty + response = ipc3270_get_property(source->object, request_name, &error); + break; + + case 2: // setProperty + ipc3270_set_property(source->object, request_name, parameters, &error); + response = g_variant_new_int32(0); + break; + + case 3: // method + { + g_autoptr(GObject) rsp = ipc3270_response_new(); - case 3: // method - { - g_autoptr(GObject) rsp = ipc3270_response_new(); - ipc3270_method_call(source->object, request_name, parameters, response, &error); + debug("Parameters: %p", parameters); + debug("rsp: %p", rsp); - if(ipc3270_response_has_values(rsp)) - response = ipc3270_response_steal_value(rsp); + ipc3270_method_call(source->object, request_name, parameters, rsp, &error); + + if(ipc3270_response_has_values(rsp)) + response = ipc3270_response_steal_value(rsp); + + } + break; + + default: + g_message("Rejecting request \"%s\": Invalid type %d",request_name, request_type); + g_set_error(&error,IPC3270(source->object)->error_domain,EINVAL,"Invalid or unexpected type %d",request_type); } - break; - default: - g_message("Rejecting request \"%s\": Invalid type %d",request_name, request_type); - g_set_error(&error,IPC3270(source->object)->error_domain,EINVAL,"Invalid or unexpected type %d",request_type); + } else if(!error) { + + g_set_error(&error,IPC3270(source->object)->error_domain,errno ? errno : EINVAL,"Can't parse parameter list"); } -- libgit2 0.21.2