Commit dcf0fc2cd7f4b1d0d22491a1b288bca594973ac7

Authored by Perry Werneck
1 parent 0d0564a2
Exists in master and in 1 other branch develop

Fixing IPC response on empty URL.

client/src/core/windows/pop.cc
... ... @@ -44,11 +44,31 @@
44 44  
45 45 namespace TN3270 {
46 46  
  47 + class InvalidFormatException : public std::exception {
  48 + private:
  49 + string message;
  50 +
  51 + public:
  52 + InvalidFormatException(const IPC::Request::Type received, const IPC::Request::Type expected) {
  53 +
  54 + message = "Invalid format on IPC package, expecting \'";
  55 + message += (char) expected;
  56 + message += "\' but received \'";
  57 + message += (char) received;
  58 + message += "\'";
  59 +
  60 + }
  61 +
  62 + const char * what() const noexcept override {
  63 + return message.c_str();
  64 + }
  65 + };
  66 +
47 67 IPC::Request & IPC::Request::pop(std::string &value) {
48 68 DataBlock * block = getNextBlock();
49 69  
50 70 if(block->type != IPC::Request::String)
51   - throw std::runtime_error("Invalid format");
  71 + throw InvalidFormatException(block->type, IPC::Request::String);
52 72  
53 73 const char *ptr = (const char *) (block+1);
54 74  
... ... @@ -80,7 +100,7 @@
80 100 break;
81 101  
82 102 default:
83   - throw std::runtime_error("Invalid format");
  103 + throw InvalidFormatException(block->type, IPC::Request::Int16);
84 104 }
85 105  
86 106 return *this;
... ... @@ -107,7 +127,7 @@
107 127 break;
108 128  
109 129 default:
110   - throw std::runtime_error("Invalid format");
  130 + throw InvalidFormatException(block->type, IPC::Request::Uint16);
111 131 }
112 132  
113 133 return *this;
... ... @@ -139,7 +159,7 @@
139 159 break;
140 160  
141 161 default:
142   - throw std::runtime_error("Invalid format");
  162 + throw InvalidFormatException(block->type, IPC::Request::Boolean);
143 163 }
144 164  
145 165 return *this;
... ...
client/src/core/windows/request.cc
... ... @@ -37,6 +37,7 @@
37 37 */
38 38  
39 39 #include <ipc-client-internals.h>
  40 + #include <lib3270/trace.h>
40 41  
41 42 using std::string;
42 43  
... ... @@ -46,6 +47,51 @@
46 47  
47 48 #define PIPE_BUFFER_LENGTH 8192
48 49  
  50 +#ifdef DEBUG
  51 +
  52 + // From lib3270_trace_data
  53 + static void trace_data(const char *msg, const unsigned char *data, size_t datalen)
  54 +{
  55 + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777
  56 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
  57 + // xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx . . . . . . . . . . . . . . . .
  58 +
  59 + size_t ix;
  60 + char buffer[80];
  61 + char hexvalue[3];
  62 +
  63 + memset(buffer,0,sizeof(buffer));
  64 +
  65 + std::cout << msg << "(" << datalen << " bytes)" << std::endl;
  66 +
  67 + for(ix = 0; ix < datalen; ix++)
  68 + {
  69 + size_t col = (ix%15);
  70 +
  71 + if(col == 0)
  72 + {
  73 + if(ix) {
  74 + std::cout << "\t" << buffer << std::endl;
  75 + }
  76 +
  77 + memset(buffer,' ',79);
  78 + buffer[79] = 0;
  79 + }
  80 +
  81 + snprintf(hexvalue,3,"%02x",data[ix]);
  82 + memcpy(buffer+(col*3),hexvalue,2);
  83 +
  84 + if(data[ix] > ' ')
  85 + buffer[48 + (col*2)] = data[ix];
  86 +
  87 + }
  88 +
  89 + std::cout << "\t" << buffer << std::endl;
  90 +
  91 +}
  92 +
  93 +#endif // DEBUG
  94 +
