'use strict'; 'require view'; 'require ui'; 'require form'; 'require tools.widgets as widgets'; // [Widget, Option, Title, Description, {Param: 'Value'}], var startupConf = [ [form.Flag, 'stdout', _('Log stdout')], [form.Flag, 'stderr', _('Log stderr')], [widgets.UserSelect, 'user', _('Run daemon as user')], [widgets.GroupSelect, 'group', _('Run daemon as group')], [form.Flag, 'respawn', _('Respawn when crashed')], [form.DynamicList, 'env', _('Environment variable'), _('OS environments pass to frp for config file template, see <a href="https://github.com/fatedier/frp#configuration-file-template">frp README</a>'), {placeholder: 'ENV_NAME=value'}], [form.DynamicList, 'conf_inc', _('Additional configs'), _('Config files include in temporary config file'), {placeholder: '/etc/frp/frpc.d/frpc_full.ini'}] ]; var commonConf = [ [form.Value, 'server_addr', _('Server address'), _('ServerAddr specifies the address of the server to connect to.<br>By default, this value is "0.0.0.0".'), {datatype: 'ipaddr'}], [form.Value, 'server_port', _('Server port'), _('ServerPort specifies the port to connect to the server on.<br>By default, this value is 7000.'), {datatype: 'port'}], [form.Value, 'http_proxy', _('HTTP proxy'), _('HttpProxy specifies a proxy address to connect to the server through. If this value is "", the server will be connected to directly.<br>By default, this value is read from the "http_proxy" environment variable.')], [form.ListValue, 'log_level', _('Log level'), _('LogLevel specifies the minimum log level. Valid values are "trace", "debug", "info", "warn", and "error".<br>By default, this value is "info".'), {values: ['trace', 'debug', 'info', 'warn', 'error']}], [form.Flag, 'disable_log_color', _('Disable log color'), _('DisableLogColor disables log colors when LogWay == "console" when set to true.'), {datatype: 'bool', default: 'true'}], [form.Value, 'token', _('Token'), _('Token specifies the authorization token used to create keys to be sent to the server. The server must have a matching token for authorization to succeed. <br>By default, this value is "".')], [form.Value, 'admin_addr', _('Admin address'), _('AdminAddr specifies the address that the admin server binds to.<br>By default, this value is "127.0.0.1".'), {datatype: 'ipaddr'}], [form.Value, 'admin_port', _('Admin port'), _('AdminPort specifies the port for the admin server to listen on. If this value is 0, the admin server will not be started.<br>By default, this value is 0.'), {datatype: 'port'}], [form.Value, 'admin_user', _('Admin user'), _('AdminUser specifies the username that the admin server will use for login.<br>By default, this value is "admin".')], [form.Value, 'admin_pwd', _('Admin password'), _('AdminPwd specifies the password that the admin server will use for login.<br>By default, this value is "admin".'), {password: true}], [form.Value, 'assets_dir', _('Assets dir'), _('AssetsDir specifies the local directory that the admin server will load resources from. If this value is "", assets will be loaded from the bundled executable using statik.<br>By default, this value is "".')], [form.Flag, 'tcp_mux', _('TCP mux'), _('TcpMux toggles TCP stream multiplexing. This allows multiple requests from a client to share a single TCP connection. If this value is true, the server must have TCP multiplexing enabled as well.<br>By default, this value is true.'), {datatype: 'bool', default: 'true'}], [form.Value, 'user', _('User'), _('User specifies a prefix for proxy names to distinguish them from other clients. If this value is not "", proxy names will automatically be changed to "{user}.{proxy_name}".<br>By default, this value is "".')], [form.Flag, 'login_fail_exit', _('Exit when login fail'), _('LoginFailExit controls whether or not the client should exit after a failed login attempt. If false, the client will retry until a login attempt succeeds.<br>By default, this value is true.'), {datatype: 'bool', default: 'true'}], [form.ListValue, 'protocol', _('Protocol'), _('Protocol specifies the protocol to use when interacting with the server. Valid values are "tcp", "kcp", and "websocket".<br>By default, this value is "tcp".'), {values: ['tcp', 'kcp', 'websocket']}], [form.Flag, 'tls_enable', _('TLS'), _('TLSEnable specifies whether or not TLS should be used when communicating with the server.'), {datatype: 'bool'}], [form.Value, 'heartbeat_interval', _('Heartbeat interval'), _('HeartBeatInterval specifies at what interval heartbeats are sent to the server, in seconds. It is not recommended to change this value.<br>By default, this value is 30.'), {datatype: 'uinteger'}], [form.Value, 'heartbeat_timeout', _('Heartbeat timeout'), _('HeartBeatTimeout specifies the maximum allowed heartbeat response delay before the connection is terminated, in seconds. It is not recommended to change this value.<br>By default, this value is 90.'), {datatype: 'uinteger'}], [form.DynamicList, '_', _('Additional settings'), _('This list can be used to specify some additional parameters which have not been included in this LuCI.'), {placeholder: 'Key-A=Value-A'}] ]; var baseProxyConf = [ [form.ListValue, 'type', _('Proxy type'), _('ProxyType specifies the type of this proxy. Valid values include "tcp", "udp", "http", "https", "stcp", and "xtcp".<br>By default, this value is "tcp".'), {values: ['tcp', 'udp', 'http', 'https', 'stcp', 'xtcp']}], [form.Flag, 'use_encryption', _('Encryption'), _('UseEncryption controls whether or not communication with the server will be encrypted. Encryption is done using the tokens supplied in the server and client configuration.<br>By default, this value is false.'), {datatype: 'bool'}], [form.Flag, 'use_compression', _('Compression'), _('UseCompression controls whether or not communication with the server will be compressed.<br>By default, this value is false.'), {datatype: 'bool'}], [form.Value, 'local_ip', _('Local IP'), _('LocalIp specifies the IP address or host name to proxy to.'), {datatype: 'ipaddr'}], [form.Value, 'local_port', _('Local port'), _('LocalPort specifies the port to proxy to.'), {datatype: 'port'}], ]; var bindInfoConf = [ [form.Value, 'remote_port', _('Remote port'), _('If remote_port is 0, frps will assign a random port for you'), {datatype: 'port'}] ]; var domainConf = [ [form.Value, 'custom_domains', _('Custom domains')], [form.Value, 'sub_domain', _('Subdomain')], ]; var httpProxyConf = [ [form.Value, 'locations', _('Locations')], [form.Value, 'http_user', _('HTTP user')], [form.Value, 'http_pwd', _('HTTP password')], [form.Value, 'host_header_rewrite', _('Host header rewrite')], // [form.Value, 'headers', _('Headers')], // FIXME ]; var stcpProxyConf = [ [form.ListValue, 'role', _('Role'), undefined, {values: ['server', 'visitor']}], [form.Value, 'sk', _('Sk')], ]; function setParams(o, params) { if (!params) return; for (var key in params) { var val = params[key]; if (key === 'values') { for (var j = 0; j < val.length; j++) { var args = val[j]; if (!Array.isArray(args)) args = [args]; o.value.apply(o, args); } } else if (key === 'depends') { if (!Array.isArray(val)) val = [val]; for (var j = 0; j < val.length; j++) { var args = val[j]; if (!Array.isArray(args)) args = [args]; o.depends.apply(o, args); } } else { o[key] = params[key]; } } if (params['datatype'] === 'bool') { o.enabled = 'true'; o.disabled = 'false'; } } function defTabOpts(s, t, opts, params) { for (var i = 0; i < opts.length; i++) { var opt = opts[i]; var o = s.taboption(t, opt[0], opt[1], opt[2], opt[3]); setParams(o, opt[4]); setParams(o, params); } } function defOpts(s, opts, params) { for (var i = 0; i < opts.length; i++) { var opt = opts[i]; var o = s.option(opt[0], opt[1], opt[2], opt[3]); setParams(o, opt[4]); setParams(o, params); } } return view.extend({ render: function() { var m, s, o; m = new form.Map('frpc', _('frp Client')); s = m.section(form.NamedSection, 'common', 'conf'); s.dynamic = true; s.tab('common', _('Common Settings')); s.tab('init', _('Startup Settings')); defTabOpts(s, 'common', commonConf, {optional: true}); o = s.taboption('init', form.SectionValue, 'init', form.TypedSection, 'init', _('Startup Settings')); s = o.subsection; s.anonymous = true; s.dynamic = true; defOpts(s, startupConf); s = m.section(form.GridSection, 'conf', _('Proxy Settings')); s.addremove = true; s.filter = function(s) { return s !== 'common'; }; s.renderSectionAdd = function(extra_class) { var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments), nameEl = el.querySelector('.cbi-section-create-name'); ui.addValidator(nameEl, 'uciname', true, function(v) { if (v === 'common') return _('Name can not be "common"'); return true; }, 'blur', 'keyup'); return el; } s.tab('general', _('General Settings')); s.tab('http', _('HTTP Settings')); s.option(form.Value, 'type', _('Proxy type')).modalonly = false; s.option(form.Value, 'local_ip', _('Local IP')).modalonly = false; s.option(form.Value, 'local_port', _('Local port')).modalonly = false; defTabOpts(s, 'general', baseProxyConf, {modalonly: true}); // TCP and UDP defTabOpts(s, 'general', bindInfoConf, {optional: true, modalonly: true, depends: [{type: 'tcp'}, {type: 'udp'}]}); // HTTP and HTTPS defTabOpts(s, 'http', domainConf, {optional: true, modalonly: true, depends: [{type: 'http'}, {type: 'https'}]}); // HTTP defTabOpts(s, 'http', httpProxyConf, {optional: true, modalonly: true, depends: {type: 'http'}}); // STCP and XTCP defTabOpts(s, 'general', stcpProxyConf, {modalonly: true, depends: [{type: 'stcp'}, {type: 'xtcp'}]}); return m.render(); } });