|
| 1 | +//! MySQL Proxy Server |
| 2 | +externcrate mysql_proxy; |
| 3 | +use mysql_proxy::*; |
| 4 | + |
| 5 | +#[macro_use] |
| 6 | +externcrate log; |
| 7 | +externcrate env_logger; |
| 8 | +#[macro_use] |
| 9 | +externcrate futures; |
| 10 | +#[macro_use] |
| 11 | +externcrate tokio_core; |
| 12 | +externcrate byteorder; |
| 13 | + |
| 14 | +use std::rc::Rc; |
| 15 | +use std::env; |
| 16 | +use std::net::{SocketAddr}; |
| 17 | +use std::str; |
| 18 | + |
| 19 | +use futures::{Future}; |
| 20 | +use futures::stream::Stream; |
| 21 | +use tokio_core::net::{TcpStream,TcpListener}; |
| 22 | +use tokio_core::reactor::{Core}; |
| 23 | + |
| 24 | +fnmain(){ |
| 25 | + env_logger::init().unwrap(); |
| 26 | + |
| 27 | +// determine address for the proxy to bind to |
| 28 | +let bind_addr = env::args().nth(1).unwrap_or("127.0.0.1:3307".to_string()); |
| 29 | +let bind_addr = bind_addr.parse::<SocketAddr>().unwrap(); |
| 30 | + |
| 31 | +// determine address of the MySQL instance we are proxying for |
| 32 | +let mysql_addr = env::args().nth(2).unwrap_or("127.0.0.1:3306".to_string()); |
| 33 | +let mysql_addr = mysql_addr.parse::<SocketAddr>().unwrap(); |
| 34 | + |
| 35 | +// Create the tokio event loop that will drive this server |
| 36 | +letmut l =Core::new().unwrap(); |
| 37 | + |
| 38 | +// Get a reference to the reactor event loop |
| 39 | +let handle = l.handle(); |
| 40 | + |
| 41 | +// Create a TCP listener which will listen for incoming connections |
| 42 | +let socket =TcpListener::bind(&bind_addr,&l.handle()).unwrap(); |
| 43 | +println!("Listening on: {}", bind_addr); |
| 44 | + |
| 45 | +// for each incoming connection |
| 46 | +let done = socket.incoming().for_each(move |(socket, _)|{ |
| 47 | + |
| 48 | +// create a future to serve requests |
| 49 | +let future =TcpStream::connect(&mysql_addr,&handle) |
| 50 | +.and_then(move |mysql|{Ok((socket, mysql))}) |
| 51 | +.and_then(move |(client, server)| |
| 52 | +{Pipe::new(Rc::new(client),Rc::new(server),PassthroughHandler{}) |
| 53 | +}); |
| 54 | + |
| 55 | +// tell the tokio reactor to run the future |
| 56 | + handle.spawn(future.map_err(|err|{ |
| 57 | +println!("Failed to spawn future: {:?}", err); |
| 58 | +})); |
| 59 | + |
| 60 | +// everything is great! |
| 61 | +Ok(()) |
| 62 | + |
| 63 | +}); |
| 64 | + l.run(done).unwrap(); |
| 65 | +} |
| 66 | + |
| 67 | +structPassthroughHandler{} |
| 68 | + |
| 69 | +implPacketHandlerforPassthroughHandler{ |
| 70 | + |
| 71 | +fnhandle_request(&mutself,p:&Packet) ->Action{ |
| 72 | +print_packet_chars(&p.bytes); |
| 73 | +Action::Forward |
| 74 | +} |
| 75 | + |
| 76 | +fnhandle_response(&mutself, _:&Packet) ->Action{ |
| 77 | +// forward all responses to the client |
| 78 | +Action::Forward |
| 79 | +} |
| 80 | + |
| 81 | +} |
| 82 | + |
| 83 | +#[allow(dead_code)] |
| 84 | +pubfnprint_packet_chars(buf:&[u8]){ |
| 85 | +print!("["); |
| 86 | +for iin0..buf.len(){ |
| 87 | +print!("{} ", buf[i]aschar); |
| 88 | +} |
| 89 | +println!("]"); |
| 90 | +} |
| 91 | + |
| 92 | +#[allow(dead_code)] |
| 93 | +pubfnprint_packet_bytes(buf:&[u8]){ |
| 94 | +print!("["); |
| 95 | +for iin0..buf.len(){ |
| 96 | +if i%8==0{println!("");} |
| 97 | +print!("{:#04x} ",buf[i]); |
| 98 | +} |
| 99 | +println!("]"); |
| 100 | +} |