Commit dcf0fc2cd7f4b1d0d22491a1b288bca594973ac7
1 parent
0d0564a2
Exists in
master
and in
1 other branch
Fixing IPC response on empty URL.
Showing
6 changed files
with
124 additions
and
22 deletions
Show diff stats
client/src/core/windows/pop.cc
@@ -44,11 +44,31 @@ | @@ -44,11 +44,31 @@ | ||
44 | 44 | ||
45 | namespace TN3270 { | 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 | IPC::Request & IPC::Request::pop(std::string &value) { | 67 | IPC::Request & IPC::Request::pop(std::string &value) { |
48 | DataBlock * block = getNextBlock(); | 68 | DataBlock * block = getNextBlock(); |
49 | 69 | ||
50 | if(block->type != IPC::Request::String) | 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 | const char *ptr = (const char *) (block+1); | 73 | const char *ptr = (const char *) (block+1); |
54 | 74 | ||
@@ -80,7 +100,7 @@ | @@ -80,7 +100,7 @@ | ||
80 | break; | 100 | break; |
81 | 101 | ||
82 | default: | 102 | default: |
83 | - throw std::runtime_error("Invalid format"); | 103 | + throw InvalidFormatException(block->type, IPC::Request::Int16); |
84 | } | 104 | } |
85 | 105 | ||
86 | return *this; | 106 | return *this; |
@@ -107,7 +127,7 @@ | @@ -107,7 +127,7 @@ | ||
107 | break; | 127 | break; |
108 | 128 | ||
109 | default: | 129 | default: |
110 | - throw std::runtime_error("Invalid format"); | 130 | + throw InvalidFormatException(block->type, IPC::Request::Uint16); |
111 | } | 131 | } |
112 | 132 | ||
113 | return *this; | 133 | return *this; |
@@ -139,7 +159,7 @@ | @@ -139,7 +159,7 @@ | ||
139 | break; | 159 | break; |
140 | 160 | ||
141 | default: | 161 | default: |
142 | - throw std::runtime_error("Invalid format"); | 162 | + throw InvalidFormatException(block->type, IPC::Request::Boolean); |
143 | } | 163 | } |
144 | 164 | ||
145 | return *this; | 165 | return *this; |
client/src/core/windows/request.cc
@@ -37,6 +37,7 @@ | @@ -37,6 +37,7 @@ | ||
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <ipc-client-internals.h> | 39 | #include <ipc-client-internals.h> |
40 | + #include <lib3270/trace.h> | ||
40 | 41 | ||
41 | using std::string; | 42 | using std::string; |
42 | 43 | ||
@@ -46,6 +47,51 @@ | @@ -46,6 +47,51 @@ | ||
46 | 47 | ||
47 | #define PIPE_BUFFER_LENGTH 8192 | 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 | IPC::Request::Request(HANDLE hPipe, const char *name, uint16_t type) { | 95 | IPC::Request::Request(HANDLE hPipe, const char *name, uint16_t type) { |
50 | 96 | ||
51 | this->hPipe = hPipe; | 97 | this->hPipe = hPipe; |
@@ -114,7 +160,7 @@ | @@ -114,7 +160,7 @@ | ||
114 | IPC::Request & IPC::Request::call() { | 160 | IPC::Request & IPC::Request::call() { |
115 | 161 | ||
116 | #ifdef DEBUG | 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 | #endif // DEBUG | 164 | #endif // DEBUG |
119 | 165 | ||
120 | debug("Sending request with ", *this->outvalues, " elements"); | 166 | debug("Sending request with ", *this->outvalues, " elements"); |
@@ -137,8 +183,19 @@ | @@ -137,8 +183,19 @@ | ||
137 | 183 | ||
138 | debug("Received response \"", in.block, "\" with ", in.used, " bytes"); | 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 | #ifdef DEBUG | 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 | #endif // DEBUG | 199 | #endif // DEBUG |
143 | 200 | ||
144 | // Extract response name | 201 | // Extract response name |
client/src/include/lib3270/ipc/request.h
@@ -58,12 +58,8 @@ | @@ -58,12 +58,8 @@ | ||
58 | 58 | ||
59 | /// @brief PW3270 IPC Request/Response. | 59 | /// @brief PW3270 IPC Request/Response. |
60 | class TN3270_PUBLIC Request { | 60 | class TN3270_PUBLIC Request { |
61 | - private: | ||
62 | - | 61 | + public: |
63 | #ifdef _WIN32 | 62 | #ifdef _WIN32 |
64 | - /// @brief Pipe Handle. | ||
65 | - HANDLE hPipe; | ||
66 | - | ||
67 | /// @brief IPC Data type. | 63 | /// @brief IPC Data type. |
68 | enum Type : uint8_t { | 64 | enum Type : uint8_t { |
69 | String = 's', | 65 | String = 's', |
@@ -77,6 +73,13 @@ | @@ -77,6 +73,13 @@ | ||
77 | Int64 = 'x', | 73 | Int64 = 'x', |
78 | Uint64 = 't' | 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 | struct { | 84 | struct { |
82 | DWORD length; ///< @brief Length of input buffer. | 85 | DWORD length; ///< @brief Length of input buffer. |
client/src/testprogram/testprogram.cc
@@ -99,12 +99,19 @@ | @@ -99,12 +99,19 @@ | ||
99 | */ | 99 | */ |
100 | 100 | ||
101 | // Test Attributes | 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 | TN3270::Host host{session}; | 104 | TN3270::Host host{session}; |
105 | 105 | ||
106 | + name="url"; | ||
107 | + | ||
108 | + cout << endl << endl; | ||
106 | for(auto attribute : host.getAttributes()) { | 109 | for(auto attribute : host.getAttributes()) { |
107 | 110 | ||
111 | + if(name && *name && strcasecmp(name,"all") && strcasecmp(attribute.getName(),name)) { | ||
112 | + continue; | ||
113 | + } | ||
114 | + | ||
108 | cout << attribute.getName() << ":\t"; | 115 | cout << attribute.getName() << ":\t"; |
109 | 116 | ||
110 | try { | 117 | try { |
@@ -113,13 +120,17 @@ | @@ -113,13 +120,17 @@ | ||
113 | 120 | ||
114 | } catch(const std::exception &e) { | 121 | } catch(const std::exception &e) { |
115 | 122 | ||
116 | - cout << e.what(); | 123 | + cout << "Exception(" << e.what() << ")"; |
117 | } | 124 | } |
118 | 125 | ||
119 | cout << endl; | 126 | cout << endl; |
120 | 127 | ||
128 | + Sleep(100); | ||
129 | + | ||
121 | } | 130 | } |
122 | 131 | ||
132 | + cout << endl << endl; | ||
133 | + | ||
123 | } | 134 | } |
124 | 135 | ||
125 | // Performance test. | 136 | // Performance test. |
@@ -237,17 +248,18 @@ | @@ -237,17 +248,18 @@ | ||
237 | #if ! defined(_MSC_VER) | 248 | #if ! defined(_MSC_VER) |
238 | 249 | ||
239 | static struct option options[] = { | 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 | { 0, 0, 0, 0} | 256 | { 0, 0, 0, 0} |
245 | 257 | ||
246 | }; | 258 | }; |
247 | 259 | ||
248 | int long_index =0; | 260 | int long_index =0; |
249 | int opt; | 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 | switch(opt) { | 264 | switch(opt) { |
253 | case 's': | 265 | case 's': |
@@ -255,6 +267,10 @@ | @@ -255,6 +267,10 @@ | ||
255 | cout << "Session: " << session << endl; | 267 | cout << "Session: " << session << endl; |
256 | break; | 268 | break; |
257 | 269 | ||
270 | + case 'A': | ||
271 | + testAttributes(session,optarg); | ||
272 | + break; | ||
273 | + | ||
258 | case 'U': | 274 | case 'U': |
259 | url = optarg; | 275 | url = optarg; |
260 | cout << "URL: " << session << endl; | 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,6 +127,7 @@ GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GEr | ||
127 | if(strprop[ix].get && !g_ascii_strcasecmp(strprop[ix].name, property_name)) { | 127 | if(strprop[ix].get && !g_ascii_strcasecmp(strprop[ix].name, property_name)) { |
128 | 128 | ||
129 | // Found it! | 129 | // Found it! |
130 | + errno = 0; | ||
130 | const char * value = strprop[ix].get(hSession); | 131 | const char * value = strprop[ix].get(hSession); |
131 | 132 | ||
132 | if(value) { | 133 | if(value) { |
@@ -134,9 +135,14 @@ GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GEr | @@ -134,9 +135,14 @@ GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GEr | ||
134 | return g_variant_new_string(value); | 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,7 +59,7 @@ unsigned char * ipc3270_pack_error(const GError *error, size_t * szPacket) { | ||
59 | txtptr += strlen((char *) txtptr) + 1; | 59 | txtptr += strlen((char *) txtptr) + 1; |
60 | 60 | ||
61 | // Add RC | 61 | // Add RC |
62 | - *((guint16 *) txtptr) = (guint16) error->code; | 62 | + *((guint16 *) txtptr) = (guint16) (error->code ? error->code : -1); |
63 | txtptr += sizeof(guint16); | 63 | txtptr += sizeof(guint16); |
64 | 64 | ||
65 | // Add message | 65 | // Add message |