NetworkController.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. const log$i = new Logger("NetworkController");
  2. class NetworkController extends EventEmitter {
  3. constructor(e) {
  4. super();
  5. E(this, "socket");
  6. E(this, "rtcp");
  7. E(this, "stream");
  8. E(this, "_state", "connecting");
  9. E(this, "_networkMonitor");
  10. E(this, "blockedActions", []);
  11. E(this, "reconnectCount", 0);
  12. E(this, "startGame", ()=>new Promise((e,t)=>{
  13. if (!this.rtcp.connected)
  14. return t(new InternalError("Game cannot load. Please refresh"));
  15. if (!this.rtcp.inputReady)
  16. return t(new InternalError("Game is not ready yet. Please wait"));
  17. this.socket.on("gameRoomAvailable", r=>{
  18. this.setState("connected"),
  19. e(r),
  20. this.rtcp.heartbeat.start()
  21. }
  22. ),
  23. this.socket.on("socketClosed", r=>{
  24. t(r)
  25. }
  26. ),
  27. this.socket.startGame()
  28. }
  29. ));
  30. this.room = e,
  31. this.socket = new Socket(this),
  32. this.rtcp = new Rtcp(this),
  33. this.stream = new Stream,
  34. this._networkMonitor = new NetworkMonitor(()=>{
  35. log$i.info("network changed, online:", this._networkMonitor.isOnline),
  36. this._state === "disconnected" && this._networkMonitor.isOnline && (log$i.info("network back to online, try to reconnect"),
  37. this.reconnect())
  38. }
  39. ),
  40. checkNetworkQuality(this.room.currentNetworkOptions.wsServerUrl),
  41. this._networkMonitor.start(),
  42. new VisibilityChangeHandler().subscribe(r=>{
  43. var n, o;
  44. r ? ((o = this.room.stats) == null || o.disable(),
  45. log$i.infoAndReportMeasurement({
  46. metric: "pageHide",
  47. startTime: Date.now()
  48. })) : ((n = this.room.stats) == null || n.enable(),
  49. log$i.infoAndReportMeasurement({
  50. metric: "pageShow",
  51. startTime: Date.now(),
  52. extra: {
  53. state: this._state
  54. }
  55. }),
  56. this._state === "disconnected" && this.reconnect())
  57. }
  58. )
  59. }
  60. addBlockedActions(e) {
  61. this.blockedActions.push(...e)
  62. }
  63. removeBlockedActions(e) {
  64. if (!e) {
  65. this.blockedActions = [];
  66. return
  67. }
  68. const t = this.blockedActions.indexOf(e);
  69. this.blockedActions.splice(t, 1)
  70. }
  71. setState(e) {
  72. this._state !== e && (log$i.info("Set network state to ", e),
  73. this._state = e)
  74. }
  75. async connectAndStart(e) {
  76. return this.connect(e).then(this.startGame)
  77. }
  78. async connect(e=!1) {
  79. return this.room.updateCurrentNetworkOptions({
  80. reconnect: e
  81. }),
  82. new Promise((t,r)=>{
  83. this.rtcp.on("rtcConnected", ()=>{
  84. this.setState("connected"),
  85. t()
  86. }
  87. ),
  88. this.rtcp.on("rtcDisconnected", ()=>{
  89. log$i.info("rtc disconnected"),
  90. this._state === "connecting" ? (this.setState("disconnected"),
  91. r(new InternalError("rtc connect failed"))) : (this.setState("disconnected"),
  92. log$i.info("rtc disconnected, start to reconnect"),
  93. this.reconnect())
  94. }
  95. ),
  96. this.socket.on("socketQuit", ()=>{
  97. log$i.info("socket quit success"),
  98. this.setState("closed")
  99. }
  100. ),
  101. this.socket.on("socketClosed", n=>{
  102. this._state === "connecting" && (this.setState("disconnected"),
  103. r(n)),
  104. r(n)
  105. }
  106. ),
  107. this.socket.start()
  108. }
  109. )
  110. }
  111. reconnect() {
  112. if (this.room.viewMode === "observer")
  113. return;
  114. const e = Date.now();
  115. if (this.reconnectCount++,
  116. this.reconnectCount > MAX_RECONNECT_COUNT) {
  117. log$i.error("reconnect failed, reached max reconnect count", MAX_RECONNECT_COUNT),
  118. this.reconnectCount = 0,
  119. this.emit("stateChanged", {
  120. state: "disconnected"
  121. });
  122. return
  123. }
  124. return log$i.info("start reconnect, count:", this.reconnectCount),
  125. this._reconnect().then(()=>{
  126. log$i.infoAndReportMeasurement({
  127. startTime: e,
  128. metric: "reconnect"
  129. })
  130. }
  131. ).catch(t=>{
  132. if (log$i.infoAndReportMeasurement({
  133. startTime: e,
  134. metric: "reconnect",
  135. error: t
  136. }),
  137. t.code === Codes$1.RepeatLogin) {
  138. this.room.handleRepetLogin();
  139. return
  140. }
  141. const r = 1e3;
  142. log$i.info("reconnect failed, wait " + r + " ms for next reconnect"),
  143. setTimeout(()=>{
  144. this.reconnect()
  145. }
  146. , r)
  147. }
  148. )
  149. }
  150. _reconnect() {
  151. return this._state === "closed" ? (log$i.warn("connection closed already"),
  152. Promise.reject()) : this._state === "connecting" ? (log$i.warn("connection is already in connecting state"),
  153. Promise.reject()) : this._state !== "disconnected" ? Promise.reject() : (this.prepareReconnect(),
  154. this._state = "connecting",
  155. this.emit("stateChanged", {
  156. state: "reconnecting",
  157. count: this.reconnectCount
  158. }),
  159. this.socket.off("gameRoomAvailable"),
  160. this.socket.off("socketClosed"),
  161. this.rtcp.off("rtcDisconnected"),
  162. this.rtcp.off("rtcConnected"),
  163. this.connectAndStart(!0).then(({session_id: e})=>{
  164. this.room.updateCurrentNetworkOptions({
  165. sessionId: e
  166. }),
  167. reporter.updateBody({
  168. serverSession: e
  169. }),
  170. log$i.info("reconnect success"),
  171. this.setState("connected"),
  172. this.reconnectCount = 0,
  173. this.emit("stateChanged", {
  174. state: "reconnected"
  175. })
  176. }
  177. ))
  178. }
  179. prepareReconnect() {
  180. this.rtcp.disconnect(),
  181. this.socket.prepareReconnect(),
  182. this.prepareReconnectOptions()
  183. }
  184. prepareReconnectOptions() {
  185. const {camera: e, player: t} = this.room.currentClickingState || {};
  186. e && t && this.room.updateCurrentNetworkOptions({
  187. camera: e,
  188. player: t
  189. })
  190. }
  191. sendRtcData(e) {
  192. if (this.blockedActions.includes(e.action_type)) {
  193. log$i.info(`action: ${Actions[e.action_type]} was blocked`);
  194. return
  195. }
  196. this.rtcp.sendData(e)
  197. }
  198. sendSocketData(e) {
  199. log$i.debug("ws send ->", e),
  200. this.socket.send(e)
  201. }
  202. quit() {
  203. const e = uuid$1()
  204. , t = {
  205. action_type: Actions.Exit,
  206. trace_id: e,
  207. exit_action: {},
  208. user_id: this.room.options.userId,
  209. packet_id: e
  210. };
  211. this.setState("closed"),
  212. this.socket.quit(),
  213. this.sendRtcData(t)
  214. }
  215. }