| 82 | const size_t PROTO_DUMMY_LEN = 4; |
| 83 | |
| 84 | ParseResult InputMessenger::CutInputMessage( |
| 85 | Socket* m, size_t* index, bool read_eof) { |
| 86 | const int preferred = m->preferred_index(); |
| 87 | const int max_index = (int)_max_index.load(butil::memory_order_acquire); |
| 88 | // Try preferred handler first. The preferred_index is set on last |
| 89 | // selection or by client. |
| 90 | if (preferred >= 0 && preferred <= max_index |
| 91 | && _handlers[preferred].parse != NULL) { |
| 92 | int cur_index = preferred; |
| 93 | do { |
| 94 | ParseResult result = |
| 95 | _handlers[cur_index].parse(&m->_read_buf, m, read_eof, _handlers[cur_index].arg); |
| 96 | if (result.is_ok() || |
| 97 | result.error() == PARSE_ERROR_NOT_ENOUGH_DATA) { |
| 98 | m->set_preferred_index(cur_index); |
| 99 | *index = cur_index; |
| 100 | return result; |
| 101 | } else if (result.error() != PARSE_ERROR_TRY_OTHERS) { |
| 102 | // Critical error, return directly. |
| 103 | LOG_IF(ERROR, result.error() == PARSE_ERROR_TOO_BIG_DATA) |
| 104 | << "A message from " << m->remote_side() |
| 105 | << "(protocol=" << _handlers[cur_index].name |
| 106 | << ") is bigger than " << FLAGS_max_body_size |
| 107 | << " bytes, the connection will be closed." |
| 108 | " Set max_body_size to allow bigger messages"; |
| 109 | return result; |
| 110 | } else { |
| 111 | if (m->_read_buf.size() >= 4) { |
| 112 | // The length of `data' must be PROTO_DUMMY_LEN + 1 to store extra ending char '\0' |
| 113 | char data[PROTO_DUMMY_LEN + 1]; |
| 114 | m->_read_buf.copy_to_cstr(data, PROTO_DUMMY_LEN); |
| 115 | if (strncmp(data, "RDMA", PROTO_DUMMY_LEN) == 0) { |
| 116 | // To avoid timeout when client uses RDMA but server uses TCP |
| 117 | return MakeParseError(PARSE_ERROR_TRY_OTHERS); |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | if (m->CreatedByConnect()) { |
| 123 | if((ProtocolType)cur_index == PROTOCOL_BAIDU_STD && cur_index == preferred) { |
| 124 | // baidu_std may fall to streaming_rpc. |
| 125 | cur_index = (int)PROTOCOL_STREAMING_RPC; |
| 126 | continue; |
| 127 | } else if((ProtocolType)cur_index == PROTOCOL_STREAMING_RPC && cur_index == preferred) { |
| 128 | // streaming_rpc may fall to baidu_std. |
| 129 | cur_index = (int)PROTOCOL_BAIDU_STD; |
| 130 | continue; |
| 131 | } else { |
| 132 | // The protocol is fixed at client-side, no need to try others. |
| 133 | LOG(ERROR) << "Fail to parse response from " << m->remote_side() |
| 134 | << " by " << _handlers[preferred].name |
| 135 | << " at client-side"; |
| 136 | return MakeParseError(PARSE_ERROR_ABSOLUTELY_WRONG); |
| 137 | } |
| 138 | } else { |
| 139 | // Try other protocols. |
| 140 | break; |
| 141 | } |
nothing calls this directly
no test coverage detected