trojan-uri.peg 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // global initializer
  2. {{
  3. function $set(obj, path, value) {
  4. if (Object(obj) !== obj) return obj;
  5. if (!Array.isArray(path)) path = path.toString().match(/[^.[\]]+/g) || [];
  6. path
  7. .slice(0, -1)
  8. .reduce((a, c, i) => (Object(a[c]) === a[c] ? a[c] : (a[c] = Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] : {})), obj)[
  9. path[path.length - 1]
  10. ] = value;
  11. return obj;
  12. }
  13. function toBool(str) {
  14. if (typeof str === 'undefined' || str === null) return undefined;
  15. return /(TRUE)|1/i.test(str);
  16. }
  17. }}
  18. {
  19. const proxy = {};
  20. const obfs = {};
  21. const $ = {};
  22. const params = {};
  23. }
  24. start = (trojan) {
  25. return proxy
  26. }
  27. trojan = "trojan://" password:password "@" server:server ":" port:port "/"? params? name:name?{
  28. proxy.type = "trojan";
  29. proxy.password = password;
  30. proxy.server = server;
  31. proxy.port = port;
  32. proxy.name = name;
  33. // name may be empty
  34. if (!proxy.name) {
  35. proxy.name = server + ":" + port;
  36. }
  37. };
  38. password = match:$[^@]+ {
  39. return decodeURIComponent(match);
  40. };
  41. server = ip/domain;
  42. domain = match:[0-9a-zA-z-_.]+ {
  43. const domain = match.join("");
  44. if (/(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]/.test(domain)) {
  45. return domain;
  46. }
  47. }
  48. ip = & {
  49. const start = peg$currPos;
  50. let end;
  51. let j = start;
  52. while (j < input.length) {
  53. if (input[j] === ",") break;
  54. if (input[j] === ":") end = j;
  55. j++;
  56. }
  57. peg$currPos = end || j;
  58. $.ip = input.substring(start, end).trim();
  59. return true;
  60. } { return $.ip; }
  61. port = digits:[0-9]+ {
  62. const port = parseInt(digits.join(""), 10);
  63. if (port >= 0 && port <= 65535) {
  64. return port;
  65. } else {
  66. throw new Error("Invalid port: " + port);
  67. }
  68. }
  69. params = "?" head:param tail:("&"@param)* {
  70. proxy["skip-cert-verify"] = toBool(params["allowInsecure"]);
  71. proxy.sni = params["sni"] || params["peer"];
  72. if (toBool(params["ws"])) {
  73. proxy.network = "ws";
  74. $set(proxy, "ws-opts.path", params["wspath"]);
  75. }
  76. if (params["type"]) {
  77. let httpupgrade
  78. proxy.network = params["type"]
  79. if(proxy.network === 'httpupgrade') {
  80. proxy.network = 'ws'
  81. httpupgrade = true
  82. }
  83. if (['grpc'].includes(proxy.network)) {
  84. proxy[proxy.network + '-opts'] = {
  85. 'grpc-service-name': params["serviceName"],
  86. '_grpc-type': params["mode"],
  87. };
  88. } else {
  89. if (params["path"]) {
  90. $set(proxy, proxy.network+"-opts.path", decodeURIComponent(params["path"]));
  91. }
  92. if (params["host"]) {
  93. $set(proxy, proxy.network+"-opts.headers.Host", decodeURIComponent(params["host"]));
  94. }
  95. if (httpupgrade) {
  96. $set(proxy, proxy.network+"-opts.v2ray-http-upgrade", true);
  97. $set(proxy, proxy.network+"-opts.v2ray-http-upgrade-fast-open", true);
  98. }
  99. }
  100. }
  101. proxy.udp = toBool(params["udp"]);
  102. proxy.tfo = toBool(params["tfo"]);
  103. }
  104. param = kv/single;
  105. kv = key:$[a-z]i+ "=" value:$[^&#]i* {
  106. params[key] = value;
  107. }
  108. single = key:$[a-z]i+ {
  109. params[key] = true;
  110. };
  111. name = "#" + match:$.* {
  112. return decodeURIComponent(match);
  113. }