opensrv_clickhouse/protocols/
protocol_hello.rs

1// Copyright 2021 Datafuse Labs.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::io::Read;
16
17use crate::binary::Encoder;
18use crate::binary::ReadEx;
19use crate::error_codes;
20use crate::errors::Error;
21use crate::errors::Result;
22use crate::errors::ServerError;
23use crate::protocols::*;
24
25#[derive(Default, Debug, Clone)]
26pub struct HelloRequest {
27    pub client_name: Vec<u8>,
28    pub client_version_major: u64,
29    pub client_version_minor: u64,
30    pub client_revision: u64,
31    pub default_database: Vec<u8>,
32
33    pub user: String,
34    pub password: Vec<u8>,
35
36    // Not set currently
37    pub client_version_patch: u64,
38}
39
40impl HelloRequest {
41    pub fn read_from<R: Read>(reader: &mut R) -> Result<HelloRequest> {
42        let request = HelloRequest {
43            client_name: reader.read_len_encode_bytes()?,
44            client_version_major: reader.read_uvarint()?,
45            client_version_minor: reader.read_uvarint()?,
46            client_revision: reader.read_uvarint()?,
47            default_database: reader.read_len_encode_bytes()?,
48            user: reader.read_string()?,
49            password: reader.read_len_encode_bytes()?,
50
51            client_version_patch: 0,
52        };
53
54        if request.user.is_empty() {
55            return Err(Error::Server(ServerError {
56                name: "UNEXPECTED_PACKET_FROM_CLIENT".to_string(),
57                code: error_codes::UNEXPECTED_PACKET_FROM_CLIENT,
58                message: "Unexpected packet from client (no user in Hello package)".to_string(),
59                stack_trace: "".to_string(),
60            }));
61        }
62
63        Ok(request)
64    }
65}
66
67pub struct HelloResponse {
68    pub dbms_name: String,
69    pub dbms_version_major: u64,
70    pub dbms_version_minor: u64,
71    pub dbms_tcp_protocol_version: u64,
72    pub timezone: String,
73    pub server_display_name: String,
74    pub dbms_version_patch: u64,
75}
76
77impl HelloResponse {
78    pub fn encode(&self, encoder: &mut Encoder, client_revision: u64) -> Result<()> {
79        encoder.uvarint(SERVER_HELLO);
80
81        encoder.string(&self.dbms_name);
82        encoder.uvarint(self.dbms_version_major);
83        encoder.uvarint(self.dbms_version_minor);
84        encoder.uvarint(self.dbms_tcp_protocol_version);
85
86        if client_revision >= DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE {
87            encoder.string(&self.timezone);
88        }
89
90        if client_revision >= DBMS_MIN_REVISION_WITH_SERVER_DISPLAY_NAME {
91            encoder.string(&self.server_display_name);
92        }
93
94        if client_revision >= DBMS_MIN_REVISION_WITH_VERSION_PATCH {
95            encoder.uvarint(self.dbms_version_patch);
96        }
97
98        Ok(())
99    }
100}