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 | 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 | ... | ... |