Skip to content

Commit df7bfdf

Browse files
cursoragentlovasoa
andcommitted
Checkpoint before follow-up message
Co-authored-by: contact <[email protected]>
1 parent 6307c50 commit df7bfdf

File tree

1 file changed

+49
-26
lines changed
  • sqlx-core/src/mssql/connection

1 file changed

+49
-26
lines changed

sqlx-core/src/mssql/connection/ssrp.rs

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
11
use crate::error::Error;
2+
use encoding_rs::WINDOWS_1252;
23
use sqlx_rt::{timeout, UdpSocket};
3-
use std::borrow::Cow;
4-
use std::collections::HashMap;
54
use std::time::Duration;
65

76
const SSRP_PORT: u16 = 1434;
87
const CLNT_UCAST_INST: u8 = 0x04;
98
const SVR_RESP: u8 = 0x05;
109
const SSRP_TIMEOUT: Duration = Duration::from_secs(1);
1110

11+
struct InstanceInfo<'a> {
12+
server_name: Option<&'a str>,
13+
instance_name: Option<&'a str>,
14+
is_clustered: Option<&'a str>,
15+
version: Option<&'a str>,
16+
tcp_port: Option<&'a str>,
17+
}
18+
1219
pub(crate) async fn resolve_instance_port(server: &str, instance: &str) -> Result<u16, Error> {
1320
log::debug!(
1421
"resolving SQL Server instance port for '{}' on server '{}'",
@@ -88,37 +95,27 @@ pub(crate) async fn resolve_instance_port(server: &str, instance: &str) -> Resul
8895
));
8996
}
9097

91-
let response_data = String::from_utf8_lossy(&buffer[3..(3 + response_size)]);
98+
let response_bytes = &buffer[3..(3 + response_size)];
99+
let (response_str, _encoding_used, had_errors) = WINDOWS_1252.decode(response_bytes);
100+
101+
if had_errors {
102+
log::debug!("SSRP response had MBCS decoding errors, continuing anyway");
103+
}
92104

93-
log::debug!("SSRP response data: {}", response_data);
105+
log::debug!("SSRP response data: {}", response_str);
94106

95-
parse_ssrp_response(&response_data, instance)
107+
parse_ssrp_response(&response_str, instance)
96108
}
97109

98-
fn parse_ssrp_response(data: &Cow<'_, str>, instance_name: &str) -> Result<u16, Error> {
99-
let instances: Vec<&str> = data.split(";;").collect();
100-
log::debug!(
101-
"parsing SSRP response, found {} instance entries",
102-
instances.len()
103-
);
104-
105-
for instance_data in instances {
110+
fn parse_ssrp_response(data: &str, instance_name: &str) -> Result<u16, Error> {
111+
for instance_data in data.split(";;") {
106112
if instance_data.is_empty() {
107113
continue;
108114
}
109115

110-
let tokens: Vec<&str> = instance_data.split(';').collect();
111-
let mut properties: HashMap<&str, &str> = HashMap::new();
112-
113-
let mut i = 0;
114-
while i + 1 < tokens.len() {
115-
let key = tokens[i];
116-
let value = tokens[i + 1];
117-
properties.insert(key, value);
118-
i += 2;
119-
}
120-
121-
if let Some(name) = properties.get("InstanceName") {
116+
let info = parse_instance_info(instance_data);
117+
118+
if let Some(name) = info.instance_name {
122119
log::debug!("found instance '{}' in SSRP response", name);
123120

124121
if name.eq_ignore_ascii_case(instance_name) {
@@ -128,7 +125,7 @@ fn parse_ssrp_response(data: &Cow<'_, str>, instance_name: &str) -> Result<u16,
128125
instance_name
129126
);
130127

131-
if let Some(tcp_port_str) = properties.get("tcp") {
128+
if let Some(tcp_port_str) = info.tcp_port {
132129
let port = tcp_port_str.parse::<u16>().map_err(|e| {
133130
err_protocol!(
134131
"invalid TCP port '{}' in SSRP response: {}",
@@ -160,6 +157,32 @@ fn parse_ssrp_response(data: &Cow<'_, str>, instance_name: &str) -> Result<u16,
160157
))
161158
}
162159

160+
fn parse_instance_info<'a>(data: &'a str) -> InstanceInfo<'a> {
161+
let mut info = InstanceInfo {
162+
server_name: None,
163+
instance_name: None,
164+
is_clustered: None,
165+
version: None,
166+
tcp_port: None,
167+
};
168+
169+
let mut tokens = data.split(';');
170+
while let Some(key) = tokens.next() {
171+
let value = tokens.next();
172+
173+
match key {
174+
"ServerName" => info.server_name = value,
175+
"InstanceName" => info.instance_name = value,
176+
"IsClustered" => info.is_clustered = value,
177+
"Version" => info.version = value,
178+
"tcp" => info.tcp_port = value,
179+
_ => {}
180+
}
181+
}
182+
183+
info
184+
}
185+
163186
#[cfg(test)]
164187
mod tests {
165188
use super::*;

0 commit comments

Comments
 (0)