diff --git a/client/Makefile.in b/client/Makefile.in index ae10b26..e49eeb0 100644 --- a/client/Makefile.in +++ b/client/Makefile.in @@ -33,6 +33,7 @@ MAIN_SOURCES= \ $(wildcard src/core/*.cc) \ $(wildcard src/core/@OSNAME@/*.cc) \ $(wildcard src/core/@OSNAME@/*.rc) \ + $(wildcard src/session/*.cc) \ $(wildcard src/session/local/*.cc) \ $(wildcard src/session/remote/*.cc) @@ -55,6 +56,7 @@ XGETTEXT=@XGETTEXT@ MSGCAT=@MSGCAT@ WINDRES=@WINDRES@ AR=@AR@ +VALGRIND=@VALGRIND@ #---[ Paths ]---------------------------------------------------------------------------- @@ -310,8 +312,18 @@ $(BINDBG)/lib$(MODULE_NAME)@LIBEXT@: \ run: \ $(BINDBG)/$(MODULE_NAME)-client@EXEEXT@ +ifeq ($(VALGRIND),no) + + @LD_LIBRARY_PATH=$(BINDBG) \ + $(BINDBG)/$(MODULE_NAME)-client@EXEEXT@ + +else + @touch valgrind.suppression + @LD_LIBRARY_PATH=$(BINDBG) \ + $(VALGRIND) --leak-check=full --track-origins=yes --gen-suppressions=all --suppressions=valgrind.suppression \ $(BINDBG)/$(MODULE_NAME)-client@EXEEXT@ +endif #---[ Clean Targets ]-------------------------------------------------------------------- diff --git a/client/lib3270++.cbp b/client/lib3270++.cbp index ba6ca38..1b6f2b3 100644 --- a/client/lib3270++.cbp +++ b/client/lib3270++.cbp @@ -53,8 +53,15 @@ + + - + + + + + + diff --git a/client/src/core/abstract.cc b/client/src/core/abstract.cc index 9e0d712..842274c 100644 --- a/client/src/core/abstract.cc +++ b/client/src/core/abstract.cc @@ -51,8 +51,6 @@ this->converter.host = (iconv_t) (-1); #endif - this->baddr = 0; - } Abstract::Session::~Session() { @@ -72,6 +70,17 @@ /// @brief Setup charsets void Abstract::Session::setCharSet(const char *remote, const char *local) { + if(!local) { + + // TODO: Detect the current value (maybee something like g_charset) +#ifdef _WIN32 + local = "CP1252"; +#else + local = "UTF-8"; +#endif // _WIN32 + + } + #ifdef HAVE_ICONV if(this->converter.local != (iconv_t) (-1)) @@ -101,24 +110,19 @@ } /// @brief Converte charset. - std::string Abstract::Session::convertCharset(iconv_t &converter, const char *str, int length) { + std::string Abstract::Session::convertCharset(iconv_t &converter, const std::string &str) { std::string rc; #ifdef HAVE_ICONV - size_t in; - - if(length < 0) - in = (size_t) strlen(str); - else - in = (size_t) length; + size_t in = str.size(); if(in && converter != (iconv_t)(-1)) { size_t out = (in << 1); char * ptr; char * outBuffer = (char *) malloc(out); - ICONV_CONST char * inBuffer = (ICONV_CONST char *) str; + ICONV_CONST char * inBuffer = (ICONV_CONST char *) str.c_str(); memset(ptr=outBuffer,0,out); @@ -141,13 +145,13 @@ } /// @brief Converte string recebida do host para o charset atual. - std::string Abstract::Session::convertFromHost(const char *str, int length) const { - return convertCharset(const_cast(this)->converter.local,str,length); + std::string Abstract::Session::convertFromHost(const std::string &str) const { + return convertCharset(const_cast(this)->converter.local,str); } /// @brief Converte string do charset atual para o charset do host. - std::string Abstract::Session::convertToHost(const char *str, int length) const { - return convertCharset(const_cast(this)->converter.host,str,length); + std::string Abstract::Session::convertToHost(const std::string &str) const { + return convertCharset(const_cast(this)->converter.host,str); } diff --git a/client/src/core/constants.cc b/client/src/core/constants.cc index ac6155c..7402dd5 100644 --- a/client/src/core/constants.cc +++ b/client/src/core/constants.cc @@ -36,11 +36,20 @@ * */ - #include + #include + #include /*---[ Implement ]----------------------------------------------------------------------------------*/ +TN3270_PUBLIC const char * getVersion() { + return PACKAGE_VERSION; +} + +TN3270_PUBLIC const char * getRevision() { + return LIB3270_STRINGIZE_VALUE_OF(PACKAGE_RELEASE); +} + TN3270_PUBLIC const char * toCharString(const TN3270::Action action) { static const char * actions[] = { diff --git a/client/src/core/host.cc b/client/src/core/host.cc index 6748a61..b472220 100644 --- a/client/src/core/host.cc +++ b/client/src/core/host.cc @@ -49,6 +49,7 @@ namespace TN3270 { + /* Host::Host(const char *id, const char *url, time_t timeout) { debug("Creating host id=\"", id); @@ -464,7 +465,7 @@ return *this; } - + */ } diff --git a/client/src/core/linux/request.cc b/client/src/core/linux/request.cc index c4c917e..8a6491c 100644 --- a/client/src/core/linux/request.cc +++ b/client/src/core/linux/request.cc @@ -44,6 +44,7 @@ namespace TN3270 { + /* IPC::Request::Request(const Session &session) { this->conn = session.conn; this->msg.in = nullptr; @@ -67,16 +68,6 @@ IPC::Request::Request(const Session &session, bool isSet, const char *property) : Request(session) { -/* - dbus-send \ - --session \ - --dest=br.com.bb.pw3270.a\ - --print-reply \ - "/br/com/bb/tn3270/session" \ - "org.freedesktop.DBus.Properties.Get" \ - string:br.com.bb.tn3270.session \ - string:${1} -*/ this->msg.out = dbus_message_new_method_call( session.name.c_str(), // Destination session.path.c_str(), // Path @@ -262,6 +253,8 @@ } + */ + } diff --git a/client/src/core/linux/session.cc b/client/src/core/linux/session.cc index 5b93c64..4376026 100644 --- a/client/src/core/linux/session.cc +++ b/client/src/core/linux/session.cc @@ -58,6 +58,7 @@ namespace TN3270 { + /* IPC::Session::Session(const char *id) : Abstract::Session() { // Create D-Bus session. @@ -92,6 +93,7 @@ IPC::Session::~Session() { } + */ } diff --git a/client/src/core/session.cc b/client/src/core/session.cc index 1c26778..d838638 100644 --- a/client/src/core/session.cc +++ b/client/src/core/session.cc @@ -43,37 +43,33 @@ namespace TN3270 { - /// @brief Create a tn3270 session. - Session * Session::create(const char *id) { - - debug("Creating session with ID \"",id,"\""); + Session * Session::getInstance(const char *id) { if(!(id && *id)) { - return new Local::Session(); + return Local::getSessionInstance(); } - return new IPC::Session(id); + // return new IPC::Session(id); + return nullptr; } Session::Session() { - } Session::~Session() { - - } - - void Session::insert(Event::Type type, std::function listener) { } /// @brief Fire event. void Session::fire(const Event &event) { + } - + /* + void Session::insert(Event::Type type, std::function listener) { } + Session & Session::push(const PFKey key) { return pfkey( ((unsigned short) key) + 1); } @@ -93,7 +89,7 @@ void Session::setCharSet(const char *charset) { } - + */ } diff --git a/client/src/include/ipc-client-internals.h b/client/src/include/ipc-client-internals.h index 7ec2ad3..f3627f6 100644 --- a/client/src/include/ipc-client-internals.h +++ b/client/src/include/ipc-client-internals.h @@ -36,9 +36,9 @@ * */ -#ifndef PRIVATE_H_INCLUDED +#ifndef IPC_CLIENT_INTERNALS_INCLUDED - #define PRIVATE_H_INCLUDED + #define IPC_CLIENT_INTERNALS_INCLUDED #include @@ -70,12 +70,6 @@ #include #endif // HAVE_ICONV -#ifdef WIN32 - #define SYSTEM_CHARSET "CP1252" -#else - #define SYSTEM_CHARSET "UTF-8" -#endif // WIN32 - #ifdef DEBUG inline void console(std::ostream &out) { @@ -121,24 +115,38 @@ #endif /// @brief Converte charset. - static std::string convertCharset(iconv_t &converter, const char *str, int length); + static std::string convertCharset(iconv_t &converter, const std::string &str); protected: - /// @brief Current in/out position. - int baddr; - Session(); virtual ~Session(); /// @brief Setup charsets - void setCharSet(const char *remote, const char *local = SYSTEM_CHARSET); + void setCharSet(const char *remote, const char *local); /// @brief Converte string recebida do host para o charset atual. - std::string convertFromHost(const char *str, int length = -1) const; + std::string convertFromHost(const std::string &str) const; /// @brief Converte string do charset atual para o charset do host. - std::string convertToHost(const char *str, int length = -1) const; + std::string convertToHost(const std::string &str) const; + + // Get strings from lib3270 without charset conversion. + virtual std::string get() const = 0; + virtual std::string get(int baddr, size_t len, char lf) const = 0; + virtual std::string get(int row, int col, size_t sz, char lf) const = 0; + + // Set strings to lib3270 without charset conversion. + virtual void set(const std::string &str) = 0; + virtual void set(int baddr, const std::string &str) = 0; + virtual void set(int row, int col, const std::string &str) = 0; + + public: + + // Contents + std::string toString(int baddr = 0, size_t len = -1, char lf = '\n') const override; + std::string toString(int row, int col, size_t sz, char lf = '\n') const override; + }; @@ -147,6 +155,15 @@ /// @brief lib3270 direct access objects (no IPC); namespace Local { + TN3270_PRIVATE Session * getSessionInstance(); + + } + + /* + + /// @brief lib3270 direct access objects (no IPC); + namespace Local { + class TN3270_PRIVATE Session : public TN3270::Abstract::Session { private: @@ -429,7 +446,8 @@ }; } + */ } -#endif // PRIVATE_H_INCLUDED +#endif // IPC_CLIENT_INTERNALS_INCLUDED diff --git a/client/src/session/get.cc b/client/src/session/get.cc new file mode 100644 index 0000000..9703f10 --- /dev/null +++ b/client/src/session/get.cc @@ -0,0 +1,55 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + +#include + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + std::string Abstract::Session::toString(int baddr, size_t len, char lf) const { + return convertFromHost(get(baddr,len,lf)); + } + + std::string Abstract::Session::toString(int row, int col, size_t sz, char lf) const { + return convertFromHost(get(row,col,sz,lf)); + } + + } + + diff --git a/client/src/session/local/actions.cc b/client/src/session/local/actions.cc new file mode 100644 index 0000000..e627311 --- /dev/null +++ b/client/src/session/local/actions.cc @@ -0,0 +1,95 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + #include + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + void Local::Session::connect(const char *url, bool wait) { + + std::lock_guard lock(sync); + chkResponse(lib3270_connect_url(hSession,url,(wait ? 1 : 0))); + } + + void Local::Session::disconnect() { + + std::lock_guard lock(sync); + chkResponse(lib3270_disconnect(hSession)); + } + + void Local::Session::wait(unsigned short seconds) const { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_wait(this->hSession, seconds)); + + } + + void Local::Session::waitForReady(time_t timeout) const { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_wait_for_ready(this->hSession, timeout)); + + } + + void Local::Session::waitForChange(unsigned short seconds) const { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_wait_for_update(this->hSession, seconds)); + + } + + void Local::Session::pfkey(unsigned short value) { + + std::lock_guard lock(sync); + chkResponse(lib3270_pfkey(hSession,value)); + + } + + void Local::Session::pakey(unsigned short value) { + + std::lock_guard lock(sync); + chkResponse(lib3270_pakey(hSession,value)); + + } + + } + + diff --git a/client/src/session/local/events.cc b/client/src/session/local/events.cc index ed9e8f8..a60f670 100644 --- a/client/src/session/local/events.cc +++ b/client/src/session/local/events.cc @@ -36,11 +36,7 @@ * */ - #include - #include - #include - #include - #include + #include "private.h" extern "C" { #include @@ -179,7 +175,6 @@ } - } diff --git a/client/src/session/local/get.cc b/client/src/session/local/get.cc new file mode 100644 index 0000000..e55529b --- /dev/null +++ b/client/src/session/local/get.cc @@ -0,0 +1,109 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + std::string Local::Session::get() const { + + std::lock_guard lock(const_cast(this)->sync); + + lib3270_autoptr(char) text = lib3270_get_string_at_address(hSession, 0, -1, '\n'); + + if(!text) { + throw std::runtime_error( _("Can't get screen contents") ); + } + + return std::string(text); + } + + std::string Local::Session::get(int baddr, size_t len, char lf) const { + + std::lock_guard lock(const_cast(this)->sync); + + lib3270_autoptr(char) text = lib3270_get_string_at_address(hSession, baddr, len, lf); + + if(!text) { + throw std::runtime_error( _("Can't get screen contents") ); + } + + return std::string(text); + } + + std::string Local::Session::get(int row, int col, size_t sz, char lf) const { + + std::lock_guard lock(const_cast(this)->sync); + + lib3270_autoptr(char) text = lib3270_get_string_at(hSession, row, col, sz, lf); + + if(!text) { + throw std::runtime_error( _("Can't get screen contents") ); + } + + return std::string(text); + + } + + ProgramMessage Local::Session::getProgramMessage() const { + + std::lock_guard lock(const_cast(this)->sync); + return (ProgramMessage) lib3270_get_program_message(this->hSession); + + } + + ConnectionState Local::Session::getConnectionState() const { + + std::lock_guard lock(const_cast(this)->sync); + return (ConnectionState) lib3270_get_connection_state(this->hSession); + + } + + SSLState Local::Session::getSSLState() const { + + std::lock_guard lock(const_cast(this)->sync); + return (TN3270::SSLState) lib3270_get_ssl_state(hSession); + + } + + + } + + diff --git a/client/src/session/local/init.cc b/client/src/session/local/init.cc new file mode 100644 index 0000000..f42f02e --- /dev/null +++ b/client/src/session/local/init.cc @@ -0,0 +1,270 @@ +/* + * "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/session/local/init.cc + * + * @brief Implement lib3270 direct access layout (NO IPC). + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + + extern "C" { + #include + } + + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + Session * Local::getSessionInstance() { + return new Local::Session(); + } + + #ifdef _WIN32 + + string getUserName() { + + char username[UNLEN + 1]; + DWORD szName = sizeof(username); + + memset(username,0,UNLEN + 1); + + if(!GetUserName(username, &szName)) { + return "?"; + } + + return string(username); + + } + + static void writeLog(HANDLE hEventLog, const char *msg, int rc = (int) GetLastError()) { + + + debug(msg," rc=",rc); + + if(hEventLog) { + + string username = getUserName(); + char lasterror[1024]; + snprintf(lasterror,sizeof(lasterror),"The error code was %d",rc); + + const char *outMsg[] = { + username.c_str(), + msg, + lasterror + }; + + ReportEvent( + hEventLog, + EVENTLOG_ERROR_TYPE, + 1, + 0, + NULL, + (sizeof(outMsg) / sizeof(outMsg[0])), + 0, + outMsg, + NULL + ); + + } + + } + + static string getInstallLocation(HANDLE hEventLog) { + + LSTATUS rc; + HKEY hKey = 0; + + static const char * keys[] = { +#ifdef LIB3270_NAME + "Software\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME), + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME), +#endif + "Software\\pw3270", + "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\pw3270" + }; + + size_t ix; + + string installLocation; + + for(ix = 0; installLocation.empty() && ix < (sizeof(keys)/sizeof(keys[0])); ix++) { + + debug(ix,"=",keys[ix]); + + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keys[ix],0,KEY_QUERY_VALUE,&hKey); + if(rc == ERROR_SUCCESS) { + + unsigned long datatype; // #defined in winnt.h (predefined types 0-11) + char datadir[4096]; + unsigned long datalen = sizeof(datadir); + + memset(datadir,0,datalen); + + rc = RegQueryValueExA(hKey,"InstallLocation",NULL,&datatype,(LPBYTE) datadir,&datalen); + if(rc == ERROR_SUCCESS) { + + debug("Found: ",datadir); + + installLocation.assign(datadir); + string username = getUserName(); + + const char *outMsg[] = { + username.c_str(), + "Found LIB3270 installation", + keys[ix], + installLocation.c_str() + }; + + ReportEvent( + hEventLog, + EVENTLOG_INFORMATION_TYPE, + 1, + 0, + NULL, + (sizeof(outMsg) / sizeof(outMsg[0])), + 0, + outMsg, + NULL + ); + + } + + RegCloseKey(hKey); + + } + + } + + return installLocation; + } + + #endif // _WIN32 + + Local::Session::Session() : Abstract::Session() { + + std::lock_guard lock(sync); + +#ifdef _WIN32 + { + static bool initialized = false; + + if(!initialized) { + +#ifdef LIB3270_NAME + HANDLE hEventLog = RegisterEventSource(NULL, LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME)); +#else + HANDLE hEventLog = RegisterEventSource(NULL, PACKAGE_NAME); +#endif // LIB3270_NAME + + string installLocation = getInstallLocation(hEventLog); + + if(installLocation.empty()) { + + writeLog(hEventLog, "Can't identify lib3270 installation path"); + + } else { + + // TODO: Understand why SetDefaultDllDirectories & AddDllDirectory causes failure in DNS resolution. + + + SetCurrentDirectory(installLocation.c_str()); + +/* + wchar_t *path = (wchar_t *) malloc(sizeof(datadir)*sizeof(wchar_t)); + mbstowcs(path, datadir, 4095); + + if(!SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS)) { + writeLog(hEventLog,"SetDefaultDllDirectories has failed"); + } +#ifdef DEBUG + else { + debug("SetDefaultDllDirectories has suceeded"); + } +#endif + + if(!AddDllDirectory(path)) { + string msg = "Can't add "; + msg += datadir; + msg += " to directory path"; + writeLog(hEventLog,msg.c_str()); + } +#ifdef DEBUG + else { + debug("AddDllDirectory has suceeded"); + } +#endif + free(path); + +*/ + } + + initialized = true; + DeregisterEventSource(hEventLog); + + } + + } +#endif // _WIN32 + + this->hSession = lib3270_session_new(""); + + lib3270_set_user_data(this->hSession,(void *) this); + setCharSet(); + lib3270_set_popup_handler(this->hSession, popupHandler); + + // Setup callbacks + struct lib3270_session_callbacks *cbk; + + cbk = lib3270_get_session_callbacks(this->hSession,sizeof(struct lib3270_session_callbacks)); + if(!cbk) { + throw runtime_error( _("Invalid callback table, possible version mismatch in lib3270") ); + } + + cbk->update_connect = connectHandler; + + } + + Local::Session::~Session() { + + std::lock_guard lock(sync); + + lib3270_session_free(this->hSession); + this->hSession = nullptr; + + } + + } + + diff --git a/client/src/session/local/private.h b/client/src/session/local/private.h new file mode 100644 index 0000000..73c66ed --- /dev/null +++ b/client/src/session/local/private.h @@ -0,0 +1,130 @@ +/* + * "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 private.h + * + * @brief Private definitions for local session. + * + * @author perry.werneck@gmail.com + * + */ + +#ifndef PRIVATE_H_INCLUDED + + #define PRIVATE_H_INCLUDED + + #include + #include + #include + #include + #include + + using std::string; + using std::runtime_error; + + namespace TN3270 { + + namespace Local { + + class TN3270_PRIVATE Session : public TN3270::Abstract::Session { + private: + + /// @brief Handle of the related instance of lib3270 + H3270 * hSession; + + /// @brief Mutex to serialize access to lib3270 + std::mutex sync; + + /// @brief Popup Handler. + static void popupHandler(H3270 *session, LIB3270_NOTIFY type, const char *title, const char *msg, const char *fmt, va_list arg); + + /// @brief Connect Handler. + static void connectHandler(H3270 *session, unsigned char connected); + + /// @brief Wait for network events + void wait(time_t timeout = 5); + + /// @brief Check lib3270 return codes, launch exception when failed. + static void chkResponse(int rc); + + protected: + + // Get strings from lib3270 without charset conversion. + std::string get() const override; + std::string get(int baddr, size_t len, char lf) const override; + std::string get(int row, int col, size_t sz, char lf) const override; + + // Set strings to lib3270 without charset conversion. + void set(const std::string &str) override; + void set(int baddr, const std::string &str) override; + void set(int row, int col, const std::string &str) override; + + public: + + Session(); + virtual ~Session(); + + // Actions + void connect(const char *url, bool wait) override; + void disconnect() override; + void pfkey(unsigned short value) override; + void pakey(unsigned short value) override; + + void wait(unsigned short seconds) const override; + void waitForReady(time_t timeout) const override; + void waitForChange(unsigned short seconds) const override; + + // States + ProgramMessage getProgramMessage() const override; + ConnectionState getConnectionState() const override; + SSLState getSSLState() const override; + + // Properties. + std::string getVersion() const override; + std::string getRevision() const override; + std::string getLUName() const override; + std::string getHostURL() const override; + unsigned short getScreenWidth() const override; + unsigned short getScreenHeight() const override; + unsigned short getScreenLength() const override; + void setUnlockDelay(unsigned short delay) override; + void setCharSet(const char *charset = NULL) override; + void setCursor(unsigned short addr) override; + void setCursor(unsigned short row, unsigned short col) override; + unsigned short getCursorAddress() override; + + + }; + + } + + } + +#endif // PRIVATE_H_INCLUDED diff --git a/client/src/session/local/properties.cc b/client/src/session/local/properties.cc new file mode 100644 index 0000000..5418405 --- /dev/null +++ b/client/src/session/local/properties.cc @@ -0,0 +1,87 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + void Local::Session::setCharSet(const char *charset) { + Abstract::Session::setCharSet(lib3270_get_display_charset(this->hSession),charset); + } + + unsigned short Local::Session::getScreenWidth() const { + std::lock_guard lock(const_cast(this)->sync); + return (unsigned short) lib3270_get_width(hSession); + } + + unsigned short Local::Session::getScreenHeight() const { + std::lock_guard lock(const_cast(this)->sync); + return (unsigned short) lib3270_get_height(hSession); + } + + unsigned short Local::Session::getScreenLength() const { + std::lock_guard lock(const_cast(this)->sync); + return (unsigned short) lib3270_get_length(hSession); + } + + void Local::Session::setUnlockDelay(unsigned short delay) { + std::lock_guard lock(sync); + chkResponse(lib3270_set_unlock_delay(hSession,delay)); + } + + void Local::Session::setCursor(unsigned short addr) { + std::lock_guard lock(sync); + chkResponse(lib3270_set_cursor_address(hSession,addr)); + } + + void Local::Session::setCursor(unsigned short row, unsigned short col) { + std::lock_guard lock(sync); + chkResponse(lib3270_set_cursor_position(hSession,row,col)); + } + + unsigned short Local::Session::getCursorAddress() { + std::lock_guard lock(sync); + return lib3270_get_cursor_address(hSession); + } + + + } + + diff --git a/client/src/session/local/session.cc b/client/src/session/local/session.cc deleted file mode 100644 index 6ad0d5e..0000000 --- a/client/src/session/local/session.cc +++ /dev/null @@ -1,704 +0,0 @@ -/* - * "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/session/local/session.cc - * - * @brief Implement lib3270 direct access layout (NO IPC). - * - * @author perry.werneck@gmail.com - * - */ - - #ifdef _WIN32 - - #include - #include - #include - #include - - #endif // _WIN32 - - #include - #include - #include - #include - #include - #include - - extern "C" { - #include - - - } - - using std::string; - -/*---[ Implement ]----------------------------------------------------------------------------------*/ - - namespace TN3270 { - - #ifdef _WIN32 - - string getUserName() { - - char username[UNLEN + 1]; - DWORD szName = sizeof(username); - - memset(username,0,UNLEN + 1); - - if(!GetUserName(username, &szName)) { - return "?"; - } - - return string(username); - - } - - static void writeLog(HANDLE hEventLog, const char *msg, int rc = (int) GetLastError()) { - - - debug(msg," rc=",rc); - - if(hEventLog) { - - string username = getUserName(); - char lasterror[1024]; - snprintf(lasterror,sizeof(lasterror),"The error code was %d",rc); - - const char *outMsg[] = { - username.c_str(), - msg, - lasterror - }; - - ReportEvent( - hEventLog, - EVENTLOG_ERROR_TYPE, - 1, - 0, - NULL, - (sizeof(outMsg) / sizeof(outMsg[0])), - 0, - outMsg, - NULL - ); - - } - - } - - static string getInstallLocation(HANDLE hEventLog) { - - LSTATUS rc; - HKEY hKey = 0; - - static const char * keys[] = { -#ifdef LIB3270_NAME - "Software\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME), - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME), -#endif - "Software\\pw3270", - "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\pw3270" - }; - - size_t ix; - - string installLocation; - - for(ix = 0; installLocation.empty() && ix < (sizeof(keys)/sizeof(keys[0])); ix++) { - - debug(ix,"=",keys[ix]); - - rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,keys[ix],0,KEY_QUERY_VALUE,&hKey); - if(rc == ERROR_SUCCESS) { - - unsigned long datatype; // #defined in winnt.h (predefined types 0-11) - char datadir[4096]; - unsigned long datalen = sizeof(datadir); - - memset(datadir,0,datalen); - - rc = RegQueryValueExA(hKey,"InstallLocation",NULL,&datatype,(LPBYTE) datadir,&datalen); - if(rc == ERROR_SUCCESS) { - - debug("Found: ",datadir); - - installLocation.assign(datadir); - string username = getUserName(); - - const char *outMsg[] = { - username.c_str(), - "Found LIB3270 installation", - keys[ix], - installLocation.c_str() - }; - - ReportEvent( - hEventLog, - EVENTLOG_INFORMATION_TYPE, - 1, - 0, - NULL, - (sizeof(outMsg) / sizeof(outMsg[0])), - 0, - outMsg, - NULL - ); - - } - - RegCloseKey(hKey); - - } - - } - - return installLocation; - } - - #endif // _WIN32 - - Local::Session::Session() : Abstract::Session() { - - std::lock_guard lock(sync); - -#ifdef _WIN32 - { - static bool initialized = false; - - if(!initialized) { - -#ifdef LIB3270_NAME - HANDLE hEventLog = RegisterEventSource(NULL, LIB3270_STRINGIZE_VALUE_OF(LIB3270_NAME)); -#else - HANDLE hEventLog = RegisterEventSource(NULL, PACKAGE_NAME); -#endif // LIB3270_NAME - - string installLocation = getInstallLocation(hEventLog); - - if(installLocation.empty()) { - - writeLog(hEventLog, "Can't identify lib3270 installation path"); - - } else { - - // TODO: Understand why SetDefaultDllDirectories & AddDllDirectory causes failure in DNS resolution. - - - SetCurrentDirectory(installLocation.c_str()); - -/* - wchar_t *path = (wchar_t *) malloc(sizeof(datadir)*sizeof(wchar_t)); - mbstowcs(path, datadir, 4095); - - if(!SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_USER_DIRS)) { - writeLog(hEventLog,"SetDefaultDllDirectories has failed"); - } -#ifdef DEBUG - else { - debug("SetDefaultDllDirectories has suceeded"); - } -#endif - - if(!AddDllDirectory(path)) { - string msg = "Can't add "; - msg += datadir; - msg += " to directory path"; - writeLog(hEventLog,msg.c_str()); - } -#ifdef DEBUG - else { - debug("AddDllDirectory has suceeded"); - } -#endif - free(path); - -*/ - } - - initialized = true; - DeregisterEventSource(hEventLog); - - } - - } -#endif // _WIN32 - - this->hSession = lib3270_session_new(""); - - lib3270_set_user_data(this->hSession,(void *) this); - setCharSet(lib3270_get_display_charset(this->hSession)); - - lib3270_set_popup_handler(this->hSession, popupHandler); - - // Setup callbacks - struct lib3270_session_callbacks *cbk; - - cbk = lib3270_get_session_callbacks(this->hSession,sizeof(struct lib3270_session_callbacks)); - if(!cbk) { - throw std::runtime_error( _("Invalid callback table, possible version mismatch in lib3270") ); - } - - cbk->update_connect = connectHandler; - - - } - - Local::Session::~Session() { - - std::lock_guard lock(sync); - - lib3270_session_free(this->hSession); - this->hSession = nullptr; - } - - void Local::Session::chkResponse(int rc) { - - if(rc == 0) - return; - -#ifdef _WIN32 - if(rc == ENOTCONN) - throw std::runtime_error("Not connected"); -#endif // _WIN32 - - throw std::system_error(rc, std::system_category()); - - } - - void Local::Session::wait(time_t timeout) { - - std::lock_guard lock(sync); - chkResponse(lib3270_wait(this->hSession, timeout)); - - } - - void Local::Session::connect(const char *url) { - std::lock_guard lock(sync); - chkResponse(lib3270_connect_url(hSession,url,0)); - } - - void Local::Session::disconnect() { - std::lock_guard lock(sync); - lib3270_disconnect(hSession); - } - - // Wait for session state. - void Local::Session::waitForReady(time_t timeout) throw() { - std::lock_guard lock(sync); - chkResponse(lib3270_wait_for_ready(hSession,timeout)); - } - - std::string Local::Session::toString(int baddr, size_t len, char lf) const { - - std::lock_guard lock(const_cast(this)->sync); - - char * text = lib3270_get_string_at_address(hSession, baddr, len, lf); - - if(!text) { - throw std::runtime_error( _("Can't get screen contents") ); - } - - string rc = convertFromHost(text); - - lib3270_free(text); - - return rc; - - } - - std::string Local::Session::toString(int row, int col, size_t sz, char lf) const { - - std::lock_guard lock(const_cast(this)->sync); - - char * text = lib3270_get_string_at(hSession, row, col, sz, lf); - - if(!text) { - throw std::runtime_error( _("Can't get screen contents") ); - } - - string rc = convertFromHost(text); - - lib3270_free(text); - - return rc; - } - - void Local::Session::getProperty(const char *name, int &value) const { - - const LIB3270_INT_PROPERTY * intprop = lib3270_get_int_properties_list(); - for(size_t ix = 0; intprop[ix].name; ix++) { - - if(!strcasecmp(name,intprop[ix].name)) { - - std::lock_guard lock(const_cast(this)->sync); - - value = intprop[ix].get(hSession); - - if(value < 0 && errno != 0) { - throw std::system_error(errno, std::system_category()); - } - - - } - - } - - throw std::system_error(ENOENT, std::system_category()); - - } - - void Local::Session::getProperty(const char *name, std::string &value) const { - - const LIB3270_STRING_PROPERTY * strprop = lib3270_get_string_properties_list(); - - for(size_t ix = 0; strprop[ix].name; ix++) { - - if(!strcasecmp(name,strprop[ix].name)) { - - std::lock_guard lock(const_cast(this)->sync); - - // Found it! - const char * str = strprop[ix].get(hSession); - - if(str) { - value.assign(str); - return; - } - - throw std::system_error(errno, std::system_category()); - - } - - } - - throw std::system_error(ENOENT, std::system_category()); - } - - void Local::Session::getProperty(const char *name, bool &value) const { - - LIB3270_TOGGLE toggle = lib3270_get_toggle_id(name); - if(toggle != (LIB3270_TOGGLE) -1) { - - // Is a Tn3270 toggle, get it! - std::lock_guard lock(const_cast(this)->sync); - value = lib3270_get_toggle(hSession,toggle); - - } - - throw std::system_error(ENOENT, std::system_category()); - } - - ProgramMessage Local::Session::getProgramMessage() const { - std::lock_guard lock(const_cast(this)->sync); - return (ProgramMessage) lib3270_get_program_message(this->hSession); - } - - ConnectionState Local::Session::getConnectionState() const { - std::lock_guard lock(const_cast(this)->sync); - return (ConnectionState) lib3270_get_connection_state(this->hSession); - } - - /// @brief Set field at current position, jumps to next writable field. - TN3270::Session & Local::Session::push(const char *text) { - std::lock_guard lock(sync); - - string converted = convertToHost(text); - - chkResponse(lib3270_input_string(this->hSession, (unsigned char *) converted.c_str(), converted.size())); - - return *this; - } - - TN3270::Session & Local::Session::input(const char *text, size_t length) { - std::lock_guard lock(sync); - - string converted = convertToHost(text,length); - - chkResponse(lib3270_input_string(this->hSession, (unsigned char *) converted.c_str(), converted.size())); - - return *this; - } - - TN3270::Session & Local::Session::push(int baddr, const char * text, int length) { - std::lock_guard lock(sync); - - string converted = convertToHost(text, length); - - if(lib3270_set_string_at_address(this->hSession,baddr,(unsigned char *) converted.c_str(),converted.length()) < 0) { - throw std::system_error(errno, std::system_category()); - } - - return *this; - } - - TN3270::Session & Local::Session::push(int row, int col, const char *text, int length) { - std::lock_guard lock(sync); - - string converted = convertToHost(text,length); - - if(lib3270_set_string_at(this->hSession,row,col,(unsigned char *) converted.c_str(),-1)) { - throw std::system_error(errno, std::system_category()); - } - - return *this; - } - - TN3270::Session & Local::Session::push(const Action action) { - - typedef int (*ActionCallback)(H3270 *); - - static const ActionCallback actions[] = { - lib3270_enter, // ENTER - lib3270_erase, // ERASE - lib3270_eraseeof, // ERASE_EOF - lib3270_eraseeol, // ERASE_EOL - lib3270_eraseinput, // ERASE_INPUT - lib3270_kybdreset, // KYBD_RESET - lib3270_newline, // NEWLINE - lib3270_clear, // CLEAR - lib3270_select_field, // SELECT_FIELD - lib3270_select_all, // SELECT_ALL - lib3270_unselect, // UNSELECT - lib3270_reselect, // RESELECT - lib3270_delete, // DELETE - lib3270_dup, // DUP - lib3270_fieldmark, // FIELDMARK - lib3270_backspace, // BACKSPACE - lib3270_previousword, // WORD_PREVIOUS - lib3270_nextword, // WORD_NEXT - lib3270_fieldend, // FIELD_END - lib3270_firstfield, // FIELD_FIRST - lib3270_nextfield, // FIELD_NEXT - lib3270_previousfield, // FIELD_PREVIOUS - lib3270_attn, // ATTN - lib3270_break, // BREAK - lib3270_deleteword, // WORD_DELETE - lib3270_deletefield, // FIELD_DELETE - lib3270_sysreq, // SYSREQ - }; - - if( ((size_t) action) > (sizeof(actions)/sizeof(actions[0]))) { - throw std::system_error(EINVAL, std::system_category()); - } - - std::lock_guard lock(sync); - - chkResponse(actions[(size_t) action](hSession)); - - return *this; - } - - TN3270::Session & Local::Session::pfkey(unsigned short value) { - - std::lock_guard lock(sync); - - chkResponse(lib3270_pfkey(hSession,(int) value)); - - return *this; - } - - TN3270::Session & Local::Session::pakey(unsigned short value) { - - std::lock_guard lock(sync); - - chkResponse(lib3270_pakey(hSession,(int) value)); - - return *this; - } - - - TN3270::Session & Local::Session::pop(int baddr, std::string &text) { - - std::lock_guard lock(sync); - - if(!lib3270_is_connected(hSession)) { - throw std::system_error(ENOTCONN, std::system_category()); - } - - char *contents = lib3270_get_field_text_at(hSession, baddr); - - if(!contents) { - throw std::system_error(errno, std::system_category()); - } - - text.assign(convertFromHost(contents).c_str()); - - lib3270_free(contents); - - return *this; - } - - TN3270::Session & Local::Session::pop(int row, int col, std::string &text) { - return this->pop(lib3270_translate_to_address(hSession,row,col),text); - } - - TN3270::Session & Local::Session::pop(std::string &text) { - - std::lock_guard lock(sync); - - if(!lib3270_is_connected(hSession)) { - throw std::system_error(ENOTCONN, std::system_category()); - } - - int baddr = lib3270_get_cursor_address(hSession); - if(baddr < 0) { - throw std::system_error(errno, std::system_category()); - } - - char *contents = lib3270_get_field_text_at(hSession, baddr); - - if(!contents) { - throw std::system_error(errno, std::system_category()); - } - - text.assign(convertFromHost(contents).c_str()); - - lib3270_free(contents); - - baddr = lib3270_get_next_unprotected(hSession,baddr); - if(!baddr) { - baddr = lib3270_get_next_unprotected(hSession,0); - } - - if(lib3270_set_cursor_address(hSession,baddr)) { - throw std::system_error(errno, std::system_category()); - } - - return *this; - } - - /// @brief Set cursor address. - /// - /// @param addr Cursor address. - TN3270::Session & Local::Session::setCursor(unsigned short addr) { - - if(lib3270_set_cursor_address(hSession,addr) < 0) { - throw std::system_error(errno, std::system_category()); - } - - return *this; - } - - /// @brief Get cursor address. - /// - /// @return - unsigned short Local::Session::getCursorAddress() { - - unsigned int position = lib3270_get_cursor_address(hSession); - - if(!position) - throw std::system_error(errno, std::system_category()); - - return position; - } - - - /// @brief Set cursor position. - /// - /// @param row New cursor row. - /// @param col New cursor column. - TN3270::Session & Local::Session::setCursor(unsigned short row, unsigned short col) { - - if(lib3270_set_cursor_position(hSession,row,col)) { - throw std::system_error(errno, std::system_category()); - } - - return *this; - - } - - // Get properties. - std::string Local::Session::getVersion() const { - return lib3270_get_version(); - } - - std::string Local::Session::getRevision() const { - return lib3270_get_revision(); - } - - std::string Local::Session::getLUName() const { - const char * luname = lib3270_get_luname(hSession); - if(luname) - return luname; - return ""; - } - - /// @brief Execute action by name. - TN3270::Session & Local::Session::action(const char *action_name) { - - chkResponse(lib3270_action(hSession,action_name)); - - return *this; - } - - /// @brief Wait. - TN3270::Session & Local::Session::wait(unsigned short seconds) { - chkResponse(lib3270_wait(hSession,seconds)); - return *this; - } - - /// @brief Wait for update. - TN3270::Session & Local::Session::waitForChange(unsigned short seconds) { - chkResponse(lib3270_wait_for_update(hSession,seconds)); - return *this; - } - - void Local::Session::setUnlockDelay(unsigned short delay) { - lib3270_set_unlock_delay(hSession,delay); - } - - std::string Local::Session::getHostURL() const { - return lib3270_get_url(hSession); - } - - void Local::Session::setHostURL(const char *url) { - lib3270_set_url(hSession,url); - } - - unsigned short Local::Session::getScreenWidth() const { - return (unsigned short) lib3270_get_width(hSession); - } - - unsigned short Local::Session::getScreenHeight() const { - return (unsigned short) lib3270_get_height(hSession); - } - - unsigned short Local::Session::getScreenLength() const { - return (unsigned short) lib3270_get_length(hSession); - } - - TN3270::SSLState Local::Session::getSSLState() const { - return (TN3270::SSLState) lib3270_get_ssl_state(hSession); - } - - } - - diff --git a/client/src/session/local/set.cc b/client/src/session/local/set.cc new file mode 100644 index 0000000..7491b19 --- /dev/null +++ b/client/src/session/local/set.cc @@ -0,0 +1,68 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + void Local::Session::set(const std::string &str) { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_input_string(hSession,(unsigned char *) str.c_str(),str.length())); + + } + + void Local::Session::set(int baddr, const std::string &str) { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_set_string_at_address(hSession,baddr,(unsigned char *) str.c_str(),str.length())); + + } + + void Local::Session::set(int row, int col, const std::string &str) { + + std::lock_guard lock(const_cast(this)->sync); + chkResponse(lib3270_set_string_at(hSession,row,col,(unsigned char *) str.c_str(),str.length())); + + } + + } + + diff --git a/client/src/session/local/tools.cc b/client/src/session/local/tools.cc new file mode 100644 index 0000000..997d688 --- /dev/null +++ b/client/src/session/local/tools.cc @@ -0,0 +1,91 @@ +/* + * "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 + * + * @author perry.werneck@gmail.com + * + */ + + #include "private.h" + +/*---[ Implement ]----------------------------------------------------------------------------------*/ + + namespace TN3270 { + + void Local::Session::chkResponse(int rc) { + + if(rc == 0) + return; + +#ifdef _WIN32 + if(rc == ENOTCONN) + throw std::runtime_error("Not connected"); +#endif // _WIN32 + + throw std::system_error(rc, std::system_category()); + + } + + std::string Local::Session::getVersion() const { + + std::lock_guard lock(const_cast(this)->sync); + return lib3270_get_version(); + + } + + std::string Local::Session::getRevision() const { + + std::lock_guard lock(const_cast(this)->sync); + return lib3270_get_revision(); + + } + + std::string Local::Session::getLUName() const { + + std::lock_guard lock(const_cast(this)->sync); + return lib3270_get_luname(hSession); + + } + + std::string Local::Session::getHostURL() const { + + std::lock_guard lock(const_cast(this)->sync); + return lib3270_get_url(hSession); + + } + + + + } + + diff --git a/client/src/session/remote/session.cc b/client/src/session/remote/session.cc deleted file mode 100644 index 1498a9e..0000000 --- a/client/src/session/remote/session.cc +++ /dev/null @@ -1,504 +0,0 @@ -/* - * "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/session/remote/session.cc - * - * @brief Implements lib3270 access using IPC calls. - * - * @author perry.werneck@gmail.com - * - */ - - #include - #include - -#ifndef _WIN32 - #include // sleep -#endif // _WIN32 - - using std::string; - -/*---[ Implement ]----------------------------------------------------------------------------------*/ - - namespace TN3270 { - - void IPC::Session::connect(const char *url) { - Request request(*this,"connect"); - request.push(url).call(); - } - - void IPC::Session::disconnect() { - Request(*this,"disconnect").call(); - } - - // Wait for session state. - void IPC::Session::waitForReady(time_t timeout) { - - int rc; - - time_t end = time(nullptr) + timeout; - - while(time(nullptr) < end) { - - debug("Running waitForReady request..."); - - Request(*this,"waitForReady") - .push((uint32_t) 1) - .call() - .pop(rc); - - debug("Wait for ready returned ",rc); - - if(rc == 0) - return; - - } - - throw std::system_error(ETIMEDOUT, std::system_category()); - - } - - std::string IPC::Session::toString(int baddr, size_t len, char lf) const { - - std::string rc; - - Request(*this,"getStringAtAddress") - .push((uint32_t) baddr) - .push((uint32_t) len) - .push((uint8_t) lf) - .call() - .pop(rc); - - return rc; - } - - std::string IPC::Session::toString(int row, int col, size_t sz, char lf) const { - - std::string rc; - - Request(*this,"getStringAt") - .push((uint32_t) row) - .push((uint32_t) col) - .push((uint32_t) sz) - .push((uint8_t) lf) - .call() - .pop(rc); - - return rc; - } - - ProgramMessage IPC::Session::getProgramMessage() const { - - int program_message; - getProperty("program_message",program_message); - return (ProgramMessage) program_message; - - } - - ConnectionState IPC::Session::getConnectionState() const { - - int cstate; - getProperty("cstate",cstate); - return (ConnectionState) cstate; - - } - - TN3270::Session & IPC::Session::input(const char *text, size_t length) { - - throw std::system_error(ENOTSUP, std::system_category()); - - return *this; - } - - /// @brief Set field at current position, jumps to next writable field. - TN3270::Session & IPC::Session::push(const char *text) { - - int rc; - - Request(*this,"setString") - .push(text) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - - } - - TN3270::Session & IPC::Session::push(int baddr, const char *text, int length) { - - int rc; - - if(length < 0) - length = strlen(text); - - Request(*this,"setStringAtAddress") - .push((uint32_t) baddr) - .push(text) - .push((uint32_t) length) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - - } - - TN3270::Session & IPC::Session::push(int row, int col, const char *text, int length) { - - int32_t rc; - - if(length < 0) - length = strlen(text); - - Request(*this,"setStringAt") - .push((uint32_t) row) - .push((uint32_t) col) - .push(text) - .push((uint32_t) length) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - - } - - TN3270::Session & IPC::Session::pfkey(unsigned short value) { - - int32_t rc; - - Request(*this,"pfkey") - .push((uint32_t) value) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - } - - TN3270::Session & IPC::Session::pakey(unsigned short value) { - - int32_t rc; - - Request(*this,"pakey") - .push((uint32_t) value) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - - } - - TN3270::Session & IPC::Session::push(const Action action) { - return this->action(toCharString(action)); - } - - TN3270::Session & IPC::Session::pop(int baddr, std::string &text) { - - Request(*this,"getFieldAtAddress") - .push((uint32_t) baddr) - .call() - .pop(text); - - return *this; - } - - TN3270::Session & IPC::Session::pop(int row, int col, std::string &text) { - - Request(*this,"getFieldAt") - .push((uint32_t) row) - .push((uint32_t) col) - .call() - .pop(text); - - return *this; - } - - TN3270::Session & IPC::Session::pop(std::string &text) { - - Request(*this,"getFieldAtCursor") - .call() - .pop(text); - - return *this; - - } - - /// @brief Set cursor address. - /// - /// @param addr Cursor address. - TN3270::Session & IPC::Session::setCursor(unsigned short addr) { - - setProperty("setCursorAddress", (uint32_t) addr); - return *this; - - } - - unsigned short IPC::Session::getCursorAddress() { - - int32_t address; - getProperty("cursor_address",address); - return (unsigned short) address; - - } - - /// @brief Set cursor position. - /// - /// @param row New cursor row. - /// @param col New cursor column. - TN3270::Session & IPC::Session::setCursor(unsigned short row, unsigned short col) { - - int32_t rc; - - Request(*this,"setCursorPosition") - .push((uint32_t) row) - .push((uint32_t) col) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - - } - - void IPC::Session::getProperty(const char *name, int &value) const { - - Request(*this,false,name) - .call() - .pop(value); - - } - - void IPC::Session::setProperty(const char *name, const int value) const { - - int32_t rc; - - Request(*this,true,name) - .push(value) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - } - - void IPC::Session::setProperty(const char *name, const char *value) const { - - int32_t rc; - - Request(*this,true,name) - .push(value) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - } - - void IPC::Session::getProperty(const char *name, std::string &value) const { - - Request(*this,false,name) - .call() - .pop(value); - - } - - void IPC::Session::getProperty(const char *name, bool &value) const { - throw std::system_error(ENOENT, std::system_category()); - } - - /// @brief Get lib3270 version. - std::string IPC::Session::getVersion() const { - - string rc; - getProperty("version",rc); - return rc; - - } - - /// @brief Get lib3270 revision. - std::string IPC::Session::getRevision() const { - - string rc; - getProperty("revision",rc); - return rc; - - } - - std::string IPC::Session::getLUName() const { - - string rc; - getProperty("luname",rc); - return rc; - - } - - /// @brief Execute action by name. - TN3270::Session & IPC::Session::action(const char *action_name) { - - int32_t rc; - - Request(*this,"action") - .push(action_name) - .call() - .pop(rc); - - if(rc) { - throw std::system_error((int) rc, std::system_category()); - } - - return *this; - } - - /// @brief Wait. - TN3270::Session & IPC::Session::wait(unsigned short seconds) { - - time_t end = time(nullptr) + seconds; - - while(time(nullptr) < end) { - -#ifdef _WIN32 - Sleep(1000); -#else - sleep(1); -#endif // _WIN32 - - if(getConnectionState() == TN3270::DISCONNECTED) - throw std::runtime_error("Disconnected"); - - } - - return *this; - } - - /// @brief Wait for update. - TN3270::Session & IPC::Session::waitForChange(unsigned short seconds) { - - int rc; - - time_t end = time(nullptr) + seconds; - - while(time(nullptr) < end) { - - debug("Running waitForUpdate request..."); - - Request(*this,"waitForUpdate") - .push((uint32_t) 1) - .call() - .pop(rc); - - debug("Wait for update returned ",rc); - - if(rc == 0) - return *this; - - } - - throw std::system_error(ETIMEDOUT, std::system_category()); - - } - - void IPC::Session::setUnlockDelay(unsigned short delay) { - - setProperty("unlock_delay", (uint32_t) delay); - - } - - std::string IPC::Session::getHostURL() const { - - std::string value; - getProperty("url",value); - return value; - - } - - void IPC::Session::setHostURL(const char *url) { - setProperty("url",url); - } - - unsigned short IPC::Session::getScreenWidth() const { - - int value; - getProperty("width",value); - return (unsigned short) value; - - } - - unsigned short IPC::Session::getScreenHeight() const { - - int value; - getProperty("height",value); - return (unsigned short) value; - - } - - unsigned short IPC::Session::getScreenLength() const { - - int value; - getProperty("length",value); - return (unsigned short) value; - - } - - TN3270::SSLState IPC::Session::getSSLState() const { - - int value; - getProperty("sslstate",value); - return (TN3270::SSLState) value; - - } - - } - - diff --git a/client/src/testprogram/testprogram.cc b/client/src/testprogram/testprogram.cc index c6679b7..49b1051 100644 --- a/client/src/testprogram/testprogram.cc +++ b/client/src/testprogram/testprogram.cc @@ -44,6 +44,44 @@ /*---[ Implement ]----------------------------------------------------------------------------------*/ + // Test "Session" object + static void chkSession() { + + TN3270::Session * hSession = TN3270::Session::getInstance(); + + try { + + cout + << "Version: " << hSession->getVersion() + << "\tRevision: " << hSession->getRevision() + << endl; + + hSession->connect("tn3270s://3270.df.bb:9023"); + hSession->waitForReady(30); + + cout + << "Connection state is " << toCharString(hSession->getConnectionState()) << std::endl + << "Program message is " << toCharString(hSession->getProgramMessage()) << std::endl + << "Luname is " << hSession->getLUName() << std::endl + << std::endl; + + cout + << endl << endl + << hSession->toString() + << endl << endl; + + hSession->disconnect(); + + } catch(const std::exception &e) { + + cerr << "Exception: " << e.what() << endl; + + } + + delete hSession; + + } + int main(int argc, char **argv) { const char * session = ""; // "pw3270:a"; @@ -70,6 +108,9 @@ } + chkSession(); + + /* cout << "Session: " << session << endl; TN3270::Host host{session}; @@ -92,19 +133,17 @@ // host.input("test@0another line"); - /* - host.connect(); - - if(host) { - cout << host << endl; - } - */ + //host.connect(); + //if(host) { + // cout << host << endl; + //} } catch(const std::exception &e) { cerr << std::endl << e.what() << std::endl << std::endl; } + */ return 0; diff --git a/client/valgrind.suppression b/client/valgrind.suppression index e69de29..0f577b5 100644 --- a/client/valgrind.suppression +++ b/client/valgrind.suppression @@ -0,0 +1,14 @@ +{ + libcrypt_FIPS_selftest + Memcheck:Cond + ... + fun:FIPS_selftest +} + +{ + libcrypt_FIPS_mode_set + Memcheck:Cond + ... + fun:FIPS_mode_set +} + diff --git a/common/src/include/lib3270/ipc.h b/common/src/include/lib3270/ipc.h index 98b7ed2..b44122e 100644 --- a/common/src/include/lib3270/ipc.h +++ b/common/src/include/lib3270/ipc.h @@ -69,6 +69,9 @@ #define DEFAULT_TIMEOUT 5 + TN3270_PUBLIC const char * getVersion(); + TN3270_PUBLIC const char * getRevision(); + class TN3270_PUBLIC Event { public: enum Type : uint8_t { @@ -234,64 +237,74 @@ public: - /// @brief Create a tn3270 session. - static Session * create(const char *id = nullptr); - + /// @brief Get an instance of the TN3270 session based on the supplied ID. + static Session * getInstance(const char *id = nullptr); virtual ~Session(); - // Connect/disconnect - virtual void connect(const char *url) = 0; - virtual void disconnect() = 0; + // States + virtual ProgramMessage getProgramMessage() const = 0; + virtual ConnectionState getConnectionState() const = 0; + virtual SSLState getSSLState() const = 0; - // Gets + // Contents virtual std::string toString(int baddr = 0, size_t len = -1, char lf = '\n') const = 0; virtual std::string toString(int row, int col, size_t sz, char lf = '\n') const = 0; - inline operator std::string() const { - return toString(); - } - - // Get properties. - virtual void getProperty(const char *name, int &value) const = 0; - virtual void getProperty(const char *name, std::string &value) const = 0; - virtual void getProperty(const char *name, bool &value) const = 0; + // Properties. virtual std::string getVersion() const = 0; virtual std::string getRevision() const = 0; virtual std::string getLUName() const = 0; virtual std::string getHostURL() const = 0; + virtual void setUnlockDelay(unsigned short delay = 350) = 0; + virtual unsigned short getScreenWidth() const = 0; virtual unsigned short getScreenHeight() const = 0; virtual unsigned short getScreenLength() const = 0; - virtual ProgramMessage getProgramMessage() const = 0; - inline operator ProgramMessage() const { - return getProgramMessage(); - } + /// @brief Set cursor address. + virtual void setCursor(unsigned short addr) = 0; - virtual ConnectionState getConnectionState() const = 0; - inline operator ConnectionState() const { - return getConnectionState(); - } + /// @brief Set cursor position. + virtual void setCursor(unsigned short row, unsigned short col) = 0; - inline bool operator==(ConnectionState state) const { - return this->getConnectionState() == state; - } + /// @brief Get cursor address + virtual unsigned short getCursorAddress() = 0; - virtual SSLState getSSLState() const = 0; + /// @brief Set local charset. + virtual void setCharSet(const char *charset = NULL) = 0; - inline operator SSLState() const { - return getSSLState(); - } + // Actions + + // Connect/disconnect + virtual void connect(const char *url = nullptr, bool wait = true) = 0; + virtual void disconnect() = 0; + + /// @brief Wait. + virtual void wait(unsigned short seconds) const = 0; + + /// @brief Wait until session state changes to "ready". + virtual void waitForReady(time_t timeout = DEFAULT_TIMEOUT) const = 0; + + /// @brief Wait for screen changes. + virtual void waitForChange(unsigned short seconds) const = 0; + + /// @brief Send PF. + virtual void pfkey(unsigned short value) = 0; + + /// @brief Send PA. + virtual void pakey(unsigned short value) = 0; + + /* + + // Get properties. + virtual void getProperty(const char *name, int &value) const = 0; + virtual void getProperty(const char *name, std::string &value) const = 0; + virtual void getProperty(const char *name, bool &value) const = 0; - inline bool operator==(SSLState state) const { - return this->getSSLState() == state; - } // Set properties. - virtual void setUnlockDelay(unsigned short delay = 350) = 0; - void setCharSet(const char *charset); virtual void setHostURL(const char *url) = 0; // Set contents. @@ -305,21 +318,6 @@ /// @brief Input string. virtual Session & input(const char *text, size_t length) = 0; - /// @brief Set cursor address. - virtual TN3270::Session & setCursor(unsigned short addr) = 0; - - /// @brief Set cursor position. - virtual TN3270::Session & setCursor(unsigned short row, unsigned short col) = 0; - - /// @brief Get cursor address - virtual unsigned short getCursorAddress() = 0; - - /// @brief Send PF. - virtual Session & pfkey(unsigned short value) = 0; - - /// @brief Send PA. - virtual Session & pakey(unsigned short value) = 0; - virtual Session & push(int baddr, const char *text, int length) = 0; virtual Session & push(int row, int col, const char *text, int length) = 0; @@ -344,15 +342,6 @@ /// @brief Execute action by name. virtual Session & action(const char *action_name) = 0; - /// @brief Wait. - virtual Session & wait(unsigned short seconds) = 0; - - /// @brief Wait until session state changes to "ready". - virtual void waitForReady(time_t timeout = DEFAULT_TIMEOUT) = 0; - - /// @brief Wait for screen changes. - virtual Session & waitForChange(unsigned short seconds) = 0; - /// @brief Wait for string. /// /// @return 0 if the string was found, error code if not. @@ -366,9 +355,11 @@ int compare(size_t baddr, const char* s, size_t len) const; int compare(int row, int col, const char* s, size_t len) const; + */ }; /// @brief TN3270 Host + /* class TN3270_PUBLIC Host : public std::basic_streambuf > { private: @@ -579,6 +570,7 @@ }; + */ } @@ -586,6 +578,7 @@ TN3270_PUBLIC const char * toCharString(const TN3270::ConnectionState connectionState); TN3270_PUBLIC const char * toCharString(const TN3270::Action action); + /* template inline TN3270_PUBLIC TN3270::Session & operator<<(TN3270::Session& session, const T value) { return session.push(value); @@ -605,6 +598,7 @@ stream << host.toString(); return stream; } + */ #endif -- libgit2 0.21.2