49 95 IPC::Request::Request(HANDLE hPipe, const char *name, uint16_t type) {
50 96  
51 97 this->hPipe = hPipe;
... ... @@ -114,7 +160,7 @@
114 160 IPC::Request & IPC::Request::call() {
115 161  
116 162 #ifdef DEBUG
117   - // lib3270_trace_data(NULL,"Request block",(const char *) this->out.block, this->out.used);
  163 + // trace_data("Request block",(const unsigned char *) this->out.block, this->out.used);
118 164 #endif // DEBUG
119 165  
120 166 debug("Sending request with ", *this->outvalues, " elements");
... ... @@ -137,8 +183,19 @@
137 183  
138 184 debug("Received response \"", in.block, "\" with ", in.used, " bytes");
139 185  
  186 + //
  187 + // Heaer format:
  188 + //
  189 + // STRING Response name
  190 + // uint16_t Return code
  191 + // uint16_t Arguments
  192 + //
  193 + // Data block:
  194 + //
  195 + //
  196 +
140 197 #ifdef DEBUG
141   - // lib3270_trace_data(NULL,"Response block",(const char *) this->in.block, this->in.used);
  198 + trace_data("Response block",(const unsigned char *) this->in.block, this->in.used);
142 199 #endif // DEBUG
143 200  
144 201 // Extract response name
... ...
client/src/include/lib3270/ipc/request.h
... ... @@ -58,12 +58,8 @@
58 58  
59 59 /// @brief PW3270 IPC Request/Response.
60 60 class TN3270_PUBLIC Request {
61   - private:
62   -
  61 + public:
63 62 #ifdef _WIN32
64   - /// @brief Pipe Handle.
65   - HANDLE hPipe;
66   -
67 63 /// @brief IPC Data type.
68 64 enum Type : uint8_t {
69 65 String = 's',
... ... @@ -77,6 +73,13 @@
77 73 Int64 = 'x',
78 74 Uint64 = 't'
79 75 };
  76 +#endif // _WIN32
  77 +
  78 + private:
  79 +
  80 +#ifdef _WIN32
  81 + /// @brief Pipe Handle.
  82 + HANDLE hPipe;
80 83  
81 84 struct {
82 85 DWORD length; ///< @brief Length of input buffer.
... ...
client/src/testprogram/testprogram.cc
... ... @@ -99,12 +99,19 @@
99 99 */
100 100  
101 101 // Test Attributes
102   - static void testAttributes(const char *session, const char *url) {
  102 + static void testAttributes(const char *session, const char *name) {
103 103  
104 104 TN3270::Host host{session};
105 105  
  106 + name="url";
  107 +
  108 + cout << endl << endl;
106 109 for(auto attribute : host.getAttributes()) {
107 110  
  111 + if(name && *name && strcasecmp(name,"all") && strcasecmp(attribute.getName(),name)) {
  112 + continue;
  113 + }
  114 +
108 115 cout << attribute.getName() << ":\t";
109 116  
110 117 try {
... ... @@ -113,13 +120,17 @@
113 120  
114 121 } catch(const std::exception &e) {
115 122  
116   - cout << e.what();
  123 + cout << "Exception(" << e.what() << ")";
117 124 }
118 125  
119 126 cout << endl;
120 127  
  128 + Sleep(100);
  129 +
121 130 }
122 131  
  132 + cout << endl << endl;
  133 +
123 134 }
124 135  
125 136 // Performance test.
... ... @@ -237,17 +248,18 @@
237 248 #if ! defined(_MSC_VER)
238 249  
239 250 static struct option options[] = {
240   - { "session", required_argument, 0, 's' },
241   - { "url", required_argument, 0, 'U' },
242   - { "perftest", no_argument, 0, 'P' },
243   - { "info", no_argument, 0, 'I' },
  251 + { "session", required_argument, 0, 's' },
  252 + { "url", required_argument, 0, 'U' },
  253 + { "perftest", no_argument, 0, 'P' },
  254 + { "attribute", optional_argument, 0, 'A' },
  255 + { "info", no_argument, 0, 'I' },
244 256 { 0, 0, 0, 0}
245 257  
246 258 };
247 259  
248 260 int long_index =0;
249 261 int opt;
250   - while((opt = getopt_long(argc, argv, "s:", options, &long_index )) != -1) {
  262 + while((opt = getopt_long(argc, argv, "s:A", options, &long_index )) != -1) {
251 263  
252 264 switch(opt) {
253 265 case 's':
... ... @@ -255,6 +267,10 @@
255 267 cout << "Session: " << session << endl;
256 268 break;
257 269  
  270 + case 'A':
  271 + testAttributes(session,optarg);
  272 + break;
  273 +
258 274 case 'U':
259 275 url = optarg;
260 276 cout << "URL: " << session << endl;
... ...
server/src/core/getproperties.c
... ... @@ -127,6 +127,7 @@ GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GEr
127 127 if(strprop[ix].get && !g_ascii_strcasecmp(strprop[ix].name, property_name)) {
128 128  
129 129 // Found it!
  130 + errno = 0;
130 131 const char * value = strprop[ix].get(hSession);
131 132  
132 133 if(value) {
... ... @@ -134,9 +135,14 @@ GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GEr
134 135 return g_variant_new_string(value);
135 136 }
136 137  
137   - // Erro!
138   - ipc3270_set_error(object,errno,error);
139   - return NULL;
  138 + debug("%s=%s",property_name,"NULL");
  139 +
  140 + if(errno) {
  141 + ipc3270_set_error(object,errno,error);
  142 + return NULL;
  143 + }
  144 +
  145 + return g_variant_new_string("");
140 146  
141 147 }
142 148  
... ...
server/src/core/windows/inout.c
... ... @@ -59,7 +59,7 @@ unsigned char * ipc3270_pack_error(const GError *error, size_t * szPacket) {
59 59 txtptr += strlen((char *) txtptr) + 1;
60 60  
61 61 // Add RC
62   - *((guint16 *) txtptr) = (guint16) error->code;
  62 + *((guint16 *) txtptr) = (guint16) (error->code ? error->code : -1);
63 63 txtptr += sizeof(guint16);
64 64  
65 65 // Add message
... ...