xhttp-session-id.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334
  1. // Client-side validation for xray-core #6258 sessionIDTable / sessionIDLength.
  2. // xray-core also enforces a room-size minimum (sum(table^k for k in
  3. // from..to) >= 2<<30) server-side; we deliberately skip replicating that
  4. // big-int check and only catch the cheap, obvious mistakes here.
  5. // xray-core requires the charset table to be ASCII-only.
  6. export function validateSessionIDTable(_rule: unknown, value: unknown): Promise<void> {
  7. const str = typeof value === 'string' ? value : '';
  8. if (str === '') return Promise.resolve();
  9. // eslint-disable-next-line no-control-regex
  10. if (/[^\x00-\x7f]/.test(str)) {
  11. return Promise.reject(new Error('sessionIDTable must contain only ASCII characters'));
  12. }
  13. return Promise.resolve();
  14. }
  15. // A dash-range like "8-16" or a single "8". The lower bound must be > 0
  16. // (xray rejects sessionIDLength.from <= 0 when a table is set).
  17. export function validateSessionIDLength(_rule: unknown, value: unknown): Promise<void> {
  18. const str = typeof value === 'string' ? value.trim() : '';
  19. if (str === '') return Promise.resolve();
  20. if (!/^\d+(?:-\d+)?$/.test(str)) {
  21. return Promise.reject(new Error('Use a length or range, e.g. 8 or 8-16'));
  22. }
  23. const parts = str.split('-');
  24. const from = Number(parts[0]);
  25. if (!Number.isFinite(from) || from <= 0) {
  26. return Promise.reject(new Error('sessionIDLength minimum must be greater than 0'));
  27. }
  28. if (parts.length === 2 && Number(parts[1]) < from) {
  29. return Promise.reject(new Error('sessionIDLength range upper bound must be ≥ lower bound'));
  30. }
  31. return Promise.resolve();
  32. }