| 276 | } |
| 277 | |
| 278 | static void ParseResponse(Controller* cntl, butil::IOBuf& buf, |
| 279 | google::protobuf::Message* res) { |
| 280 | if (res == NULL) { |
| 281 | // silently ignore response. |
| 282 | return; |
| 283 | } |
| 284 | const std::string msg_name = butil::EnsureString(res->GetDescriptor()->full_name()); |
| 285 | mcpack2pb::MessageHandler handler = mcpack2pb::find_message_handler(msg_name); |
| 286 | if (handler.parse_body == NULL) { |
| 287 | return cntl->SetFailed(ERESPONSE, "Fail to find parser of %s", |
| 288 | msg_name.c_str()); |
| 289 | } |
| 290 | butil::IOBufAsZeroCopyInputStream zc_stream(buf); |
| 291 | mcpack2pb::InputStream stream(&zc_stream); |
| 292 | if (!::mcpack2pb::unbox(&stream)) { |
| 293 | cntl->SetFailed(ERESPONSE, "Response is not a compack/mcpack2 object"); |
| 294 | return; |
| 295 | } |
| 296 | mcpack2pb::ObjectIterator it1(&stream, buf.size() - stream.popped_bytes()); |
| 297 | bool found_content = false; |
| 298 | for (; it1 != NULL; ++it1) { |
| 299 | if (it1->name == "content") { |
| 300 | found_content = true; |
| 301 | break; |
| 302 | } |
| 303 | } |
| 304 | if (!found_content) { |
| 305 | cntl->SetFailed(ERESPONSE, "Fail to find response.content"); |
| 306 | return; |
| 307 | } |
| 308 | if (it1->value.type() != mcpack2pb::FIELD_ARRAY) { |
| 309 | cntl->SetFailed(ERESPONSE, "Expect response.content to be array," |
| 310 | " actually %s", mcpack2pb::type2str(it1->value.type())); |
| 311 | return; |
| 312 | } |
| 313 | mcpack2pb::ArrayIterator it2(it1->value); |
| 314 | if (it2 == NULL) { |
| 315 | cntl->SetFailed("Fail to parse response.content as array"); |
| 316 | return; |
| 317 | } |
| 318 | bool has_result_params = false; |
| 319 | size_t user_res_offset = 0; |
| 320 | size_t user_res_size = 0; |
| 321 | const char* response_name = "result_params"; |
| 322 | for (mcpack2pb::ObjectIterator it3(*it2); it3 != NULL; ++it3) { |
| 323 | if (it3->name == "error") { |
| 324 | if (it3->value.type() != mcpack2pb::FIELD_OBJECT) { |
| 325 | cntl->SetFailed(ERESPONSE, "Expect response.content[0].error" |
| 326 | " to be object, actually %s", |
| 327 | mcpack2pb::type2str(it3->value.type())); |
| 328 | return; |
| 329 | } |
| 330 | int32_t code = 0; |
| 331 | std::string msg; |
| 332 | for (mcpack2pb::ObjectIterator it4(it3->value); it4 != NULL; ++it4) { |
| 333 | if (it4->name == "code") { |
| 334 | if (!mcpack2pb::is_primitive(it4->value.type()) || |
| 335 | !mcpack2pb::is_integral( |
no test coverage detected