├── .github ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ └── Feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── mtproxy.dockerfile └── src ├── config.rs ├── main.rs ├── proto.rs ├── proxy.rs └── pump.rs /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ## Context 8 | 9 | Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions. 10 | 11 | * mtproxy Version: 12 | * Rust Version: 13 | * Operating System: 14 | 15 | ## Expected Behavior 16 | 17 | Please describe the behavior you are expecting 18 | 19 | ## Current Behavior 20 | 21 | What is the current behavior? 22 | 23 | ## Failure Information (for bugs) 24 | 25 | Please help provide information about the failure if this is a bug. If it is not a bug, please remove the rest of this template. 26 | 27 | ### Steps to Reproduce 28 | 29 | Please provide detailed steps for reproducing the issue. 30 | 31 | 1. step 1 32 | 2. step 2 33 | 3. you get it... 34 | 35 | ### Failure Logs 36 | 37 | Please include any relevant log snippets or files here. 38 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. 4 | 5 | Fixes # (issue) 6 | 7 | ## Type of change 8 | 9 | Please delete options that are not relevant. 10 | 11 | - [ ] Documentstion (typos, code examples or any documentation update) 12 | - [ ] Bug fix (non-breaking change which fixes an issue) 13 | - [ ] New feature (non-breaking change which adds functionality) 14 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 15 | - [ ] This change requires a documentation update 16 | 17 | # How Has This Been Tested? 18 | 19 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 20 | 21 | - [ ] Test A 22 | - [ ] Test B 23 | 24 | **Test Configuration**: 25 | * Rust Version: 26 | * Operating System: 27 | 28 | # Checklist: 29 | 30 | - [ ] My code follows the style guidelines of this project 31 | - [ ] I have performed a self-review of my own code 32 | - [ ] I have made corresponding changes to the documentation 33 | - [ ] My changes generate no new warnings 34 | - [ ] I have added tests that prove my fix is effective or that my feature works 35 | - [ ] New and existing unit tests pass locally with my changes 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: rust 3 | os: 4 | - linux 5 | - osx 6 | rust: 7 | - stable 8 | - nightly 9 | cache: cargo 10 | script: 11 | - cargo build 12 | - cargo test 13 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "ansi_term" 3 | version = "0.11.0" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "atty" 11 | version = "0.2.10" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | dependencies = [ 14 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 15 | "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 16 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 17 | ] 18 | 19 | [[package]] 20 | name = "base64" 21 | version = "0.9.2" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 26 | ] 27 | 28 | [[package]] 29 | name = "bitflags" 30 | version = "1.0.3" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | 33 | [[package]] 34 | name = "byteorder" 35 | version = "1.2.3" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | 38 | [[package]] 39 | name = "bytes" 40 | version = "0.4.8" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | dependencies = [ 43 | "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 44 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 45 | ] 46 | 47 | [[package]] 48 | name = "cc" 49 | version = "1.0.17" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | 52 | [[package]] 53 | name = "cfg-if" 54 | version = "0.1.3" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | 57 | [[package]] 58 | name = "chrono" 59 | version = "0.4.3" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | dependencies = [ 62 | "num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", 63 | "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", 64 | "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 65 | ] 66 | 67 | [[package]] 68 | name = "clap" 69 | version = "2.31.2" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | dependencies = [ 72 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 74 | "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 76 | "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 77 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 78 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 79 | ] 80 | 81 | [[package]] 82 | name = "cloudabi" 83 | version = "0.0.3" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | dependencies = [ 86 | "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 87 | ] 88 | 89 | [[package]] 90 | name = "fuchsia-zircon" 91 | version = "0.3.3" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | dependencies = [ 94 | "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 95 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 96 | ] 97 | 98 | [[package]] 99 | name = "fuchsia-zircon-sys" 100 | version = "0.3.3" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | 103 | [[package]] 104 | name = "gcc" 105 | version = "0.3.54" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | 108 | [[package]] 109 | name = "iovec" 110 | version = "0.1.2" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | dependencies = [ 113 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 114 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 115 | ] 116 | 117 | [[package]] 118 | name = "kernel32-sys" 119 | version = "0.2.2" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | dependencies = [ 122 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 123 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 124 | ] 125 | 126 | [[package]] 127 | name = "lazy_static" 128 | version = "1.0.1" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | 131 | [[package]] 132 | name = "lazycell" 133 | version = "0.6.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | 136 | [[package]] 137 | name = "libc" 138 | version = "0.2.42" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | 141 | [[package]] 142 | name = "log" 143 | version = "0.4.2" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | dependencies = [ 146 | "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 147 | ] 148 | 149 | [[package]] 150 | name = "mio" 151 | version = "0.6.14" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | dependencies = [ 154 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 155 | "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 156 | "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 157 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 159 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 160 | "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 161 | "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 162 | "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", 163 | "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 164 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 165 | ] 166 | 167 | [[package]] 168 | name = "miow" 169 | version = "0.2.1" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | dependencies = [ 172 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 173 | "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", 174 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 175 | "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 176 | ] 177 | 178 | [[package]] 179 | name = "mtproxy" 180 | version = "0.0.2" 181 | dependencies = [ 182 | "bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 183 | "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 184 | "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", 185 | "rand 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 186 | "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", 187 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 188 | "rustls 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 189 | "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 190 | "stderrlog 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 191 | "structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 192 | "webpki 0.18.0-alpha4 (registry+https://github.com/rust-lang/crates.io-index)", 193 | "webpki-roots 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "net2" 198 | version = "0.2.32" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | dependencies = [ 201 | "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 202 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 203 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 204 | ] 205 | 206 | [[package]] 207 | name = "num-integer" 208 | version = "0.1.38" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | dependencies = [ 211 | "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", 212 | ] 213 | 214 | [[package]] 215 | name = "num-traits" 216 | version = "0.2.4" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | 219 | [[package]] 220 | name = "proc-macro2" 221 | version = "0.4.6" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | dependencies = [ 224 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 225 | ] 226 | 227 | [[package]] 228 | name = "quote" 229 | version = "0.6.3" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | dependencies = [ 232 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 233 | ] 234 | 235 | [[package]] 236 | name = "rand" 237 | version = "0.3.22" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | dependencies = [ 240 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 241 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 242 | "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 243 | ] 244 | 245 | [[package]] 246 | name = "rand" 247 | version = "0.4.2" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | dependencies = [ 250 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 251 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 252 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 253 | ] 254 | 255 | [[package]] 256 | name = "rand" 257 | version = "0.5.1" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | dependencies = [ 260 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 261 | "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 262 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 263 | "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 264 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 265 | ] 266 | 267 | [[package]] 268 | name = "rand_core" 269 | version = "0.2.1" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | 272 | [[package]] 273 | name = "redox_syscall" 274 | version = "0.1.40" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | 277 | [[package]] 278 | name = "redox_termios" 279 | version = "0.1.1" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | dependencies = [ 282 | "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 283 | ] 284 | 285 | [[package]] 286 | name = "ring" 287 | version = "0.13.0-alpha5" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | dependencies = [ 290 | "cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 291 | "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 292 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 293 | "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 294 | ] 295 | 296 | [[package]] 297 | name = "rust-crypto" 298 | version = "0.2.36" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | dependencies = [ 301 | "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", 302 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 303 | "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", 304 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 305 | "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 306 | ] 307 | 308 | [[package]] 309 | name = "rustc-serialize" 310 | version = "0.3.24" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | 313 | [[package]] 314 | name = "rustls" 315 | version = "0.12.0" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | dependencies = [ 318 | "base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", 319 | "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 320 | "ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)", 321 | "sct 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 322 | "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 323 | "webpki 0.18.0-alpha4 (registry+https://github.com/rust-lang/crates.io-index)", 324 | ] 325 | 326 | [[package]] 327 | name = "safemem" 328 | version = "0.2.0" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | 331 | [[package]] 332 | name = "sct" 333 | version = "0.3.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | dependencies = [ 336 | "ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)", 337 | "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 338 | ] 339 | 340 | [[package]] 341 | name = "slab" 342 | version = "0.4.0" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | 345 | [[package]] 346 | name = "stderrlog" 347 | version = "0.4.0" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | dependencies = [ 350 | "chrono 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 351 | "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 352 | "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 353 | "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 354 | ] 355 | 356 | [[package]] 357 | name = "strsim" 358 | version = "0.7.0" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | 361 | [[package]] 362 | name = "structopt" 363 | version = "0.2.10" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | dependencies = [ 366 | "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", 367 | "structopt-derive 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", 368 | ] 369 | 370 | [[package]] 371 | name = "structopt-derive" 372 | version = "0.2.10" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | dependencies = [ 375 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 376 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 377 | "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", 378 | ] 379 | 380 | [[package]] 381 | name = "syn" 382 | version = "0.14.2" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | dependencies = [ 385 | "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 386 | "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 387 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 388 | ] 389 | 390 | [[package]] 391 | name = "termcolor" 392 | version = "0.3.6" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | dependencies = [ 395 | "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 396 | ] 397 | 398 | [[package]] 399 | name = "termion" 400 | version = "1.5.1" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | dependencies = [ 403 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 404 | "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 405 | "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 406 | ] 407 | 408 | [[package]] 409 | name = "textwrap" 410 | version = "0.9.0" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | dependencies = [ 413 | "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 414 | ] 415 | 416 | [[package]] 417 | name = "thread_local" 418 | version = "0.3.5" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | dependencies = [ 421 | "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 422 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 423 | ] 424 | 425 | [[package]] 426 | name = "time" 427 | version = "0.1.40" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | dependencies = [ 430 | "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", 431 | "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 432 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 433 | ] 434 | 435 | [[package]] 436 | name = "unicode-width" 437 | version = "0.1.5" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | 440 | [[package]] 441 | name = "unicode-xid" 442 | version = "0.1.0" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | 445 | [[package]] 446 | name = "unreachable" 447 | version = "1.0.0" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | dependencies = [ 450 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 451 | ] 452 | 453 | [[package]] 454 | name = "untrusted" 455 | version = "0.6.1" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | 458 | [[package]] 459 | name = "vec_map" 460 | version = "0.8.1" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | 463 | [[package]] 464 | name = "void" 465 | version = "1.0.2" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | 468 | [[package]] 469 | name = "webpki" 470 | version = "0.18.0-alpha4" 471 | source = "registry+https://github.com/rust-lang/crates.io-index" 472 | dependencies = [ 473 | "ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)", 474 | "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 475 | ] 476 | 477 | [[package]] 478 | name = "webpki-roots" 479 | version = "0.14.0" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | dependencies = [ 482 | "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", 483 | "webpki 0.18.0-alpha4 (registry+https://github.com/rust-lang/crates.io-index)", 484 | ] 485 | 486 | [[package]] 487 | name = "winapi" 488 | version = "0.2.8" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | 491 | [[package]] 492 | name = "winapi" 493 | version = "0.3.5" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | dependencies = [ 496 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 497 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 498 | ] 499 | 500 | [[package]] 501 | name = "winapi-build" 502 | version = "0.1.1" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | 505 | [[package]] 506 | name = "winapi-i686-pc-windows-gnu" 507 | version = "0.4.0" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | 510 | [[package]] 511 | name = "winapi-x86_64-pc-windows-gnu" 512 | version = "0.4.0" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | 515 | [[package]] 516 | name = "wincolor" 517 | version = "0.1.6" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | dependencies = [ 520 | "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", 521 | ] 522 | 523 | [[package]] 524 | name = "ws2_32-sys" 525 | version = "0.2.1" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | dependencies = [ 528 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 529 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 530 | ] 531 | 532 | [metadata] 533 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 534 | "checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" 535 | "checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9" 536 | "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" 537 | "checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9" 538 | "checksum bytes 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dd32989a66957d3f0cba6588f15d4281a733f4e9ffc43fcd2385f57d3bf99ff" 539 | "checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d" 540 | "checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" 541 | "checksum chrono 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a81892f0d5a53f46fc05ef0b917305a81c13f1f13bb59ac91ff595817f0764b1" 542 | "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" 543 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 544 | "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 545 | "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 546 | "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" 547 | "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" 548 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 549 | "checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" 550 | "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" 551 | "checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" 552 | "checksum log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fddaa003a65722a7fb9e26b0ce95921fe4ba590542ced664d8ce2fa26f9f3ac" 553 | "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" 554 | "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 555 | "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" 556 | "checksum num-integer 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac0ea58d64a89d9d6b7688031b3be9358d6c919badcf7fbb0527ccfd891ee45" 557 | "checksum num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "775393e285254d2f5004596d69bb8bc1149754570dcc08cf30cabeba67955e28" 558 | "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" 559 | "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" 560 | "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" 561 | "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" 562 | "checksum rand 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "482c45f965103f2433002a0c4d908599f38d1b8c1375e66e801a24c1c6cadc03" 563 | "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" 564 | "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" 565 | "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 566 | "checksum ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)" = "3845516753f91b4511f9b17c917ea6fa4bc5a7853a9947b0f66731aff51cdef5" 567 | "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" 568 | "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" 569 | "checksum rustls 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab72e4883a4fc9fd5cd462a51c55d79f6a7b5c9483e8d73a2b7bca0b18430bcd" 570 | "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" 571 | "checksum sct 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4540aed8d71a5de961a8902cf356e28122bd62695eb5be1c214f84d8704097c" 572 | "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" 573 | "checksum stderrlog 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79e2092d748ec253efe457b78b40ae2332c2e8f682d4da133896e3ee43a0cd1a" 574 | "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" 575 | "checksum structopt 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8e9ad6a11096cbecdcca0cc6aa403fdfdbaeda2fb3323a39c98e6a166a1e45a" 576 | "checksum structopt-derive 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4cbce8ccdc62166bd594c14396a3242bf94c337a51dbfa9be1076dd74b3db2af" 577 | "checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d" 578 | "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" 579 | "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" 580 | "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" 581 | "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" 582 | "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" 583 | "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" 584 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 585 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 586 | "checksum untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70afa43c8c5d23a53a3c39ec9b56232c5badc19f6bb5ad529c1d6448a7241365" 587 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 588 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 589 | "checksum webpki 0.18.0-alpha4 (registry+https://github.com/rust-lang/crates.io-index)" = "724897af4bb44f3e0142b9cca300eb15f61b9b34fa559440bed8c43f2ff7afc0" 590 | "checksum webpki-roots 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "edbd75d6abf044ef0c9d7ec92b9e8c518bcd93a15bb7bd9a92239e035248fc17" 591 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 592 | "checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" 593 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 594 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 595 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 596 | "checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" 597 | "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 598 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Vitaly Domnikov "] 3 | description = "MTProto Proxy Server" 4 | documentation = "https://github.com/dotcypress/mtproxy" 5 | homepage = "https://github.com/dotcypress/mtproxy" 6 | license = "MIT/Apache-2.0" 7 | name = "mtproxy" 8 | readme = "README.md" 9 | repository = "https://github.com/dotcypress/mtproxy" 10 | version = "0.0.2" 11 | 12 | [badges.appveyor] 13 | branch = "master" 14 | repository = "dotcypress/mtproxy" 15 | service = "github" 16 | 17 | [badges.travis-ci] 18 | branch = "master" 19 | repository = "dotcypress/mtproxy" 20 | 21 | [dependencies] 22 | bytes = "0.4.7" 23 | log = "0.4.1" 24 | mio = "0.6.14" 25 | rand = "0.5.0" 26 | rust-crypto = "0.2.36" 27 | rustc-serialize = "0.3.24" 28 | rustls = "0.12.0" 29 | slab = "0.4.0" 30 | stderrlog = "0.4.0" 31 | structopt = "0.2.10" 32 | webpki = "0.18.0-alpha3" 33 | webpki-roots = "0.14.0" 34 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT LICENSE 2 | 3 | Copyright (c) 2018 Vitaly Domnikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mtproxy 2 | 3 | 🚧 *Work in progress* 4 | 5 | `mio` powered Telegram MTProto proxy server. 6 | 7 | ## Installation 8 | 9 | You can use the `cargo install` command: 10 | 11 | ```bash 12 | $ rustup update 13 | $ cargo install mtproxy 14 | ``` 15 | or a classic build and run: 16 | 17 | ```bash 18 | $ git clone https://github.com/dotcypress/mtproxy 19 | $ cd mtproxy 20 | $ cargo build --release 21 | $ cp target/release/mtproxy ~/.bin # assuming .bin is in your path 22 | ``` 23 | 24 | *Note*: `mtproxy` requires rust v1.26.0 or higher. 25 | 26 | ## Docker 27 | ### Start proxy 28 | * `docker run --name 'mtproto_proxy' --restart unless-stopped -p 1984:1984 -dti dotcypress/mtproxy -s '07123e1f482356c415f684407a3b8723'` 29 | 30 | `07123e1f482356c415f684407a3b8723` - proxy secret, you should choose another word or generate random with `openssl rand -hex 16` 31 | 32 | ### Get secret 33 | * `docker logs mtproto_proxy` 34 | 35 | ### Stop proxy 36 | * `docker stop mtproto_proxy` 37 | 38 | ### Remove proxy 39 | * `docker rm mtproto_proxy` 40 | -------------------------------------------------------------------------------- /mtproxy.dockerfile: -------------------------------------------------------------------------------- 1 | FROM ekidd/rust-musl-builder as builder 2 | WORKDIR /home/rust/src 3 | ADD . ./ 4 | RUN sudo chown -R rust:rust . 5 | RUN cargo build --release 6 | 7 | FROM alpine:latest 8 | COPY --from=builder /home/rust/src/target/x86_64-unknown-linux-musl/release/mtproxy /bin/ 9 | 10 | ENTRYPOINT ["mtproxy"] -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use rand; 2 | use rand::Rng; 3 | use rustls::{ClientConfig, ClientSession, Stream}; 4 | use std::collections::HashMap; 5 | use std::io; 6 | use std::io::Read; 7 | use std::io::Write; 8 | use std::net::{SocketAddr, TcpStream}; 9 | use std::sync::Arc; 10 | use webpki::DNSNameRef; 11 | use webpki_roots::TLS_SERVER_ROOTS; 12 | 13 | pub struct Config { 14 | bind_addr: SocketAddr, 15 | secret: Vec, 16 | dc_secret: Vec, 17 | servers: HashMap>, 18 | } 19 | 20 | impl Config { 21 | pub fn init( 22 | bind_addr: SocketAddr, 23 | secret: Vec, 24 | _tag: Option>, 25 | ipv6: bool, 26 | ) -> io::Result { 27 | let dc_secret = Config::http_get("/getProxySecret")?; 28 | let mut servers = HashMap::new(); 29 | 30 | let path = if ipv6 { 31 | "/getProxyConfigV6" 32 | } else { 33 | "/getProxyConfig" 34 | }; 35 | 36 | match Config::http_get(path) { 37 | Ok(buf) => { 38 | let text = String::from_utf8_lossy(&buf); 39 | for line in text.lines() { 40 | if !line.starts_with("proxy_for") { 41 | continue; 42 | } 43 | 44 | let chunks: Vec<&str> = line.splitn(3, " ").collect(); 45 | let dc: i16 = chunks[1].parse().or(Err(io::Error::new( 46 | io::ErrorKind::Other, 47 | "Failed to parse proxy config", 48 | )))?; 49 | 50 | let mut addr = String::from(chunks[2]); 51 | addr.pop(); 52 | let addr = addr.parse().or(Err(io::Error::new( 53 | io::ErrorKind::Other, 54 | "Failed to parse proxy config", 55 | )))?; 56 | 57 | let dc_config = servers.entry(dc).or_insert_with(|| vec![]); 58 | dc_config.push(addr); 59 | } 60 | } 61 | Err(err) => { 62 | error!("Failed to load proxy config: {:?}", err); 63 | return Err(io::Error::new( 64 | io::ErrorKind::Other, 65 | "Failed to load proxy config", 66 | )); 67 | } 68 | }; 69 | 70 | Ok(Config { 71 | secret, 72 | dc_secret, 73 | servers, 74 | bind_addr, 75 | }) 76 | } 77 | 78 | pub fn bind_addr(&self) -> &SocketAddr { 79 | &self.bind_addr 80 | } 81 | 82 | pub fn secret(&self) -> &[u8] { 83 | &self.secret 84 | } 85 | 86 | pub fn dc_addr(&self, dc_idx: i16) -> Option<&SocketAddr> { 87 | let mut rng = rand::thread_rng(); 88 | self 89 | .servers 90 | .get(&dc_idx) 91 | .and_then(|servers| rng.choose(&servers)) 92 | } 93 | 94 | pub fn dc_secret(&self) -> &[u8] { 95 | &self.dc_secret 96 | } 97 | 98 | fn http_get(path: &str) -> io::Result> { 99 | let mut config = ClientConfig::new(); 100 | config 101 | .root_store 102 | .add_server_trust_anchors(&TLS_SERVER_ROOTS); 103 | 104 | let dns_name = DNSNameRef::try_from_ascii_str("core.telegram.org").unwrap(); 105 | let mut sess = ClientSession::new(&Arc::new(config), dns_name); 106 | let mut sock = TcpStream::connect("core.telegram.org:443")?; 107 | let mut tls = Stream::new(&mut sess, &mut sock); 108 | let payload = format!( 109 | "GET {} HTTP/1.1\r\nHost: core.telegram.org\r\nConnection: close\r\nAccept-Encoding: identity\r\n\r\n", 110 | path 111 | ); 112 | tls.write_all(payload.as_bytes())?; 113 | let mut buf = Vec::new(); 114 | tls.read_to_end(&mut buf).unwrap_or(0); 115 | Ok(buf) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | #[macro_use] 4 | extern crate log; 5 | #[macro_use] 6 | extern crate structopt; 7 | extern crate bytes; 8 | extern crate crypto; 9 | extern crate mio; 10 | extern crate rand; 11 | extern crate rustc_serialize; 12 | extern crate rustls; 13 | extern crate slab; 14 | extern crate stderrlog; 15 | extern crate webpki; 16 | extern crate webpki_roots; 17 | 18 | mod config; 19 | mod proto; 20 | mod proxy; 21 | mod pump; 22 | 23 | use std::{io, net::SocketAddr}; 24 | 25 | use config::Config; 26 | use proxy::Server; 27 | use rustc_serialize::hex::FromHex; 28 | use structopt::StructOpt; 29 | 30 | #[derive(Debug, StructOpt)] 31 | struct Cli { 32 | #[structopt( 33 | short = "a", long = "addr", default_value = "0.0.0.0:1984", help = "Listening address." 34 | )] 35 | addr: SocketAddr, 36 | 37 | #[structopt(long = "ipv6", help = "Use IPv6.")] 38 | ipv6: bool, 39 | 40 | #[structopt(short = "s", long = "secret", help = "Proxy secret.")] 41 | secret: String, 42 | 43 | #[structopt(long = "tag", help = "Proxy tag.")] 44 | tag: Option, 45 | 46 | #[structopt(short = "v", long = "verbose", parse(from_occurrences))] 47 | verbose: usize, 48 | 49 | #[structopt(short = "q", long = "quiet", help = "Silence all output.")] 50 | quiet: bool, 51 | } 52 | 53 | fn main() { 54 | if let Err(err) = run() { 55 | eprintln!("Error: {}", err) 56 | } 57 | } 58 | 59 | fn run() -> Result<(), io::Error> { 60 | let cli = Cli::from_args(); 61 | 62 | stderrlog::new() 63 | .module(module_path!()) 64 | .quiet(cli.quiet) 65 | .verbosity(cli.verbose) 66 | .timestamp(stderrlog::Timestamp::Second) 67 | .init() 68 | .unwrap(); 69 | 70 | let secret = match cli.secret.from_hex() { 71 | Ok(ref buf) if buf.len() == 16 => buf.to_vec(), 72 | Ok(_) => { 73 | return Err(io::Error::new( 74 | io::ErrorKind::Other, 75 | "Unsupported secret length", 76 | )) 77 | } 78 | Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "Mailformed secret")), 79 | }; 80 | 81 | let tag = match cli.tag { 82 | Some(tag) => match tag.from_hex() { 83 | Ok(buf) => Some(buf.to_vec()), 84 | Err(_) => return Err(io::Error::new(io::ErrorKind::Other, "Mailformed tag")), 85 | }, 86 | None => None, 87 | }; 88 | 89 | let config = Config::init(cli.addr, secret, tag, cli.ipv6)?; 90 | let mut server = Server::new(config); 91 | server.run() 92 | } 93 | -------------------------------------------------------------------------------- /src/proto.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | 3 | use std::io; 4 | 5 | use bytes::{Buf, IntoBuf}; 6 | use crypto::aes::{self, KeySize}; 7 | use crypto::symmetriccipher::SynchronousStreamCipher; 8 | use crypto::{digest::Digest, sha2::Sha256}; 9 | use rand::RngCore; 10 | 11 | pub struct Proto { 12 | seed: Vec, 13 | dc: i16, 14 | dec: Box, 15 | enc: Box, 16 | } 17 | 18 | impl Proto { 19 | pub fn new(_secret: &[u8]) -> Proto { 20 | let mut buf = vec![0u8; 64]; 21 | let mut rng = rand::thread_rng(); 22 | loop { 23 | rng.fill_bytes(&mut buf); 24 | let check = ((buf[7] as u32) << 24) 25 | | ((buf[6] as u32) << 16) 26 | | ((buf[5] as u32) << 8) 27 | | (buf[4] as u32); 28 | if buf[0] == 0xef || check == 0 { 29 | continue; 30 | } 31 | let check = ((buf[3] as u32) << 24) 32 | | ((buf[2] as u32) << 16) 33 | | ((buf[1] as u32) << 8) 34 | | (buf[0] as u32); 35 | match check { 36 | 0x44414548 | 0x54534f50 | 0x20544547 | 0x4954504f | 0xeeeeeeee => (), 37 | _ => break, 38 | } 39 | } 40 | 41 | buf[56] = 0xef; 42 | buf[57] = 0xef; 43 | buf[58] = 0xef; 44 | buf[59] = 0xef; 45 | 46 | let key_iv_enc = buf[8..56].to_vec(); 47 | let key_iv_dec: Vec = key_iv_enc.iter().rev().cloned().collect(); 48 | let mut enc = aes::ctr(KeySize::KeySize256, &key_iv_enc[0..32], &key_iv_enc[32..48]); 49 | let dec = aes::ctr(KeySize::KeySize256, &key_iv_dec[0..32], &key_iv_dec[32..48]); 50 | 51 | let mut buf_enc = vec![0u8; 64]; 52 | enc.process(&buf, &mut buf_enc); 53 | for n in 56..64 { 54 | buf[n] = buf_enc[n]; 55 | } 56 | 57 | Proto { 58 | seed: buf, 59 | dc: 0, 60 | dec, 61 | enc, 62 | } 63 | } 64 | 65 | pub fn from_seed(buf: &[u8], secret: &[u8]) -> io::Result { 66 | let mut hash = Sha256::new(); 67 | let mut dec_key = vec![0u8; hash.output_bytes()]; 68 | hash.input(&[&buf[8..40], &secret].concat()); 69 | hash.result(&mut dec_key); 70 | let key_iv_rev: Vec = buf[8..56].iter().cloned().rev().collect(); 71 | 72 | let mut hash = Sha256::new(); 73 | let mut enc_key = vec![0u8; hash.output_bytes()]; 74 | hash.input(&[&key_iv_rev[0..32], &secret].concat()); 75 | hash.result(&mut enc_key); 76 | 77 | let mut dec = aes::ctr(KeySize::KeySize256, &dec_key, &buf[40..56]); 78 | let enc = aes::ctr(KeySize::KeySize256, &enc_key, &key_iv_rev[32..48]); 79 | let mut buf_dec = vec![0u8; buf.len()]; 80 | dec.process(&buf, &mut buf_dec); 81 | if buf_dec[56] != 0xef || buf_dec[57] != 0xef || buf_dec[58] != 0xef || buf_dec[59] != 0xef { 82 | return Err(io::Error::new(io::ErrorKind::Other, "Unknown protocol")); 83 | } 84 | let dc = buf_dec[60..62].into_buf().get_i16_le(); 85 | Ok(Proto { 86 | seed: buf.to_vec(), 87 | dc, 88 | dec, 89 | enc, 90 | }) 91 | } 92 | 93 | pub fn seed(&self) -> &[u8] { 94 | &self.seed 95 | } 96 | 97 | pub fn dc(&self) -> i16 { 98 | self.dc 99 | } 100 | 101 | pub fn dec(&mut self, input: &[u8], output: &mut [u8]) { 102 | self.dec.process(input, output); 103 | } 104 | 105 | pub fn enc(&mut self, input: &[u8], output: &mut [u8]) { 106 | self.enc.process(input, output); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/proxy.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::collections::{HashMap, HashSet}; 3 | use std::io; 4 | use std::usize; 5 | 6 | use config::Config; 7 | use mio::net::{TcpListener, TcpStream}; 8 | use mio::unix::UnixReady; 9 | use mio::{Events, Poll, PollOpt, Ready, Token}; 10 | use pump::Pump; 11 | use slab::Slab; 12 | 13 | const MAX_PUMPS: usize = 256 * 1024; 14 | const ROOT_TOKEN: Token = Token(::max_value() - 1); 15 | 16 | pub struct Server { 17 | config: Config, 18 | sock: TcpListener, 19 | poll: Poll, 20 | pumps: Slab>, 21 | detached: HashSet, 22 | links: HashMap, 23 | } 24 | 25 | impl Server { 26 | pub fn new(config: Config) -> Server { 27 | let sock = TcpListener::bind(&config.bind_addr()).expect("Failed to bind"); 28 | Server { 29 | config, 30 | sock, 31 | detached: HashSet::new(), 32 | poll: Poll::new().expect("Failed to create Poll"), 33 | pumps: Slab::with_capacity(MAX_PUMPS), 34 | links: HashMap::new(), 35 | } 36 | } 37 | 38 | pub fn run(&mut self) -> io::Result<()> { 39 | info!("Starting proxy"); 40 | self 41 | .poll 42 | .register(&self.sock, ROOT_TOKEN, Ready::readable(), PollOpt::edge())?; 43 | 44 | let mut events = Events::with_capacity(512); 45 | 46 | loop { 47 | self.poll.poll(&mut events, None)?; 48 | self.dispatch(&events)?; 49 | trace!( 50 | "pumps: {}, links: {}, detached: {}", 51 | self.pumps.len(), 52 | self.links.len(), 53 | self.detached.len() 54 | ); 55 | } 56 | } 57 | 58 | fn dispatch(&mut self, events: &Events) -> io::Result<()> { 59 | let mut stale = HashSet::new(); 60 | let mut new_peers = HashMap::new(); 61 | 62 | for event in events { 63 | let token = event.token(); 64 | 65 | if token == ROOT_TOKEN { 66 | trace!("accepting new connection"); 67 | self.accept()?; 68 | continue; 69 | } 70 | 71 | let readiness = UnixReady::from(event.readiness()); 72 | let mut pump = { 73 | let pump = &self.pumps.get(token.0); 74 | if pump.is_none() { 75 | warn!("slab inconsistency"); 76 | continue; 77 | } 78 | pump.unwrap().borrow_mut() 79 | }; 80 | 81 | if readiness.is_readable() { 82 | trace!("read event: {:?}", token); 83 | match pump.drain() { 84 | Ok(Some(mut dc_idx)) => { 85 | let stream = match &self.config.dc_addr(dc_idx) { 86 | Some(addr) => TcpStream::connect(addr)?, 87 | None => { 88 | warn!("failed to resolve dc address: {}", dc_idx); 89 | continue; 90 | } 91 | }; 92 | let mut peer = Pump::downstream(&self.config.dc_secret(), stream); 93 | let buf = pump.pull(); 94 | if buf.len() > 0 { 95 | peer.push(&buf); 96 | } 97 | new_peers.insert(token, peer); 98 | } 99 | Ok(_) => {} 100 | Err(e) => { 101 | warn!("drain failed: {:?}: {}", token, e); 102 | stale.insert(token); 103 | } 104 | } 105 | if let Some(peer_token) = self.links.get(&token) { 106 | self.fan_out(&mut pump, peer_token)?; 107 | } 108 | } 109 | 110 | if readiness.is_writable() { 111 | trace!("write event: {:?}", token); 112 | if let Some(peer_token) = self.links.get(&token) { 113 | self.fan_in(&mut pump, peer_token)?; 114 | } 115 | match pump.flush() { 116 | Ok(_) => {} 117 | Err(e) => { 118 | warn!("flush failed: {:?}: {}", token, e); 119 | stale.insert(token); 120 | break; 121 | } 122 | } 123 | } 124 | 125 | if readiness.is_hup() { 126 | trace!("hup event: {:?}", event.token()); 127 | stale.insert(token); 128 | } else if readiness.is_error() { 129 | trace!("error event {:?}", event.token()); 130 | stale.insert(token); 131 | } else { 132 | self.poll.reregister( 133 | pump.sock(), 134 | token, 135 | pump.interest(), 136 | PollOpt::edge() | PollOpt::oneshot(), 137 | )?; 138 | } 139 | } 140 | 141 | for (token, peer_pump) in new_peers { 142 | let idx = self.pumps.insert(RefCell::new(peer_pump)); 143 | let peer_pump = self.pumps.get(idx).unwrap().borrow(); 144 | 145 | let peer_token = Token(idx); 146 | self.links.insert(peer_token, token); 147 | self.links.insert(token, peer_token); 148 | info!("linked to dc: {:?} -> {:?}", token, peer_token); 149 | 150 | self.poll.register( 151 | peer_pump.sock(), 152 | peer_token, 153 | peer_pump.interest(), 154 | PollOpt::edge() | PollOpt::oneshot(), 155 | )?; 156 | } 157 | 158 | for token in &self.detached { 159 | let pump = self.pumps.get(token.0).unwrap(); 160 | let mut pump = pump.borrow_mut(); 161 | if !pump.interest().is_writable() { 162 | stale.insert(*token); 163 | } 164 | } 165 | 166 | for token in stale { 167 | self.drop_pump(token)?; 168 | } 169 | 170 | Ok(()) 171 | } 172 | 173 | fn accept(&mut self) -> io::Result<()> { 174 | if self.pumps.len() > MAX_PUMPS { 175 | warn!("max connection limit({}) exceeded", MAX_PUMPS / 2); 176 | return Ok(()); 177 | } 178 | 179 | let sock = match self.sock.accept() { 180 | Ok((sock, _)) => sock, 181 | Err(err) => { 182 | warn!("accept failed: {}", err); 183 | return Ok(()); 184 | } 185 | }; 186 | 187 | let pump = Pump::upstream(self.config.secret(), sock); 188 | let idx = self.pumps.insert(RefCell::new(pump)); 189 | let pump = self.pumps.get(idx).unwrap().borrow(); 190 | 191 | let token = Token(idx); 192 | 193 | self.poll.register( 194 | pump.sock(), 195 | token, 196 | pump.interest(), 197 | PollOpt::edge() | PollOpt::oneshot(), 198 | )?; 199 | 200 | Ok(()) 201 | } 202 | 203 | fn fan_out(&self, pump: &mut Pump, peer_token: &Token) -> io::Result<()> { 204 | trace!("fan out to {:?}", peer_token); 205 | let buf = pump.pull(); 206 | if buf.is_empty() { 207 | return Ok(()); 208 | } 209 | 210 | let peer = self.pumps.get(peer_token.0).unwrap(); 211 | let mut peer = peer.borrow_mut(); 212 | peer.push(&buf); 213 | 214 | self.poll.reregister( 215 | peer.sock(), 216 | *peer_token, 217 | peer.interest(), 218 | PollOpt::edge() | PollOpt::oneshot(), 219 | )?; 220 | 221 | Ok(()) 222 | } 223 | 224 | fn fan_in(&self, pump: &mut Pump, peer_token: &Token) -> io::Result<()> { 225 | trace!("fan in from {:?}", peer_token); 226 | let peer = self.pumps.get(peer_token.0).unwrap(); 227 | let mut peer = peer.borrow_mut(); 228 | 229 | let buf = peer.pull(); 230 | if buf.is_empty() { 231 | return Ok(()); 232 | } 233 | pump.push(&buf); 234 | 235 | self.poll.reregister( 236 | peer.sock(), 237 | *peer_token, 238 | peer.interest(), 239 | PollOpt::edge() | PollOpt::oneshot(), 240 | )?; 241 | 242 | Ok(()) 243 | } 244 | 245 | fn drop_pump(&mut self, token: Token) -> io::Result<()> { 246 | self.detached.remove(&token); 247 | 248 | let pump = self.pumps.remove(token.0); 249 | let pump = pump.borrow_mut(); 250 | 251 | info!("dropping pump: {:?}", token); 252 | self.poll.deregister(pump.sock())?; 253 | match self.links.remove(&token) { 254 | Some(peer_token) => { 255 | info!("dropping link to peer: {:?} -> {:?}", token, peer_token); 256 | self.links.remove(&peer_token); 257 | self.detached.insert(peer_token); 258 | } 259 | _ => {} 260 | } 261 | Ok(()) 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/pump.rs: -------------------------------------------------------------------------------- 1 | use mio::{net::TcpStream, unix::UnixReady, Ready}; 2 | use proto::Proto; 3 | use std::io::{self, prelude::*, ErrorKind}; 4 | use std::{mem, u16}; 5 | 6 | const BUF_SIZE: usize = 128 * 1024; 7 | const MAX_READ_BUF_SIZE: usize = u16::MAX as usize * 2; 8 | 9 | pub struct Pump { 10 | sock: TcpStream, 11 | secret: Vec, 12 | proto: Option, 13 | read_buf: Vec, 14 | write_buf: Vec, 15 | interest: Ready, 16 | } 17 | 18 | impl Pump { 19 | pub fn upstream(secret: &[u8], sock: TcpStream) -> Pump { 20 | Pump { 21 | sock, 22 | secret: secret.to_vec(), 23 | proto: None, 24 | read_buf: Vec::with_capacity(BUF_SIZE), 25 | write_buf: Vec::with_capacity(BUF_SIZE), 26 | interest: Ready::readable() | UnixReady::error() | UnixReady::hup(), 27 | } 28 | } 29 | 30 | pub fn downstream(secret: &[u8], sock: TcpStream) -> Pump { 31 | let proto = Proto::new(secret); 32 | let mut write_buf = Vec::with_capacity(BUF_SIZE); 33 | write_buf.append(&mut proto.seed().to_vec()); 34 | 35 | Pump { 36 | sock, 37 | secret: secret.to_vec(), 38 | proto: Some(proto), 39 | interest: Ready::readable() | Ready::writable() | UnixReady::error() | UnixReady::hup(), 40 | read_buf: Vec::with_capacity(BUF_SIZE), 41 | write_buf, 42 | } 43 | } 44 | 45 | pub fn sock(&self) -> &TcpStream { 46 | &self.sock 47 | } 48 | 49 | pub fn interest(&self) -> Ready { 50 | self.interest 51 | } 52 | 53 | pub fn push(&mut self, input: &[u8]) { 54 | match self.proto { 55 | Some(ref mut proto) => { 56 | let mut buf = vec![0u8; input.len()]; 57 | proto.enc(input, &mut buf); 58 | self.write_buf.append(&mut buf); 59 | self.interest.insert(Ready::writable()); 60 | } 61 | None => { 62 | debug!("failed to push. protocol not ready."); 63 | } 64 | } 65 | } 66 | 67 | pub fn pull(&mut self) -> Vec { 68 | if self.read_buf.is_empty() { 69 | return vec![]; 70 | } 71 | match self.proto { 72 | Some(ref mut proto) => { 73 | let mut buf = vec![0u8; self.read_buf.len()]; 74 | proto.dec(&self.read_buf, &mut buf); 75 | self.read_buf.clear(); 76 | self.interest.insert(Ready::readable()); 77 | buf 78 | } 79 | None => { 80 | debug!("failed to pull. protocol not ready."); 81 | vec![] 82 | } 83 | } 84 | } 85 | 86 | pub fn flush(&mut self) -> io::Result<()> { 87 | loop { 88 | match self.sock.write(&self.write_buf) { 89 | Ok(n) => { 90 | trace!("write {} bytes", n); 91 | let mut rest = self.write_buf.split_off(n); 92 | mem::swap(&mut rest, &mut self.write_buf); 93 | if self.write_buf.is_empty() { 94 | self.interest.remove(Ready::writable()); 95 | break; 96 | } 97 | } 98 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => { 99 | break; 100 | } 101 | Err(e) => return Err(e), 102 | } 103 | } 104 | Ok(()) 105 | } 106 | 107 | pub fn drain(&mut self) -> io::Result> { 108 | let mut link_pending = None; 109 | 110 | loop { 111 | if self.read_buf.len() > MAX_READ_BUF_SIZE { 112 | debug!("read buffer is full"); 113 | self.interest.remove(Ready::readable()); 114 | break; 115 | } 116 | let mut buf = vec![0u8; BUF_SIZE]; 117 | match self.sock.read(&mut buf) { 118 | Ok(0) => break, 119 | Ok(n) => { 120 | trace!("read {} bytes", n); 121 | buf.split_off(n); 122 | self.read_buf.extend(buf); 123 | 124 | if self.proto.is_none() { 125 | if self.read_buf.len() == 41 { 126 | return Err(io::Error::new(io::ErrorKind::Other, "Fake PQ req")); 127 | } 128 | if self.read_buf.len() >= 64 { 129 | let mut seed = self.read_buf.split_off(64); 130 | mem::swap(&mut seed, &mut self.read_buf); 131 | let proto = Proto::from_seed(&seed, &self.secret)?; 132 | link_pending = Some(proto.dc()); 133 | self.proto = Some(proto); 134 | } 135 | } 136 | } 137 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => { 138 | break; 139 | } 140 | Err(e) => return Err(e), 141 | } 142 | } 143 | Ok(link_pending) 144 | } 145 | } 146 | --------------------------------------------------------------------------------