Skip to content

Commit e4b2f54

Browse files
committed
Merge branch 'master' into upgrade_futures_and_tokio
2 parents 8a14cec + f5c4e84 commit e4b2f54

File tree

11 files changed

+511
-182
lines changed

11 files changed

+511
-182
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,22 @@ categories = ["api-bindings", "network-programming", "database-implementations"]
1717

1818
license = "MIT/Apache-2.0"
1919

20+
[features]
21+
default = ["tls"]
22+
tls = ["rustls"]
23+
2024
[badges]
2125
azure-devops = { project = "jonhoo/jonhoo", pipeline = "msql-srv", build = "27" }
2226
codecov = { repository = "jonhoo/msql-srv", branch = "master", service = "github" }
2327
maintenance = { status = "experimental" }
2428

2529
[dependencies]
26-
nom = "5"
30+
nom = "7"
2731
mysql_common = { version = "0.28.0", features = ["chrono"] }
2832
byteorder = "1"
2933
chrono = "0.4"
3034
time = "0.2.25"
35+
rustls = {version = "0.20.0", optional=true}
3136

3237
[dev-dependencies]
3338
postgres = "0.19.1"
@@ -36,3 +41,4 @@ mysql_async = "0.29.0"
3641
slab = "0.4.2"
3742
tokio = { version = "1.15.0", features = ["full"] }
3843
futures = "0.3.0"
44+
rcgen = "0.8.14"

examples/psql_as_mysql.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl From<postgres::Error> for Error {
129129
}
130130
}
131131

