李勇

1.增加Server.js选点模块,Server.js本地服务器点

2.增加选点流程
此 diff 太大无法显示。
  1 +root: true
  2 +
  3 +env:
  4 + es6: true
  5 + node: true
  6 + browser: true
  7 + mocha: true
  8 +
  9 +ecmaFeatures:
  10 + modules: true
  11 +
  12 +extends:
  13 + "airbnb"
  14 +
  15 +rules:
  16 + quotes: 0
  17 + func-names: 0
  18 + comma-dangle: 0
  19 + no-new-func: 0
  20 + no-eq-null: 0
  21 + no-param-reassign: 0
  1 +.DS_Store
  2 +*.log
  3 +node_modules
  4 +src
  5 +test
  6 +examples
  7 +coverage
  1 +language: node_js
  2 +node_js:
  3 + - "iojs"
  1 +1.0.6 / 2017-2-3
  2 +==================
  3 +* update typescript config
  4 +
  5 +1.0.5 / 2016-12-29
  6 +==================
  7 +* update typescript support
  8 +
  9 +1.0.4 / 2016-12-23
  10 +==================
  11 +* add typescript support
  12 +
  13 +1.0.3 / 2016-12-04
  14 +==================
  15 +* add examples index-ie8.html
  16 +* remove `es6-promise` dependent
  17 +
  18 +1.0.2 / 2016-09-26
  19 +==================
  20 +* Use original url when Request error
  21 +
  22 +1.0.1 / 2016-08-14
  23 +==================
  24 +* Format code
  25 +* Update Readme
  26 +
  27 +1.0.0 / 2015-11-19
  28 +==================
  29 +* Remove Bower support
  30 +* Add jsonpCallback and jsonpCallbackFunction as options
  31 +
  32 +0.9.2 / 2015-08-11
  33 +==================
  34 +* Remove global export of fetchJsonp
  35 +
  36 +0.9.1 / 2015-08-11
  37 +==================
  38 +* Update removeScript fix legacy IE
  1 +# Maintaining
  2 +
  3 +## Releasing a new version
  4 +
  5 +This project follows [semver](http://semver.org/). So if you are making a bug
  6 +fix, only increment the patch level "1.0.x". If any new files are added, a
  7 +minor version "1.x.x" bump is in order.
  8 +
  9 +### Make a release commit
  10 +
  11 +To prepare the release commit:
  12 +
  13 +1. Change the npm [package.json](https://github.com/camsong/fetch-jsonp/blob/master/package.json)
  14 +`version` value to match.
  15 +2. Make a single commit with the description as "Fetch JSONP 1.x.x".
  16 +3. Finally, tag the commit with `v1.x.x`.
  17 +
  18 +```
  19 +$ git pull
  20 +$ vim package.json
  21 +$ git add package.json
  22 +$ git commit -m "Fetch JSONP 1.x.x"
  23 +$ git tag v1.x.x
  24 +$ git push
  25 +$ git push --tags
  26 +```
  1 +# Fetch JSONP [![Build Status](https://travis-ci.org/camsong/fetch-jsonp.svg)](https://travis-ci.org/camsong/fetch-jsonp) [![npm version](https://badge.fury.io/js/fetch-jsonp.svg)](http://badge.fury.io/js/fetch-jsonp) [![npm downloads](https://img.shields.io/npm/dm/fetch-jsonp.svg?style=flat-square)](https://www.npmjs.com/package/fetch-jsonp)
  2 +
  3 +JSONP is NOT supported in standard Fetch API, https://fetch.spec.whatwg.org.
  4 +fetch-jsonp provides you same API to fetch JSONP like naive Fetch, also comes
  5 +with global `fetchJsonp` function.
  6 +
  7 +If you need a `fetch` polyfill for old browsers, try [github/fetch](http://github.com/github/fetch).
  8 +
  9 +## Installation
  10 +
  11 +You can install with `npm`.
  12 +
  13 +```
  14 +npm install fetch-jsonp
  15 +```
  16 +
  17 +## Promise Polyfill for IE
  18 +
  19 +IE8/9/10/11 does not support [ES6 Promise](https://tc39.github.io/ecma262/#sec-promise-constructor), run this to polyfill the global environment at the beginning of your application.
  20 +
  21 +```js
  22 +require('es6-promise').polyfill();
  23 +```
  24 +
  25 +## Usage
  26 +
  27 +The `fetch-jsonp` function supports any HTTP method. We'll focus on GET and POST
  28 +example requests.
  29 +
  30 +### Fetch JSONP in simple way
  31 +
  32 +```javascript
  33 +fetchJsonp('/users.jsonp')
  34 + .then(function(response) {
  35 + return response.json()
  36 + }).then(function(json) {
  37 + console.log('parsed json', json)
  38 + }).catch(function(ex) {
  39 + console.log('parsing failed', ex)
  40 + })
  41 +```
  42 +
  43 +### Set JSONP callback name, default is 'callback'
  44 +
  45 +```javascript
  46 +fetchJsonp('/users.jsonp', {
  47 + jsonpCallback: 'custom_callback'
  48 + })
  49 + .then(function(response) {
  50 + return response.json()
  51 + }).then(function(json) {
  52 + console.log('parsed json', json)
  53 + }).catch(function(ex) {
  54 + console.log('parsing failed', ex)
  55 + })
  56 +```
  57 +
  58 +### Set JSONP request timeout, default is 5000ms
  59 +
  60 +```javascript
  61 +fetchJsonp('/users.jsonp', {
  62 + timeout: 3000,
  63 + jsonpCallback: 'custom_callback'
  64 + })
  65 + .then(function(response) {
  66 + return response.json()
  67 + }).then(function(json) {
  68 + console.log('parsed json', json)
  69 + }).catch(function(ex) {
  70 + console.log('parsing failed', ex)
  71 + })
  72 +```
  73 +
  74 +### Caveats
  75 +
  76 +You need to call `.then(function(response) { return response.json(); })` in order
  77 +to keep consistent with Fetch API.
  78 +
  79 +## Browser Support
  80 +
  81 +![Chrome](https://raw.github.com/alrra/browser-logos/master/chrome/chrome_48x48.png) | ![Firefox](https://raw.github.com/alrra/browser-logos/master/firefox/firefox_48x48.png) | ![IE](https://raw.github.com/alrra/browser-logos/master/internet-explorer/internet-explorer_48x48.png) | ![Opera](https://raw.github.com/alrra/browser-logos/master/opera/opera_48x48.png) | ![Safari](https://raw.github.com/alrra/browser-logos/master/safari/safari_48x48.png)
  82 +--- | --- | --- | --- | --- |
  83 +Latest ✔ | Latest ✔ | 8+ ✔ | Latest ✔ | 6.1+ ✔ |
  84 +
  85 +# License
  86 +
  87 +MIT
  88 +
  89 +# Acknowledgement
  90 +
  91 +Thanks to [github/fetch](https://github.com/github/fetch) for bring Fetch to old browsers.
  1 +(function (global, factory) {
  2 + if (typeof define === 'function' && define.amd) {
  3 + define(['exports', 'module'], factory);
  4 + } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
  5 + factory(exports, module);
  6 + } else {
  7 + var mod = {
  8 + exports: {}
  9 + };
  10 + factory(mod.exports, mod);
  11 + global.fetchJsonp = mod.exports;
  12 + }
  13 +})(this, function (exports, module) {
  14 + 'use strict';
  15 +
  16 + var defaultOptions = {
  17 + timeout: 5000,
  18 + jsonpCallback: 'callback',
  19 + jsonpCallbackFunction: null
  20 + };
  21 +
  22 + function generateCallbackFunction() {
  23 + return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
  24 + }
  25 +
  26 + // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined'
  27 + // error if request timeout
  28 + function clearFunction(functionName) {
  29 + // IE8 throws an exception when you try to delete a property on window
  30 + // http://stackoverflow.com/a/1824228/751089
  31 + try {
  32 + delete window[functionName];
  33 + } catch (e) {
  34 + window[functionName] = undefined;
  35 + }
  36 + }
  37 +
  38 + function removeScript(scriptId) {
  39 + var script = document.getElementById(scriptId);
  40 + document.getElementsByTagName('head')[0].removeChild(script);
  41 + }
  42 +
  43 + function fetchJsonp(_url) {
  44 + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
  45 +
  46 + // to avoid param reassign
  47 + var url = _url;
  48 + var timeout = options.timeout || defaultOptions.timeout;
  49 + var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
  50 +
  51 + var timeoutId = undefined;
  52 +
  53 + return new Promise(function (resolve, reject) {
  54 + var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
  55 + var scriptId = jsonpCallback + '_' + callbackFunction;
  56 +
  57 + window[callbackFunction] = function (response) {
  58 + resolve({
  59 + ok: true,
  60 + // keep consistent with fetch API
  61 + json: function json() {
  62 + return Promise.resolve(response);
  63 + }
  64 + });
  65 +
  66 + if (timeoutId) clearTimeout(timeoutId);
  67 +
  68 + removeScript(scriptId);
  69 +
  70 + clearFunction(callbackFunction);
  71 + };
  72 +
  73 + // Check if the user set their own params, and if not add a ? to start a list of params
  74 + url += url.indexOf('?') === -1 ? '?' : '&';
  75 +
  76 + var jsonpScript = document.createElement('script');
  77 + jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
  78 + jsonpScript.id = scriptId;
  79 + document.getElementsByTagName('head')[0].appendChild(jsonpScript);
  80 +
  81 + timeoutId = setTimeout(function () {
  82 + reject(new Error('JSONP request to ' + _url + ' timed out'));
  83 +
  84 + clearFunction(callbackFunction);
  85 + removeScript(scriptId);
  86 + }, timeout);
  87 + });
  88 + }
  89 +
  90 + // export as global function
  91 + /*
  92 + let local;
  93 + if (typeof global !== 'undefined') {
  94 + local = global;
  95 + } else if (typeof self !== 'undefined') {
  96 + local = self;
  97 + } else {
  98 + try {
  99 + local = Function('return this')();
  100 + } catch (e) {
  101 + throw new Error('polyfill failed because global object is unavailable in this environment');
  102 + }
  103 + }
  104 + local.fetchJsonp = fetchJsonp;
  105 + */
  106 +
  107 + module.exports = fetchJsonp;
  108 +});
  1 +declare function fetchJsonp(url: string, options?: fetchJsonp.Options): Promise<fetchJsonp.Response>;
  2 +
  3 +declare namespace fetchJsonp {
  4 + interface Options {
  5 + timeout?: number;
  6 + jsonpCallback?: string;
  7 + jsonpCallbackFunction?: string;
  8 + }
  9 +
  10 + interface Response {
  11 + json(): Promise<any>;
  12 + json<T>(): Promise<T>;
  13 + ok: boolean;
  14 + }
  15 +}
  16 +
  17 +export = fetchJsonp;
  1 +{
  2 + "_args": [
  3 + [
  4 + "fetch-jsonp",
  5 + "D:\\work\\McuClient"
  6 + ]
  7 + ],
  8 + "_from": "fetch-jsonp@latest",
  9 + "_id": "fetch-jsonp@1.0.6",
  10 + "_inCache": true,
  11 + "_installable": true,
  12 + "_location": "/fetch-jsonp",
  13 + "_nodeVersion": "5.7.1",
  14 + "_npmOperationalInternal": {
  15 + "host": "packages-12-west.internal.npmjs.com",
  16 + "tmp": "tmp/fetch-jsonp-1.0.6.tgz_1486087842804_0.46444737794809043"
  17 + },
  18 + "_npmUser": {
  19 + "email": "neosoyn@gmail.com",
  20 + "name": "camsong"
  21 + },
  22 + "_npmVersion": "3.6.0",
  23 + "_phantomChildren": {},
  24 + "_requested": {
  25 + "name": "fetch-jsonp",
  26 + "raw": "fetch-jsonp",
  27 + "rawSpec": "",
  28 + "scope": null,
  29 + "spec": "latest",
  30 + "type": "tag"
  31 + },
  32 + "_requiredBy": [
  33 + "#USER"
  34 + ],
  35 + "_resolved": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz",
  36 + "_shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
  37 + "_shrinkwrap": null,
  38 + "_spec": "fetch-jsonp",
  39 + "_where": "D:\\work\\McuClient",
  40 + "author": {
  41 + "name": "Cam Song"
  42 + },
  43 + "bugs": {
  44 + "url": "https://github.com/camsong/fetch-jsonp/issues"
  45 + },
  46 + "dependencies": {},
  47 + "description": "Fetch JSONP like a boss using Fetch API",
  48 + "devDependencies": {
  49 + "babel": "^5.8.21",
  50 + "babel-core": "^5.8.21",
  51 + "babel-eslint": "^4.0.5",
  52 + "chai": "^3.2.0",
  53 + "eslint": "^1.1.0",
  54 + "eslint-config-airbnb": "^0.0.7",
  55 + "eslint-plugin-react": "^3.2.1",
  56 + "mocha": "^2.2.5"
  57 + },
  58 + "directories": {},
  59 + "dist": {
  60 + "shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
  61 + "tarball": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz"
  62 + },
  63 + "gitHead": "3b1be53776fa36a548fbf2aa16063c27ca318661",
  64 + "homepage": "https://github.com/camsong/fetch-jsonp#readme",
  65 + "keywords": [
  66 + "fetch",
  67 + "jsonp",
  68 + "github fetch",
  69 + "ajax"
  70 + ],
  71 + "license": "MIT",
  72 + "main": "build/fetch-jsonp.js",
  73 + "maintainers": [
  74 + {
  75 + "email": "neosoyn@gmail.com",
  76 + "name": "camsong"
  77 + }
  78 + ],
  79 + "name": "fetch-jsonp",
  80 + "optionalDependencies": {},
  81 + "readme": "ERROR: No README data found!",
  82 + "repository": {
  83 + "type": "git",
  84 + "url": "git+https://github.com/camsong/fetch-jsonp.git"
  85 + },
  86 + "scripts": {
  87 + "build": "babel src/ --modules umd --out-dir build",
  88 + "clean": "rm -rf build",
  89 + "lint": "eslint src/ test/",
  90 + "test": "mocha --compilers js:babel/register --recursive --ui bdd --reporter spec"
  91 + },
  92 + "version": "1.0.6"
  93 +}
  1 +# exclude all
  2 +/*
  3 +
  4 +# project structure
  5 +!/src/
  6 +!/etc/
  7 +!/doc/
  8 +!/test/
  9 +!/dist/
  10 +
  11 +# project files
  12 +!.gitignore
  13 +!README.md
  14 +!package.json
  15 +!LICENSE
  16 +!webpack.config.umd.js
  1 +iphunter
  2 +
  3 +to hunt a fatest http response.
  4 +
  5 +# usage
  6 +
  7 +iphunter(iplist,check_call_back[,timeout]);
  8 +
  9 +```javascript
  10 +
  11 +import iphunter from 'iphunter';
  12 +
  13 +iphunter([
  14 + '192.168.99.199',
  15 + 'baidu.com',
  16 + 'aliyun.com',
  17 + 'qq.com',
  18 + '192.168.99.100',
  19 + '127.0.0.0:8080',
  20 + '192.168.1.48:8080',
  21 + 'localhost:8080'
  22 +], function (fatest_ip_response) {
  23 + if(!fatest_ip_response) return console.error('nothing!');
  24 +
  25 + console.log('done -> ', fatest_ip_response);
  26 +},3000)
  27 +
  28 +```
  1 +<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="main.js"></script></body></html>
  1 +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new o(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var o=function(){function e(t,i,r){n(this,e),this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var o=0;o<t.length;o++)this.reqsCache.push(this.send(t[o],r-10));this.timeoutId=setTimeout(this.notify.bind(this),r)}return r(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(o,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()}])});
  1 +<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="test.js"></script></body></html>
  1 +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(2)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new r(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}();t.default=o;var r=function(){function e(t,o,i){n(this,e),this.ip="",this.ipcallback=o,this.timeoutId=null,this.reqsCache=[];for(var r=0;r<t.length;r++)this.reqsCache.push(this.send(t[r],i-10));this.timeoutId=setTimeout(this.notify.bind(this),i)}return i(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,o=new XMLHttpRequest;return o.open("HEAD","//"+e+"/?_="+Date.now()),o.timeout=t,o.onload=function(){n.ip=e,n.clearReq(o),o.onload=null,n.notify()},o.ontimeout=function(){n.clearReq(o),o.ontimeout=null},o.onerror=function(){n.clearReq(o),o.onerror=null},o.onabort=function(){n.clearReq(o),o.onabort=null},o.send(),o}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(r,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(o,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var i=n(1),r=o(i);(0,r.default)(["192.168.99.199","baidu.com","aliyun.com","qq.com","192.168.99.100","127.0.0.0:8080","192.168.1.48:8080","localhost:8080"],function(e){console.log("done -> ",e)});(function(){"undefined"==typeof __REACT_HOT_LOADER__})()}])});
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <title>UMD PLAYGROUND</title>
  6 +</head>
  7 +
  8 +<body>
  9 + <div id="stage"></div>
  10 +</body>
  11 +
  12 +</html>
  1 +{
  2 + "_args": [
  3 + [
  4 + "iphunter",
  5 + "D:\\work\\McuClient"
  6 + ]
  7 + ],
  8 + "_from": "iphunter@latest",
  9 + "_id": "iphunter@1.0.6",
  10 + "_inCache": true,
  11 + "_installable": true,
  12 + "_location": "/iphunter",
  13 + "_nodeVersion": "6.9.1",
  14 + "_npmOperationalInternal": {
  15 + "host": "packages-12-west.internal.npmjs.com",
  16 + "tmp": "tmp/iphunter-1.0.6.tgz_1488779370023_0.8911087329033762"
  17 + },
  18 + "_npmUser": {
  19 + "email": "1669499355@qq.com",
  20 + "name": "xinwangwang"
  21 + },
  22 + "_npmVersion": "3.10.8",
  23 + "_phantomChildren": {},
  24 + "_requested": {
  25 + "name": "iphunter",
  26 + "raw": "iphunter",
  27 + "rawSpec": "",
  28 + "scope": null,
  29 + "spec": "latest",
  30 + "type": "tag"
  31 + },
  32 + "_requiredBy": [
  33 + "#USER"
  34 + ],
  35 + "_resolved": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz",
  36 + "_shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
  37 + "_shrinkwrap": null,
  38 + "_spec": "iphunter",
  39 + "_where": "D:\\work\\McuClient",
  40 + "author": {
  41 + "name": "AlexWang"
  42 + },
  43 + "dependencies": {},
  44 + "description": "to hunt a fatest http response.",
  45 + "devDependencies": {},
  46 + "directories": {
  47 + "doc": "doc",
  48 + "test": "test"
  49 + },
  50 + "dist": {
  51 + "shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
  52 + "tarball": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz"
  53 + },
  54 + "gitHead": "c9958f825f514736bd0451f632c227db4bf0a7b7",
  55 + "keywords": [
  56 + "ipcheck"
  57 + ],
  58 + "license": "MIT",
  59 + "main": "dist/main.js",
  60 + "maintainers": [
  61 + {
  62 + "email": "1669499355@qq.com",
  63 + "name": "xinwangwang"
  64 + }
  65 + ],
  66 + "name": "iphunter",
  67 + "optionalDependencies": {},
  68 + "readme": "ERROR: No README data found!",
  69 + "scripts": {
  70 + "test": "test/index.js"
  71 + },
  72 + "version": "1.0.6",
  73 + "wbp": {
  74 + "build": "dist/",
  75 + "entries": {
  76 + "main": "./src/main.js",
  77 + "test": "./test/test.js"
  78 + },
  79 + "project": "umd",
  80 + "source": "src/"
  81 + }
  82 +}
  1 +class IpHunter {
  2 + constructor(ips, callback, timeout) {
  3 + this.ip = '';
  4 + this.ipcallback = callback;
  5 + this.timeoutId = null;
  6 + this.reqsCache = [];
  7 +
  8 + for (let i = 0; i < ips.length; i++) {
  9 + this.reqsCache.push(this.send(ips[i], timeout - 10));
  10 + }
  11 + this.timeoutId = setTimeout(this.notify.bind(this), timeout);
  12 + }
  13 +
  14 + clearAll() {
  15 + if (this.reqsCache && this.reqsCache.length) {
  16 + this.reqsCache.forEach((req) => {
  17 + req.abort();
  18 + })
  19 + }
  20 + clearTimeout(this.timeoutId);
  21 + this.ip = '';
  22 + this.ipcallback = null;
  23 + this.timeoutId = null;
  24 + this.reqsCache = [];
  25 + }
  26 +
  27 + clearReq(req) {
  28 + this.reqsCache.splice(this.reqsCache.indexOf(req), 1);
  29 + }
  30 +
  31 + notify() {
  32 + this.ipcallback(this.ip);
  33 + this.clearAll();
  34 + }
  35 +
  36 + send(pip, timeout) {
  37 + const req = new XMLHttpRequest();
  38 + req.open('HEAD', `//${pip}/?_=${Date.now()}`);
  39 + req.timeout = timeout;
  40 + req.onload = () => {
  41 + this.ip = pip;
  42 + this.clearReq(req);
  43 + req.onload = null;
  44 + this.notify();
  45 + }
  46 + req.ontimeout = () => {
  47 + this.clearReq(req);
  48 + req.ontimeout = null;
  49 + }
  50 + req.onerror = () => {
  51 + this.clearReq(req);
  52 + req.onerror = null;
  53 + }
  54 + req.onabort = () => {
  55 + this.clearReq(req);
  56 + req.onabort = null;
  57 + }
  58 + req.send();
  59 + return req
  60 + }
  61 +}
  62 +
  63 +/**
  64 + * ips check
  65 + * @param {array} ips
  66 + * @param {number} callback
  67 + * @return {null}
  68 + */
  69 +export default function check(ips, callback, timeout = 3000) {
  70 + if (!(ips && ips.length && callback)) throw new Error('ips and callback are required.');
  71 + new IpHunter(ips, callback, timeout);
  72 +}
  73 +
  1 +import check from 'main.js';
  2 +
  3 +check([
  4 + '192.168.99.199',
  5 + 'baidu.com',
  6 + 'aliyun.com',
  7 + 'qq.com',
  8 + '192.168.99.100',
  9 + '127.0.0.0:8080',
  10 + '192.168.1.48:8080',
  11 + 'localhost:8080'
  12 +], function (ip) {
  13 + console.log('done -> ', ip);
  14 +})
  15 +
  1 +module.exports = function (umdConf) {
  2 + umdConf.devServer.host = '0.0.0.0';
  3 + umdConf.webpackFeatures.enableEntryHTML();
  4 + umdConf.output.publicPath = '';
  5 +
  6 + if (umdConf.devMode) {
  7 + umdConf.webpackFeatures.enableEntryHot('test');
  8 + } else {
  9 + umdConf.webpackFeatures.enableUglifyJs({
  10 + comments: false
  11 + });
  12 + }
  13 + // console.log(umdConf);
  14 +};
  15 +
@@ -5,6 +5,7 @@ require('string.fromcodepoint'); @@ -5,6 +5,7 @@ require('string.fromcodepoint');
5 5
6 import Emiter from './Emiter'; 6 import Emiter from './Emiter';
7 import Sass from 'Sass'; 7 import Sass from 'Sass';
  8 +import ServerCheck from 'ServerCheck';
8 import Mcu from 'mcu'; 9 import Mcu from 'mcu';
9 import MessageTypes from 'MessageTypes'; 10 import MessageTypes from 'MessageTypes';
10 import Loger from 'Loger'; 11 import Loger from 'Loger';
@@ -26,6 +27,7 @@ let _sdkInfo={"version":"v.1.0.1","author":"www.3mang.com"}; @@ -26,6 +27,7 @@ let _sdkInfo={"version":"v.1.0.1","author":"www.3mang.com"};
26 27
27 //APE 28 //APE
28 let _sass; 29 let _sass;
  30 +let _serverCheck;
29 let _mcu ; 31 let _mcu ;
30 let _confer_ape; 32 let _confer_ape;
31 let _chat_ape; 33 let _chat_ape;
@@ -34,6 +36,7 @@ let _audio_ape; @@ -34,6 +36,7 @@ let _audio_ape;
34 let _doc_ape; 36 let _doc_ape;
35 let _whiteboard_ape; 37 let _whiteboard_ape;
36 38
  39 +
37 //MCUClient 外部实例化主类 40 //MCUClient 外部实例化主类
38 export default class MessageEntrance extends Emiter { 41 export default class MessageEntrance extends Emiter {
39 constructor() { 42 constructor() {
@@ -53,12 +56,18 @@ export default class MessageEntrance extends Emiter { @@ -53,12 +56,18 @@ export default class MessageEntrance extends Emiter {
53 _sass.on('*', (type, data) => this._emit(type, data)); 56 _sass.on('*', (type, data) => this._emit(type, data));
54 _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5) 57 _sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
55 _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息 58 _sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息
56 - _sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息 59 + //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息
57 _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据 60 _sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据
  61 +
58 _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息 62 _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息
59 _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息 63 _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息
60 _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功 64 _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
61 65
  66 + //ServerCheck ip
  67 + _serverCheck=ServerCheck;
  68 + _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
  69 +
  70 +
62 // 底层MCU消息层 71 // 底层MCU消息层
63 _mcu = Mcu; 72 _mcu = Mcu;
64 _mcu.on('*', (type, data) => this._emit(type, data)); 73 _mcu.on('*', (type, data) => this._emit(type, data));
@@ -295,6 +304,7 @@ export default class MessageEntrance extends Emiter { @@ -295,6 +304,7 @@ export default class MessageEntrance extends Emiter {
295 GlobalConfig.password = _param.password || ""; 304 GlobalConfig.password = _param.password || "";
296 GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false; 305 GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;
297 GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false; 306 GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;
  307 +
298 //debugger; 308 //debugger;
299 //开始校验 309 //开始校验
300 if (_sass) { 310 if (_sass) {
@@ -355,107 +365,12 @@ export default class MessageEntrance extends Emiter { @@ -355,107 +365,12 @@ export default class MessageEntrance extends Emiter {
355 mcu 字符串 Mcu列表 365 mcu 字符串 Mcu列表
356 rs 字符串 Rs列表 366 rs 字符串 Rs列表
357 doc 字符串 Doc列表*/ 367 doc 字符串 Doc列表*/
358 -  
359 - /* {  
360 - "record": "112.126.80.182:80",  
361 - "flag": "true",  
362 - "h5Module": 1,  
363 - "maxVideoChannels": 1,  
364 - "mcu": "123.56.73.119:7000;123.56.69.230:7000;112.126.80.182:7000",  
365 - "ms": "pubms.3mang.com:1935",  
366 - "doc": "101.200.150.192:80",  
367 - "rs": "pubms.3mang.com:1935",  
368 - "type": 1,  
369 - "maxAudioChannels": 1,  
370 - "h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"  
371 - }*/  
372 -  
373 - /*  
374 - if (_data.h5_mcu_list) {  
375 - //MCU地址默认使用第一个  
376 - let server = _data.h5_mcu_list.split(";")[0];  
377 - GlobalConfig.MCUServerIP = server.split(":")[0];  
378 - GlobalConfig.MCUServerPort = server.split(":")[1];  
379 - }  
380 -  
381 - //视频推流播流地址  
382 - if (_data.ms) {  
383 - //MS地址默认使用第一个  
384 - let server = _data.ms.split(";")[0];  
385 - GlobalConfig.MSServerIP = server.split(":")[0];  
386 - GlobalConfig.MSServerPort = server.split(":")[1];  
387 - }  
388 -  
389 - //m3u8播流地址  
390 - if(_data.rs){  
391 - //RS地址默认使用第一个  
392 - let server = _data.rs.split(";")[0];  
393 - GlobalConfig.RSServerIP = server.split(":")[0];  
394 - GlobalConfig.RSServerPort = server.split(":")[1];  
395 - }  
396 -  
397 - GlobalConfig.docServer = _data.doc;  
398 - GlobalConfig.h5_mcu_list = _data.h5_mcu_list;  
399 - GlobalConfig.h5Module = _data.h5Module;  
400 - GlobalConfig.mcu = _data.mcu;  
401 - GlobalConfig.ms = _data.ms;  
402 - GlobalConfig.record = _data.record;  
403 - GlobalConfig.rs = _data.rs;  
404 - GlobalConfig.maxVideoChannels = _data.maxVideoChannels;  
405 - GlobalConfig.maxAudioChannels = _data.maxAudioChannels;  
406 -  
407 - */  
408 -  
409 -  
410 - /*  
411 - //这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃  
412 - //获取会议基本信息  
413 - if (_sass) {  
414 - _sass.getClassDetail();  
415 - }  
416 - */  
417 -  
418 //获取会议最完整的数据 368 //获取会议最完整的数据
419 if (_sass) { 369 if (_sass) {
420 _sass.getClassParam(); 370 _sass.getClassParam();
421 } 371 }
422 } 372 }
423 373
424 - //获取会议基本信息getClassH5  
425 - _sassGetClassDetailSuccessHandler(_data) {  
426 - loger.log('获取getClassDetail完成.');  
427 - /* {  
428 - "cycle": 0,  
429 - "repeatmonthweekweek": 0,  
430 - "status": 1,  
431 - "repeatmonthday": 0,  
432 - "repeatmode": 0,  
433 - "beginTime": "2017-02-03 09:00:00",  
434 - "frequency": 1,  
435 - "endmode": 0,  
436 - "meetingContent": "",  
437 - "endTime": "2017-03-31 11:00:00",  
438 - "repeatweek": "",  
439 - "category": "",  
440 - "finalenddate": "",  
441 - "repeatday": 0,  
442 - "meetingName": "mcu1",  
443 - "errorCode": 0,  
444 - "monthType": 0,  
445 - "repeatmonthweekday": 0,  
446 - "endcount": 1  
447 - }*/  
448 - GlobalConfig.classDetail = _data;  
449 - GlobalConfig.className = _data.meetingName || "";  
450 - GlobalConfig.classBeginTime = _data.beginTime || "";  
451 - GlobalConfig.classEndTime = _data.endTime || "";  
452 -  
453 - //获取会议所有信息和以前保存的会议状态信息(最全的信息)  
454 - if (_sass) {  
455 - _sass.getClassParam();  
456 - }  
457 - }  
458 -  
459 //获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do 374 //获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
460 _sassGetClassParamSuccessHandler(_data) { 375 _sassGetClassParamSuccessHandler(_data) {
461 //console.log(GlobalConfig.classStatusInfo) 376 //console.log(GlobalConfig.classStatusInfo)
@@ -467,6 +382,7 @@ export default class MessageEntrance extends Emiter { @@ -467,6 +382,7 @@ export default class MessageEntrance extends Emiter {
467 GlobalConfig.className = _data.meetingName || ""; 382 GlobalConfig.className = _data.meetingName || "";
468 GlobalConfig.classBeginTime = _data.beginTime || ""; 383 GlobalConfig.classBeginTime = _data.beginTime || "";
469 GlobalConfig.classEndTime = _data.endTime || ""; 384 GlobalConfig.classEndTime = _data.endTime || "";
  385 + GlobalConfig.userIp=_data.userIp||"";
470 386
471 GlobalConfig.maxVideoChannels = _data.maxVideoChannels; 387 GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
472 GlobalConfig.maxAudioChannels = _data.maxAudioChannels; 388 GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
@@ -526,7 +442,18 @@ export default class MessageEntrance extends Emiter { @@ -526,7 +442,18 @@ export default class MessageEntrance extends Emiter {
526 loger.log("还没有保存过会议状信息"); 442 loger.log("还没有保存过会议状信息");
527 } 443 }
528 444
529 - //所有Sass流程完成,开始MCU连接 445 + //根据用户的userIp获取信息
  446 + this.getUserIpInfo();
  447 + }
  448 + //根据UserIp获取ip信息
  449 + getUserIpInfo(){
  450 + if(_serverCheck){
  451 + _serverCheck.getUserIpInfo("",GlobalConfig.userIp);
  452 + }
  453 + }
  454 + //MCU MS ip选点完成,开加入MCU
  455 + _serverCheckBestIpSuccessHandler(_data){
  456 + loger .log("_serverCheckBestIpSuccessHandler,IP选点结束");
530 this._joinMCU(); 457 this._joinMCU();
531 } 458 }
532 459
@@ -569,49 +496,50 @@ export default class MessageEntrance extends Emiter { @@ -569,49 +496,50 @@ export default class MessageEntrance extends Emiter {
569 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2); 496 GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
570 497
571 //返回给客户端初始化成功的数据 498 //返回给客户端初始化成功的数据
572 - let initSuccessCallBackData = {};  
573 -  
574 - initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;  
575 - initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;  
576 -  
577 - initSuccessCallBackData.classId = GlobalConfig.classId;  
578 - initSuccessCallBackData.className = GlobalConfig.className;  
579 - initSuccessCallBackData.h5Module = GlobalConfig.h5Module;  
580 - initSuccessCallBackData.isHost = GlobalConfig.isHost;  
581 - initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;  
582 - initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;  
583 - initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;  
584 -  
585 - initSuccessCallBackData.msType = GlobalConfig.msType;  
586 - initSuccessCallBackData.nodeId = GlobalConfig.nodeId;  
587 - initSuccessCallBackData.password = GlobalConfig.password;  
588 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true 499 + let joinClassSuccessCallBackData = {};
  500 +
  501 + joinClassSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;
  502 + joinClassSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;
  503 +
  504 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  505 + joinClassSuccessCallBackData.className = GlobalConfig.className;
  506 + joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
  507 + joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;
  508 + joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
  509 + joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
  510 + joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
  511 +
  512 + joinClassSuccessCallBackData.msType = GlobalConfig.msType;
  513 + joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
  514 + joinClassSuccessCallBackData.password = GlobalConfig.password;
  515 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
589 //GlobalConfig.passwordRequired 老师的默认是true 516 //GlobalConfig.passwordRequired 老师的默认是true
590 //GlobalConfig.portal=_data.portal; 517 //GlobalConfig.portal=_data.portal;
591 - initSuccessCallBackData.role = GlobalConfig.role;  
592 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
593 - initSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;  
594 - initSuccessCallBackData.userId = GlobalConfig.userId;  
595 - initSuccessCallBackData.userName = GlobalConfig.userName;  
596 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
597 - initSuccessCallBackData.userType = GlobalConfig.userType; 518 + joinClassSuccessCallBackData.role = GlobalConfig.role;
  519 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  520 + joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
  521 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  522 + joinClassSuccessCallBackData.userName = GlobalConfig.userName;
  523 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  524 + joinClassSuccessCallBackData.userType = GlobalConfig.userType;
  525 +
  526 + joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
  527 + joinClassSuccessCallBackData.classId = GlobalConfig.classId;
  528 + joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
  529 + joinClassSuccessCallBackData.userId = GlobalConfig.userId;
  530 + joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
  531 + joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
  532 +
  533 + joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
  534 + joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
  535 + joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
  536 + joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
598 537
599 - initSuccessCallBackData.siteId = GlobalConfig.siteId;  
600 - initSuccessCallBackData.classId = GlobalConfig.classId;  
601 - initSuccessCallBackData.userRole = GlobalConfig.userRole;  
602 - initSuccessCallBackData.userId = GlobalConfig.userId;  
603 - initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;  
604 - initSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;  
605 loger.log('加入会议成功'); 538 loger.log('加入会议成功');
606 - console.log(initSuccessCallBackData); 539 + console.log(joinClassSuccessCallBackData);
607 540
608 //加入会议成功,广播消息 541 //加入会议成功,广播消息
609 - this._emit(MessageTypes.CLASS_JOIN_SUCCESS,initSuccessCallBackData);  
610 -  
611 -/* //返回给客户数据  
612 - if (_joinClassSuccessCallBackFun) {  
613 - _joinClassSuccessCallBackFun(initSuccessCallBackData);  
614 - }*/ 542 + this._emit(MessageTypes.CLASS_JOIN_SUCCESS,joinClassSuccessCallBackData);
615 } 543 }
616 544
617 //Sass删除文档数据 545 //Sass删除文档数据
@@ -746,6 +674,11 @@ export default class MessageEntrance extends Emiter { @@ -746,6 +674,11 @@ export default class MessageEntrance extends Emiter {
746 } 674 }
747 675
748 _getVideoPublishPath(_param){ 676 _getVideoPublishPath(_param){
  677 + if(!_mcu.connected){
  678 + loger.warn(GlobalConfig.getCurrentStatus());
  679 + return;
  680 + }
  681 +
749 if(_video_ape){ 682 if(_video_ape){
750 return _video_ape.getPublishVideoPath(_param); 683 return _video_ape.getPublishVideoPath(_param);
751 } 684 }
@@ -801,6 +734,10 @@ export default class MessageEntrance extends Emiter { @@ -801,6 +734,10 @@ export default class MessageEntrance extends Emiter {
801 } 734 }
802 735
803 _getPublishAudioPath(_param){ 736 _getPublishAudioPath(_param){
  737 + if(!_mcu.connected){
  738 + loger.warn(GlobalConfig.getCurrentStatus());
  739 + return;
  740 + }
804 if(_audio_ape){ 741 if(_audio_ape){
805 return _audio_ape.getAudioPublishPath(_param); 742 return _audio_ape.getAudioPublishPath(_param);
806 } 743 }
@@ -272,7 +272,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用 @@ -272,7 +272,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用
272 GlobalConfig.hasMicrophone=false;//麦克风是否可用 272 GlobalConfig.hasMicrophone=false;//麦克风是否可用
273 273
274 GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios 274 GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios
275 -GlobalConfig.userIP="";//用户当前IP 275 +GlobalConfig.userIp="";//用户当前IP
276 GlobalConfig.userId=0; 276 GlobalConfig.userId=0;
277 GlobalConfig.userName=""; 277 GlobalConfig.userName="";
278 278
@@ -326,4 +326,9 @@ GlobalConfig.musicListPrepare=[];//提提前上传的music集合 @@ -326,4 +326,9 @@ GlobalConfig.musicListPrepare=[];//提提前上传的music集合
326 GlobalConfig.rsList=[]; 326 GlobalConfig.rsList=[];
327 327
328 328
  329 +GlobalConfig.country ="";//国家
  330 +GlobalConfig.city ="";//城市
  331 +GlobalConfig.province = "";//服务商
  332 +GlobalConfig.isp ="";//服务商
  333 +
329 export default GlobalConfig; 334 export default GlobalConfig;
@@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes'; @@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes';
4 import GlobalConfig from 'GlobalConfig'; 4 import GlobalConfig from 'GlobalConfig';
5 import MD5 from "md5"; 5 import MD5 from "md5";
6 import ApeConsts from 'apes/ApeConsts'; 6 import ApeConsts from 'apes/ApeConsts';
  7 +import iphunter from 'iphunter';
  8 +
  9 +import fetchJsonp from 'fetch-jsonp';
7 10
8 // 日志对象 11 // 日志对象
9 const loger = Loger.getLoger('Sass'); 12 const loger = Loger.getLoger('Sass');
@@ -390,16 +393,16 @@ class Sass extends Emiter { @@ -390,16 +393,16 @@ class Sass extends Emiter {
390 let userID = GlobalConfig.userId; 393 let userID = GlobalConfig.userId;
391 let userName = GlobalConfig.userName; 394 let userName = GlobalConfig.userName;
392 let meetingName = GlobalConfig.className; 395 let meetingName = GlobalConfig.className;
393 - let startTime =GlobalConfig.classBeginTime; 396 + let startTime = GlobalConfig.classBeginTime;
394 let endTime = GlobalConfig.classEndTime; 397 let endTime = GlobalConfig.classEndTime;
395 let playUrl = ""; 398 let playUrl = "";
396 let streamName = GlobalConfig.recordFileName; 399 let streamName = GlobalConfig.recordFileName;
397 - let confRecordFileName=GlobalConfig.recordFileName; 400 + let confRecordFileName = GlobalConfig.recordFileName;
398 let downloadUrl = ""; 401 let downloadUrl = "";
399 let recordStatus = GlobalConfig.classStatus; 402 let recordStatus = GlobalConfig.classStatus;
400 - let recordTimestamp =GlobalConfig.classTimestamp; 403 + let recordTimestamp = GlobalConfig.classTimestamp;
401 404
402 - let timestamp = new Date().getTime();; 405 + let timestamp = new Date().getTime();
403 let authId = MD5(key + siteID + meetingID + timestamp); 406 let authId = MD5(key + siteID + meetingID + timestamp);
404 let url = `http://${confInfo.portal}/3m/recordingMeeting/insertRecordingMeeting.do?siteID=${siteID}&meetingID=${meetingID}&userID=${userID}&userName=${userName}&meetingName=${meetingName}&startTime=${startTime}&endTime=${endTime}&playUrl=${playUrl}&streamName=${streamName}&downloadUrl=${downloadUrl}&configFile=${confRecordFileName}&timestamp=${timestamp}&recordTimestamp=${recordTimestamp}&authId=${authId}`; 407 let url = `http://${confInfo.portal}/3m/recordingMeeting/insertRecordingMeeting.do?siteID=${siteID}&meetingID=${meetingID}&userID=${userID}&userName=${userName}&meetingName=${meetingName}&startTime=${startTime}&endTime=${endTime}&playUrl=${playUrl}&streamName=${streamName}&downloadUrl=${downloadUrl}&configFile=${confRecordFileName}&timestamp=${timestamp}&recordTimestamp=${recordTimestamp}&authId=${authId}`;
405 loger.log('saveClassRecordContrlInfo', url); 408 loger.log('saveClassRecordContrlInfo', url);
@@ -420,7 +423,7 @@ class Sass extends Emiter { @@ -420,7 +423,7 @@ class Sass extends Emiter {
420 loger.log('保存开始录制信息 完成'); 423 loger.log('保存开始录制信息 完成');
421 this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param); 424 this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
422 } else { 425 } else {
423 - loger.warn('保存开始录制信息 失败.',ret); 426 + loger.warn('保存开始录制信息 失败.', ret);
424 } 427 }
425 }) 428 })
426 .catch(err => { 429 .catch(err => {
@@ -428,7 +431,6 @@ class Sass extends Emiter { @@ -428,7 +431,6 @@ class Sass extends Emiter {
428 }); 431 });
429 432
430 } 433 }
431 -  
432 } 434 }
433 435
434 Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success'; 436 Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
  1 +import Emiter from 'Emiter';
  2 +import Loger from 'Loger';
  3 +import MessageTypes from 'MessageTypes';
  4 +import GlobalConfig from 'GlobalConfig';
  5 +import MD5 from "md5";
  6 +import ApeConsts from 'apes/ApeConsts';
  7 +import iphunter from 'iphunter';
  8 +import Server from "config/Server";
  9 +import fetchJsonp from 'fetch-jsonp';
  10 +
  11 +// 日志对象
  12 +const loger = Loger.getLoger('ServerCheck');
  13 +
  14 +//ip选点流程的状态
  15 +let isRequestMcuCallback = false;//是否获取最佳mcu返回
  16 +let isRequestMsCallback = false;//是否获取ms最佳返回
  17 +let isTestFromSass=false;
  18 +let isTestFromServer=false;
  19 +
  20 +let tempMcuIp="";
  21 +let tempMcuPort="";
  22 +let tempMsIp="";
  23 +let tempMsPort="";
  24 +class ServerCheck extends Emiter {
  25 + constructor() {
  26 + super();
  27 +
  28 + }
  29 +
  30 + //根据userIp获取ip相关的信息,参数是userIp
  31 + getUserIpInfo(token, userIp) {
  32 + //重置ip选点流程状态
  33 + isRequestMcuCallback = false;
  34 + isRequestMsCallback = false;
  35 + isTestFromSass=false;
  36 + isTestFromServer=false;
  37 +
  38 + let userIpInfo = new Object;
  39 + userIpInfo.ret = -1;
  40 +
  41 + let ip = userIp;
  42 + let md5Str = MD5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");//("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
  43 + let timestamp = new Date().getTime();
  44 + let location = `http://ipapi.ipip.net/find?addr=${ip}&sid=14&uid=5237&sig=${md5Str}&_=${timestamp}`;
  45 + loger.log('获取IP信息 ', userIp, location);
  46 +
  47 + fetchJsonp(location, {
  48 + timeout: 3000,
  49 + }).then(function (response) {
  50 + return response.json()
  51 + }).then(function (json) {
  52 + loger.log('获取IP信息返回', json)
  53 + if (json) {
  54 + userIpInfo.ret = json.ret;
  55 + userIpInfo.country = json.data[0];//国家
  56 + userIpInfo.province = json.data[1];//省份
  57 + userIpInfo.city = json.data[2];//城市
  58 + userIpInfo.isp = json.data[4];//运营商
  59 + }
  60 + this.serverGetUserIpInfoCallback(userIpInfo);
  61 + }.bind(this)).catch(function (ex) {
  62 + loger.log('获取IP信息失败', ex.message)
  63 + this.serverGetUserIpInfoCallback(userIpInfo);
  64 + }.bind(this));
  65 + }
  66 +
  67 + //获取ip信息返回
  68 + serverGetUserIpInfoCallback(userIpInfo) {
  69 + loger.log("获取IP详情,开始处理", userIpInfo);
  70 + if (userIpInfo.ret == "ok") {
  71 + GlobalConfig.country = userIpInfo.country;//国家
  72 + GlobalConfig.city = userIpInfo.city;//城市
  73 + GlobalConfig.province = userIpInfo.province;//服务商
  74 + GlobalConfig.isp = userIpInfo.isp;//服务商
  75 + loger.log("获取ip详情成功,country:" + GlobalConfig.country + ",city:" + GlobalConfig.city + ",isp:" + GlobalConfig.isp);
  76 + this._chooseBestIpFromServer();
  77 + }
  78 + else {
  79 + loger.log("获取ip详情失败");
  80 + this._chooseBestIpFromSassParam();
  81 + }
  82 + }
  83 +
  84 + //从IPIP服务列表中选择最快的IP
  85 + _chooseBestIpFromServer() {
  86 + loger.log("从IPIP服务列表中选择最快的IP");
  87 + isRequestMcuCallback=false;
  88 + isRequestMsCallback=false;
  89 + isTestFromServer=true;
  90 + isTestFromSass=false;
  91 +
  92 + let mcuIpGroup =this._returnServerMS();
  93 + let msIpGroup = this._returnServerMCU();
  94 + this.getBestMcuServer(mcuIpGroup);
  95 + this.getBestMsServer(msIpGroup);
  96 + }
  97 + //从Sass返回的msList mcuList中选点
  98 + _chooseBestIpFromSassParam() {
  99 + loger.log("从Sass服务列表中选择最快的IP");
  100 + isRequestMcuCallback=false;
  101 + isRequestMsCallback=false;
  102 + isTestFromServer=true;
  103 + isTestFromSass=true;
  104 + //MCU
  105 + let mcuIpGroup = [];
  106 + let speedTestPort = ':8080';//测速端口统一
  107 + for (let i = 0; i < GlobalConfig.mcuList.length; i++) {
  108 + let ipPort = GlobalConfig.mcuList[i].ip+speedTestPort;
  109 + mcuIpGroup.push(ipPort)
  110 + }
  111 + this.getBestMcuServer(mcuIpGroup);
  112 +
  113 +
  114 + //MS
  115 + let msIpGroup = [];
  116 + for (let i = 0; i < GlobalConfig.msList.length; i++) {
  117 + let ipPort = GlobalConfig.msList[i].ip+speedTestPort;
  118 + msIpGroup.push(ipPort)
  119 + }
  120 + this.getBestMsServer(msIpGroup);
  121 + }
  122 +
  123 +
  124 + //获取最快的MCU服务器地址,参数是一个ip数组
  125 + getBestMcuServer(_param) {
  126 + loger.log('getBestMcuServer ', _param);
  127 + if(_param==null||_param.length<1){
  128 + this._getBestMcuServerCallbackHandler("")
  129 + return;
  130 + }
  131 + iphunter(_param, function (fatest_ip_response) {
  132 + if (!fatest_ip_response) {
  133 + loger.warn('getBestMcuServer -> nothing!');
  134 + this._getBestMcuServerCallbackHandler("")
  135 + } else {
  136 + loger.log('getBestMcuServer done -> ', fatest_ip_response);
  137 + this._getBestMcuServerCallbackHandler(fatest_ip_response)
  138 + }
  139 + }.bind(this), 3000);
  140 + }
  141 +
  142 + //获取最快的MS服务器地址,参数是一个ip数组
  143 + getBestMsServer(_param) {
  144 + loger.log('getBestMsServer ', _param);
  145 + if(_param==null||_param.length<1){
  146 + this._getBestMsServerCallbackHandler("")
  147 + return;
  148 + }
  149 + iphunter(_param, function (fatest_ip_response) {
  150 + if (!fatest_ip_response) {
  151 + loger.warn('getBestMsServer -> nothing!');
  152 + this._getBestMsServerCallbackHandler("");
  153 + } else {
  154 + loger.log('getBestMsServer done -> ', fatest_ip_response);
  155 + this._getBestMsServerCallbackHandler(fatest_ip_response);
  156 + }
  157 + }.bind(this), 3000);
  158 + }
  159 +
  160 + _getBestMcuServerCallbackHandler(_data) {
  161 + loger.log("_getBestMcuServerCallbackHandler", _data);
  162 + if (isRequestMcuCallback) {
  163 + loger.log("_getBestMcuServerCallbackHandler,已经有返回");
  164 + return;
  165 + }
  166 + isRequestMcuCallback = true;
  167 + if (_data) {
  168 + let server = _data.split(":");
  169 + if (server[0]) {
  170 + tempMcuIp= server[0];
  171 + }
  172 + if (server[1]) {
  173 + tempMcuPort = server[1];
  174 + }
  175 + }
  176 + //loger.log("_getBestMcuServerCallbackHandler",tempMcuIp,tempMcuPort);
  177 + this._startConnectMcu();
  178 + }
  179 +
  180 + _getBestMsServerCallbackHandler(_data) {
  181 + loger.log("_getBestMsServerCallbackHandler", _data);
  182 + if (isRequestMsCallback) {
  183 + loger.log("_getBestMsServerCallbackHandler,已经有返回");
  184 + return;
  185 + }
  186 + isRequestMsCallback = true;
  187 + if (_data) {
  188 + let server = _data.split(":");
  189 + if (server[0]) {
  190 + tempMsIp= server[0];
  191 + }
  192 + if (server[1]) {
  193 + tempMsPort= server[1];
  194 + }
  195 + }
  196 + //loger.log("_getBestMsServerCallbackHandler", tempMsIp,tempMsPort);
  197 + this._startConnectMcu();
  198 + }
  199 +
  200 + //ip选点结束,开始连接MCU
  201 + _startConnectMcu() {
  202 + if (isRequestMcuCallback && isRequestMsCallback) {
  203 + if (isTestFromServer && !isTestFromSass) {
  204 + //从Server服务列表中选点结束,如果没有选到合适的,从Sass的列表中获取
  205 + if(!tempMcuIp||!tempMsIp){
  206 + this._chooseBestIpFromSassParam();
  207 + }else {
  208 + this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
  209 + }
  210 + } else {
  211 + //从Sass返回的服务列表中选点结束
  212 + this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
  213 + }
  214 + } else {
  215 + loger.warn("_startConnectMcu 正在选点", isRequestMcuCallback, isRequestMsCallback);
  216 + }
  217 + }
  218 +
  219 + //检测MCU连接地址
  220 + _returnServerMCU(country, province, ctiy, isp, jsona) {
  221 + let arr=[];
  222 + return arr;
  223 + }
  224 + //检测MS连接地址
  225 + //Config.ipInfo
  226 + _returnServerMS(country, province, ctiy, isp, jsona) {
  227 + let arr = [];
  228 + /* let acquire = false;
  229 + if (isp != "") {
  230 + for (let obja in jsona.MS.isp) {
  231 + if (isp.indexOf(obja.idc) != -1) {
  232 + arr = obja.mslist;
  233 + acquire = true;
  234 + break;
  235 + }
  236 + }
  237 + }
  238 + if (country == "中国" && !acquire) {
  239 + for (let obja in jsona.MS.china) {
  240 + if (obja.province.indexOf(province) != -1 && province != "") {
  241 + arr = obja.mslist;
  242 + acquire = true;
  243 + break;
  244 + }
  245 + }
  246 + if (!acquire) {
  247 + arr = jsona.MS.china[jsona.MS.china.length - 1].mslist;
  248 + acquire = true;
  249 + }
  250 + }
  251 +
  252 + if (country != "中国" && country != "") {
  253 + for (let obja:Object in jsona.MS.international) {
  254 + if (obja.country.indexOf(country) != -1) {
  255 + arr = obja.mslist;
  256 + acquire = true;
  257 + break;
  258 + }
  259 + }
  260 + if (!acquire) {
  261 + arr = jsona.MS.international[jsona.MS.international.length - 1].mslist;
  262 + acquire = true;
  263 + }
  264 + }
  265 + else if (!acquire) {
  266 + arr = jsona.MS.Default;
  267 + }
  268 +
  269 + loger.info("ms匹配结束;" + arr.length);*/
  270 + return arr;
  271 + }
  272 +}
  273 +
  274 +ServerCheck.prototype.SEVER_CHECK_BEST_IP_SUCCESS = ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS = 'severCheck_checkBestIpSuccess_message';//获取最快的MS地址
  275 +export default new ServerCheck;
  276 +
  1 +/*
  2 + * 全局数据管理
  3 + * */
  4 +import Loger from 'Loger';
  5 +import ApeConsts from "apes/ApeConsts";
  6 +
  7 +let loger = Loger.getLoger('Server');
  8 +import EngineUtils from 'EngineUtils';
  9 +
  10 +class Server {
  11 + constructor() {
  12 +
  13 + }
  14 + static get serverList(){
  15 + return {
  16 + "共享地址": [
  17 + {
  18 + "ip": "106.3.130.98",
  19 + "name": "BGP多线3"
  20 + },
  21 + {
  22 + "ip": "123.56.75.60",
  23 + "name": "BGP多线4"
  24 + },
  25 + {
  26 + "ip": "221.228.109.123",
  27 + "name": "无锡"
  28 + },
  29 + {
  30 + "ip": "qims.3mang.com",
  31 + "name": "全球通-备"
  32 + },
  33 + {
  34 + "ip": "liantong.ms.3mang.com",
  35 + "name": "联通专线"
  36 + },
  37 + {
  38 + "ip": "yidong.ms.3mang.com",
  39 + "name": "移动专线"
  40 + },
  41 + {
  42 + "ip": "dianxin.ms.3mang.com",
  43 + "name": "电信专线"
  44 + },
  45 + {
  46 + "ip": "103.235.232.128",
  47 + "name": "BGP多线2"
  48 + },
  49 + {
  50 + "ip": "lanxms.3mang.com",
  51 + "name": "国内专线"
  52 + },
  53 + {
  54 + "ip": "116.213.102.217",
  55 + "name": "BGP多线1"
  56 + }
  57 + ],
  58 + "局域网": [
  59 + {
  60 + "ip": "106.3.130.98",
  61 + "name": "BGP多线3"
  62 + },
  63 + {
  64 + "ip": "123.56.75.60",
  65 + "name": "BGP多线4"
  66 + },
  67 + {
  68 + "ip": "221.228.109.123",
  69 + "name": "无锡"
  70 + },
  71 + {
  72 + "ip": "qims.3mang.com",
  73 + "name": "全球通-备"
  74 + },
  75 + {
  76 + "ip": "liantong.ms.3mang.com",
  77 + "name": "联通专线"
  78 + },
  79 + {
  80 + "ip": "yidong.ms.3mang.com",
  81 + "name": "移动专线"
  82 + },
  83 + {
  84 + "ip": "dianxin.ms.3mang.com",
  85 + "name": "电信专线"
  86 + },
  87 + {
  88 + "ip": "103.235.232.128",
  89 + "name": "BGP多线2"
  90 + },
  91 + {
  92 + "ip": "lanxms.3mang.com",
  93 + "name": "国内专线"
  94 + },
  95 + {
  96 + "ip": "116.213.102.217",
  97 + "name": "BGP多线1"
  98 + }
  99 + ],
  100 + "中国": {
  101 + "province": {
  102 + "香港": [
  103 + {
  104 + "ip": "bjms1.3mang.com",
  105 + "name": "全球通"
  106 + },
  107 + {
  108 + "ip": "199.59.231.234",
  109 + "name": "全球通香港"
  110 + },
  111 + {
  112 + "ip": "qims.3mang.com",
  113 + "name": "全球通-备"
  114 + }
  115 + ],
  116 + "台湾": [
  117 + {
  118 + "ip": "bjms1.3mang.com",
  119 + "name": "全球通"
  120 + },
  121 + {
  122 + "ip": "159.100.205.129",
  123 + "name": "全球通台湾"
  124 + },
  125 + {
  126 + "ip": "qims.3mang.com",
  127 + "name": "全球通-备"
  128 + }
  129 + ]
  130 + },
  131 + "isp": {
  132 + "鹏博士": [
  133 + {
  134 + "ip": "124.192.148.139",
  135 + "name": "鹏博士"
  136 + },
  137 + {
  138 + "ip": "123.56.75.60",
  139 + "name": "BGP多线4"
  140 + },
  141 + {
  142 + "ip": "106.3.130.98",
  143 + "name": "BGP多线3"
  144 + },
  145 + {
  146 + "ip": "lanxms.3mang.com",
  147 + "name": "国内专线"
  148 + },
  149 + {
  150 + "ip": "qims.3mang.com",
  151 + "name": "全球通-备"
  152 + }
  153 + ],
  154 + "长城": [
  155 + {
  156 + "ip": "124.192.148.139",
  157 + "name": "鹏博士"
  158 + },
  159 + {
  160 + "ip": "123.56.75.60",
  161 + "name": "BGP多线4"
  162 + },
  163 + {
  164 + "ip": "106.3.130.98",
  165 + "name": "BGP多线3"
  166 + },
  167 + {
  168 + "ip": "lanxms.3mang.com",
  169 + "name": "国内专线"
  170 + },
  171 + {
  172 + "ip": "qims.3mang.com",
  173 + "name": "全球通-备"
  174 + }
  175 + ],
  176 + "移动": [
  177 + {
  178 + "ip": "yidong.ms.3mang.com",
  179 + "name": "移动专线"
  180 + },
  181 + {
  182 + "ip": "116.213.102.217",
  183 + "name": "BGP多线1"
  184 + },
  185 + {
  186 + "ip": "123.56.75.60",
  187 + "name": "BGP多线4"
  188 + },
  189 + {
  190 + "ip": "103.235.232.128",
  191 + "name": "BGP多线2"
  192 + },
  193 + {
  194 + "ip": "lanxms.3mang.com",
  195 + "name": "国内专线"
  196 + },
  197 + {
  198 + "ip": "qims.3mang.com",
  199 + "name": "全球通-备"
  200 + }
  201 + ],
  202 + "电信": [
  203 + {
  204 + "ip": "dianxin.ms.3mang.com",
  205 + "name": "电信专线"
  206 + },
  207 + {
  208 + "ip": "116.213.102.217",
  209 + "name": "BGP多线1"
  210 + },
  211 + {
  212 + "ip": "103.235.232.128",
  213 + "name": "BGP多线2"
  214 + },
  215 + {
  216 + "ip": "123.56.75.60",
  217 + "name": "BGP多线4"
  218 + },
  219 + {
  220 + "ip": "lanxms.3mang.com",
  221 + "name": "国内专线"
  222 + },
  223 + {
  224 + "ip": "qims.3mang.com",
  225 + "name": "全球通-备"
  226 + }
  227 + ],
  228 + "联通": [
  229 + {
  230 + "ip": "116.213.102.217",
  231 + "name": "BGP多线1"
  232 + },
  233 + {
  234 + "ip": "103.235.232.128",
  235 + "name": "BGP多线2"
  236 + },
  237 + {
  238 + "ip": "liantong.ms.3mang.com",
  239 + "name": "联通专线"
  240 + },
  241 + {
  242 + "ip": "123.56.75.60",
  243 + "name": "BGP多线4"
  244 + },
  245 + {
  246 + "ip": "106.3.130.98",
  247 + "name": "BGP多线3"
  248 + },
  249 + {
  250 + "ip": "lanxms.3mang.com",
  251 + "name": "国内专线"
  252 + },
  253 + {
  254 + "ip": "qims.3mang.com",
  255 + "name": "全球通-备"
  256 + }
  257 + ]
  258 + },
  259 + "default": [
  260 + {
  261 + "ip": "106.3.130.98",
  262 + "name": "BGP多线3"
  263 + },
  264 + {
  265 + "ip": "221.228.109.123",
  266 + "name": "无锡"
  267 + },
  268 + {
  269 + "ip": "qims.3mang.com",
  270 + "name": "全球通-备"
  271 + },
  272 + {
  273 + "ip": "liantong.ms.3mang.com",
  274 + "name": "联通专线"
  275 + },
  276 + {
  277 + "ip": "yidong.ms.3mang.com",
  278 + "name": "移动专线"
  279 + },
  280 + {
  281 + "ip": "dianxin.ms.3mang.com",
  282 + "name": "电信专线"
  283 + },
  284 + {
  285 + "ip": "lanxms.3mang.com",
  286 + "name": "国内专线"
  287 + },
  288 + {
  289 + "ip": "123.56.75.60",
  290 + "name": "BGP多线4"
  291 + },
  292 + {
  293 + "ip": "103.235.232.128",
  294 + "name": "BGP多线2"
  295 + },
  296 + {
  297 + "ip": "116.213.102.217",
  298 + "name": "BGP多线1"
  299 + }
  300 + ]
  301 + },
  302 + "美国": [
  303 + {
  304 + "ip": "38.83.109.142",
  305 + "name": "达拉斯"
  306 + },
  307 + {
  308 + "ip": "45.126.244.41",
  309 + "name": "全球通达拉斯"
  310 + },
  311 + {
  312 + "ip": "185.114.76.243",
  313 + "name": "全球通阿什本"
  314 + },
  315 + {
  316 + "ip": "159.100.196.217",
  317 + "name": "全球通迈阿密"
  318 + },
  319 + {
  320 + "ip": "185.114.77.84",
  321 + "name": "全球通圣何塞"
  322 + },
  323 + {
  324 + "ip": "159.100.195.230",
  325 + "name": "全球通洛杉矶"
  326 + },
  327 + {
  328 + "ip": "bjms1.3mang.com",
  329 + "name": "全球通"
  330 + },
  331 + {
  332 + "ip": "159.100.192.188",
  333 + "name": "全球通芝加哥"
  334 + }
  335 + ],
  336 + "加拿大": [
  337 + {
  338 + "ip": "38.83.109.142",
  339 + "name": "达拉斯"
  340 + },
  341 + {
  342 + "ip": "45.126.244.41",
  343 + "name": "全球通达拉斯"
  344 + },
  345 + {
  346 + "ip": "185.114.76.243",
  347 + "name": "全球通阿什本"
  348 + },
  349 + {
  350 + "ip": "159.100.196.217",
  351 + "name": "全球通迈阿密"
  352 + },
  353 + {
  354 + "ip": "185.114.77.84",
  355 + "name": "全球通圣何塞"
  356 + },
  357 + {
  358 + "ip": "159.100.195.230",
  359 + "name": "全球通洛杉矶"
  360 + },
  361 + {
  362 + "ip": "bjms1.3mang.com",
  363 + "name": "全球通"
  364 + },
  365 + {
  366 + "ip": "159.100.192.188",
  367 + "name": "全球通芝加哥"
  368 + }
  369 + ],
  370 + "墨西哥": [
  371 + {
  372 + "ip": "38.83.109.142",
  373 + "name": "达拉斯"
  374 + },
  375 + {
  376 + "ip": "45.126.244.41",
  377 + "name": "全球通达拉斯"
  378 + },
  379 + {
  380 + "ip": "185.114.76.243",
  381 + "name": "全球通阿什本"
  382 + },
  383 + {
  384 + "ip": "159.100.196.217",
  385 + "name": "全球通迈阿密"
  386 + },
  387 + {
  388 + "ip": "185.114.77.84",
  389 + "name": "全球通圣何塞"
  390 + },
  391 + {
  392 + "ip": "159.100.195.230",
  393 + "name": "全球通洛杉矶"
  394 + },
  395 + {
  396 + "ip": "bjms1.3mang.com",
  397 + "name": "全球通"
  398 + },
  399 + {
  400 + "ip": "159.100.192.188",
  401 + "name": "全球通芝加哥"
  402 + }
  403 + ],
  404 + "菲律宾": [
  405 + {
  406 + "ip": "223.255.248.122",
  407 + "name": "香港"
  408 + },
  409 + {
  410 + "ip": "118.193.20.130",
  411 + "name": "日本"
  412 + },
  413 + {
  414 + "ip": "118.193.24.38",
  415 + "name": "新加坡"
  416 + },
  417 + {
  418 + "ip": "bjms1.3mang.com",
  419 + "name": "全球通"
  420 + },
  421 + {
  422 + "ip": "159.100.194.120",
  423 + "name": "全球通日本"
  424 + },
  425 + {
  426 + "ip": "185.114.78.179",
  427 + "name": "全球通新加坡"
  428 + },
  429 + {
  430 + "ip": "159.100.205.129",
  431 + "name": "全球通台湾"
  432 + },
  433 + {
  434 + "ip": "192.158.245.185",
  435 + "name": "全球通韩国"
  436 + },
  437 + {
  438 + "ip": "103.29.35.63",
  439 + "name": "全球通印度"
  440 + },
  441 + {
  442 + "ip": "199.59.231.234",
  443 + "name": "全球通香港"
  444 + }
  445 + ],
  446 + "越南": [
  447 + {
  448 + "ip": "223.255.248.122",
  449 + "name": "香港"
  450 + },
  451 + {
  452 + "ip": "118.193.20.130",
  453 + "name": "日本"
  454 + },
  455 + {
  456 + "ip": "118.193.24.38",
  457 + "name": "新加坡"
  458 + },
  459 + {
  460 + "ip": "bjms1.3mang.com",
  461 + "name": "全球通"
  462 + },
  463 + {
  464 + "ip": "159.100.194.120",
  465 + "name": "全球通日本"
  466 + },
  467 + {
  468 + "ip": "185.114.78.179",
  469 + "name": "全球通新加坡"
  470 + },
  471 + {
  472 + "ip": "159.100.205.129",
  473 + "name": "全球通台湾"
  474 + },
  475 + {
  476 + "ip": "192.158.245.185",
  477 + "name": "全球通韩国"
  478 + },
  479 + {
  480 + "ip": "103.29.35.63",
  481 + "name": "全球通印度"
  482 + },
  483 + {
  484 + "ip": "199.59.231.234",
  485 + "name": "全球通香港"
  486 + }
  487 + ],
  488 + "泰国": [
  489 + {
  490 + "ip": "223.255.248.122",
  491 + "name": "香港"
  492 + },
  493 + {
  494 + "ip": "118.193.20.130",
  495 + "name": "日本"
  496 + },
  497 + {
  498 + "ip": "118.193.24.38",
  499 + "name": "新加坡"
  500 + },
  501 + {
  502 + "ip": "bjms1.3mang.com",
  503 + "name": "全球通"
  504 + },
  505 + {
  506 + "ip": "159.100.194.120",
  507 + "name": "全球通日本"
  508 + },
  509 + {
  510 + "ip": "185.114.78.179",
  511 + "name": "全球通新加坡"
  512 + },
  513 + {
  514 + "ip": "159.100.205.129",
  515 + "name": "全球通台湾"
  516 + },
  517 + {
  518 + "ip": "192.158.245.185",
  519 + "name": "全球通韩国"
  520 + },
  521 + {
  522 + "ip": "103.29.35.63",
  523 + "name": "全球通印度"
  524 + },
  525 + {
  526 + "ip": "199.59.231.234",
  527 + "name": "全球通香港"
  528 + }
  529 + ],
  530 + "default": [
  531 + {
  532 + "ip": "bjms1.3mang.com",
  533 + "name": "全球通"
  534 + },
  535 + {
  536 + "ip": "qims.3mang.com",
  537 + "name": "全球通-备"
  538 + },
  539 + {
  540 + "ip": "38.83.109.142",
  541 + "name": "达拉斯"
  542 + },
  543 + {
  544 + "ip": "118.193.20.130",
  545 + "name": "日本"
  546 + },
  547 + {
  548 + "ip": "38.123.107.18",
  549 + "name": "德国"
  550 + },
  551 + {
  552 + "ip": "223.255.248.122",
  553 + "name": "香港"
  554 + },
  555 + {
  556 + "ip": "148.153.8.22",
  557 + "port": "1935",
  558 + "name": "纽约"
  559 + },
  560 + {
  561 + "ip": "38.121.61.242",
  562 + "port": "1935",
  563 + "name": "洛杉矶"
  564 + },
  565 + {
  566 + "ip": "118.193.24.38",
  567 + "name": "新加坡"
  568 + },
  569 + {
  570 + "ip": "159.100.194.120",
  571 + "name": "全球通日本"
  572 + },
  573 + {
  574 + "ip": "159.100.192.188",
  575 + "name": "全球通芝加哥"
  576 + },
  577 + {
  578 + "ip": "45.126.244.41",
  579 + "name": "全球通达拉斯"
  580 + },
  581 + {
  582 + "ip": "45.126.246.148",
  583 + "name": "全球通德国"
  584 + },
  585 + {
  586 + "ip": "192.158.245.185",
  587 + "name": "全球通韩国"
  588 + },
  589 + {
  590 + "ip": "103.29.35.63",
  591 + "name": "全球通印度"
  592 + },
  593 + {
  594 + "ip": "202.127.74.126",
  595 + "name": "全球通新加坡"
  596 + },
  597 + {
  598 + "ip": "199.59.231.234",
  599 + "name": "全球通香港"
  600 + },
  601 + {
  602 + "ip": "159.100.205.129",
  603 + "name": "全球通台湾"
  604 + }
  605 + ]
  606 + }
  607 + }
  608 +}
  609 +
  610 +export default Server;