132-
impl<W: io::Write> MysqlShim<W> for Postgres {
132+
impl<W: io::Read + io::Write> MysqlShim<W> for Postgres {
133133
type Error = Error;
134134

135135
fn on_prepare(&mut self, query: &str, info: StatementMetaWriter<W>) -> Result<(), Self::Error> {
@@ -141,7 +141,7 @@ impl<W: io::Write> MysqlShim<W> for Postgres {
141141
use std::mem;
142142
let params: Vec<_> = stmt
143143
.params()
144-
.into_iter()
144+
.iter()
145145
.map(|t| {
146146
let ct = p2mt(t);
147147
Column {
@@ -154,7 +154,7 @@ impl<W: io::Write> MysqlShim<W> for Postgres {
154154
.collect();
155155
let columns: Vec<_> = stmt
156156
.columns()
157-
.into_iter()
157+
.iter()
158158
.map(|c| {
159159
let t = c.type_();
160160
let ct = p2mt(t);
@@ -264,16 +264,16 @@ impl Drop for Postgres {
264264
}
265265

266266
/// Take a set of rows from PostgreSQL and re-encode them as MySQL rows
267-
fn answer_rows<W: io::Write>(
267+
fn answer_rows<W: io::Read + io::Write>(
268268
results: QueryResultWriter<W>,
269269
rows: Result<Vec<postgres::Row>, postgres::Error>,
270270
) -> Result<(), Error> {
271271
match rows {
272272
Ok(rows) => {
273-
if let Some(first) = rows.iter().next() {
273+
if let Some(first) = rows.get(0) {
274274
let cols: Vec<_> = first
275275
.columns()
276-
.into_iter()
276+
.iter()
277277
.map(|c| {
278278
let t = c.type_();
279279
let ct = p2mt(t);

examples/serve_one.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::net;
1414
use std::thread;
1515

1616
struct Backend;
17-
impl<W: io::Write> MysqlShim<W> for Backend {
17+
impl<W: io::Read + io::Write> MysqlShim<W> for Backend {
1818
type Error = io::Error;
1919

2020
fn on_prepare(&mut self, _: &str, info: StatementMetaWriter<W>) -> io::Result<()> {

src/commands.rs

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ use crate::myc::constants::{CapabilityFlags, Command as CommandByte};
33
#[derive(Debug)]
44
#[allow(dead_code)] // The fields here are read, but only in tests. This keeps clippy quiet.
55
pub struct ClientHandshake<'a> {
6-
capabilities: CapabilityFlags,
6+
pub capabilities: CapabilityFlags,
77
maxps: u32,
88
collation: u16,
9-
username: &'a [u8],
9+
username: Option<&'a [u8]>,
1010
}
1111

12-
pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
12+
pub fn client_handshake(i: &[u8], after_tls: bool) -> nom::IResult<&[u8], ClientHandshake<'_>> {
1313
// mysql handshake protocol documentation
1414
// https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_packets_protocol_handshake_response.html
1515

@@ -21,16 +21,24 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
2121
let (i, cap2) = nom::number::complete::le_u16(i)?;
2222
let cap = (cap2 as u32) << 16 | cap as u32;
2323

24+
let capabilities = CapabilityFlags::from_bits_truncate(cap);
25+
2426
let (i, maxps) = nom::number::complete::le_u32(i)?;
2527
let (i, collation) = nom::bytes::complete::take(1u8)(i)?;
2628
let (i, _) = nom::bytes::complete::take(23u8)(i)?;
27-
let (i, username) = nom::bytes::complete::take_until(&b"\0"[..])(i)?;
28-
let (i, _) = nom::bytes::complete::tag(b"\0")(i)?;
29+
30+
let (i, username) = if after_tls || !capabilities.contains(CapabilityFlags::CLIENT_SSL) {
31+
let (i, user) = nom::bytes::complete::take_until(&b"\0"[..])(i)?;
32+
let (i, _) = nom::bytes::complete::tag(b"\0")(i)?;
33+
(i, Some(user))
34+
} else {
35+
(i, None)
36+
};
2937

3038
Ok((
3139
i,
3240
ClientHandshake {
33-
capabilities: CapabilityFlags::from_bits_truncate(cap),
41+
capabilities,
3442
maxps,
3543
collation: u16::from(collation[0]),
3644
username,
@@ -49,7 +57,7 @@ pub fn client_handshake(i: &[u8]) -> nom::IResult<&[u8], ClientHandshake<'_>> {
4957
capabilities: CapabilityFlags::from_bits_truncate(cap as u32),
5058
maxps,
5159
collation: 0,
52-
username,
60+
username: Some(username),
5361
},
5462
))
5563
}
@@ -137,20 +145,82 @@ pub fn parse(i: &[u8]) -> nom::IResult<&[u8], Command<'_>> {
137145
mod tests {
138146
use super::*;
139147
use crate::myc::constants::{CapabilityFlags, UTF8_GENERAL_CI};
140-
use crate::packet::PacketReader;
148+
use crate::packet::PacketConn;
141149
use std::io::Cursor;
142150

143151
#[test]
144152
fn it_parses_handshake() {
145-
let data = &[
153+
let data = [
146154
0x25, 0x00, 0x00, 0x01, 0x85, 0xa6, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00,
147155
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148156
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x6f, 0x6e, 0x00, 0x00,
149-
];
150-
let r = Cursor::new(&data[..]);
151-
let mut pr = PacketReader::new(r);
157+
]
158+
.to_vec();
159+
let r = Cursor::new(data);
160+
let mut pr = PacketConn::new(r);
161+
let (_, p) = pr.next().unwrap().unwrap();
162+
let (_, handshake) = client_handshake(&p, false).unwrap();
163+
println!("{:?}", handshake);
164+
assert!(handshake
165+
.capabilities
166+
.contains(CapabilityFlags::CLIENT_LONG_PASSWORD));
167+
assert!(handshake
168+
.capabilities
169+
.contains(CapabilityFlags::CLIENT_MULTI_RESULTS));
170+
assert!(!handshake
171+
.capabilities
172+
.contains(CapabilityFlags::CLIENT_CONNECT_WITH_DB));
173+
assert!(!handshake
174+
.capabilities
175+
.contains(CapabilityFlags::CLIENT_DEPRECATE_EOF));
176+
assert_eq!(handshake.collation, UTF8_GENERAL_CI);
177+
assert_eq!(handshake.username.unwrap(), &b"jon"[..]);
178+
assert_eq!(handshake.maxps, 16777216);
179+
}
180+
181+
#[test]
182+
fn it_parses_handshake_with_ssl_enabled() {
183+
let data = [
184+
0x25, 0x00, 0x00, 0x01, 0x85, 0xae, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00,
185+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x6f, 0x6e, 0x00, 0x00, 0x05,
187+
]
188+
.to_vec();
189+
let r = Cursor::new(data);
190+
let mut pr = PacketConn::new(r);
191+
let (_, p) = pr.next().unwrap().unwrap();
192+
let (_, handshake) = client_handshake(&p, false).unwrap();
193+
println!("{:?}", handshake);
194+
assert!(handshake
195+
.capabilities
196+
.contains(CapabilityFlags::CLIENT_LONG_PASSWORD));
197+
assert!(handshake
198+
.capabilities
199+
.contains(CapabilityFlags::CLIENT_MULTI_RESULTS));
200+
assert!(!handshake
201+
.capabilities
202+
.contains(CapabilityFlags::CLIENT_CONNECT_WITH_DB));
203+
assert!(!handshake
204+
.capabilities
205+
.contains(CapabilityFlags::CLIENT_DEPRECATE_EOF));
206+
assert!(handshake.capabilities.contains(CapabilityFlags::CLIENT_SSL));
207+
assert_eq!(handshake.collation, UTF8_GENERAL_CI);
208+
assert_eq!(handshake.username, None);
209+
assert_eq!(handshake.maxps, 16777216);
210+
}
211+
212+
#[test]
213+
fn it_parses_handshake_after_ssl() {
214+
let data = [
215+
0x25, 0x00, 0x00, 0x01, 0x85, 0xae, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x01, 0x21, 0x00,
216+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x6f, 0x6e, 0x00, 0x00, 0x05,
218+
]
219+
.to_vec();
220+
let r = Cursor::new(data);
221+
let mut pr = PacketConn::new(r);
152222
let (_, p) = pr.next().unwrap().unwrap();
153-
let (_, handshake) = client_handshake(&p).unwrap();
223+
let (_, handshake) = client_handshake(&p, true).unwrap();
154224
println!("{:?}", handshake);
155225
assert!(handshake
156226
.capabilities
@@ -164,20 +234,22 @@ mod tests {
164234
assert!(!handshake
165235
.capabilities
166236
.contains(CapabilityFlags::CLIENT_DEPRECATE_EOF));
237+
assert!(handshake.capabilities.contains(CapabilityFlags::CLIENT_SSL));
167238
assert_eq!(handshake.collation, UTF8_GENERAL_CI);
168-
assert_eq!(handshake.username, &b"jon"[..]);
239+
assert_eq!(handshake.username.unwrap(), &b"jon"[..]);
169240
assert_eq!(handshake.maxps, 16777216);
170241
}
171242

172243
#[test]
173244
fn it_parses_request() {
174-
let data = &[
245+
let data = [
175246
0x21, 0x00, 0x00, 0x00, 0x03, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x40, 0x40,
176247
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e,
177248
0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x31,
178-
];
179-
let r = Cursor::new(&data[..]);
180-
let mut pr = PacketReader::new(r);
249+
]
250+
.to_vec();
251+
let r = Cursor::new(data);
252+
let mut pr = PacketConn::new(r);
181253
let (_, p) = pr.next().unwrap().unwrap();
182254
let (_, cmd) = parse(&p).unwrap();
183255
assert_eq!(
@@ -191,13 +263,14 @@ mod tests {
191263
// mysql_list_fields (CommandByte::COM_FIELD_LIST / 0x04) has been deprecated in mysql 5.7 and will be removed
192264
// in a future version. The mysql command line tool issues one of these commands after
193265
// switching databases with USE <DB>.
194-
let data = &[
266+
let data = [
195267
0x21, 0x00, 0x00, 0x00, 0x04, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x40, 0x40,
196268
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e,
197269
0x74, 0x20, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x20, 0x31,
198-
];
199-
let r = Cursor::new(&data[..]);
200-
let mut pr = PacketReader::new(r);
270+
]
271+
.to_vec();
272+
let r = Cursor::new(data);
273+
let mut pr = PacketConn::new(r);
201274
let (_, p) = pr.next().unwrap().unwrap();
202275
let (_, cmd) = parse(&p).unwrap();
203276
assert_eq!(

0 commit comments

Comments
 (0)