You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
преди 4 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. const connections = {}
  2. const datachannels = {}
  3. const streams = {}
  4. const screen = {}
  5. function setTracks({source, tracks}) {
  6. streams[source] = streams[source] || new MediaStream()
  7. streams[source].getTracks().forEach(t => streams[source].removeTrack(t))
  8. tracks.forEach(track => streams[source].addTrack(track))
  9. m.redraw()
  10. if(source === State.username) {
  11. reloadAllStreams()
  12. }
  13. }
  14. function reloadAllStreams() {
  15. State.online.forEach(username => {
  16. signal({kind: 'rpc', value: {type: 'request'}, source: username})
  17. })
  18. }
  19. function getOwnTracks() {
  20. if(streams[State.username]) {
  21. return streams[State.username].getTracks()
  22. }
  23. else {
  24. return []
  25. }
  26. }
  27. function createConnection(target) {
  28. const rpc = new RTCPeerConnection(rpcConfig)
  29. rpc.onicecandidate = ({candidate}) => {
  30. if(candidate && candidate.candidate) {
  31. const value = {type: 'candidate', candidate}
  32. wire({kind: 'rpc', value, target})
  33. }
  34. }
  35. rpc.ontrack = () => {
  36. const tracks = rpc.getReceivers().map(t => t.track)
  37. setTracks({source: target, tracks: tracks})
  38. }
  39. rpc.onconnectionstatechange = () => {
  40. if(rpc.connectionState === 'failed') {
  41. console.log(target, 'failed, retry!')
  42. wire({kind: 'rpc', value: {type: 'request'}, target})
  43. }
  44. }
  45. rpc.ondatachannel = ({channel}) => {
  46. datachannels[target] = channel
  47. datachannels[target].onmessage = ({data}) => console.log(data)
  48. // for testing purposes
  49. const msg = `rpc established from ${target} to ${State.username}`
  50. datachannels[target].send(msg)
  51. console.log(msg)
  52. }
  53. connections[target] = rpc
  54. if(State.username > target) {
  55. datachannels[target] = rpc.createDataChannel('test')
  56. datachannels[target].onmessage = ({data}) => console.log(data)
  57. signal({kind: 'rpc', value: {type: 'request'}, source: target})
  58. }
  59. }
  60. async function handlePeerInfo({source: target, value}) {
  61. const rpc = connections[target]
  62. if(!rpc) {
  63. return
  64. }
  65. const olds = rpc.getSenders().map(t => t.track)
  66. const news = getOwnTracks()
  67. rpc.getSenders().filter(s => !news.includes(s.track)).forEach(s => rpc.removeTrack(s))
  68. news.filter(track => !olds.includes(track)).forEach(t => t && rpc.addTrack(t))
  69. if(value.type === 'request') {
  70. const localOffer = await rpc.createOffer()
  71. await rpc.setLocalDescription(localOffer)
  72. wire({kind: 'rpc', value: localOffer, target})
  73. }
  74. else if(value.type === 'offer') {
  75. const remoteOffer = new RTCSessionDescription(value)
  76. await rpc.setRemoteDescription(remoteOffer)
  77. const localAnswer = await rpc.createAnswer()
  78. await rpc.setLocalDescription(localAnswer)
  79. wire({kind: 'rpc', value: localAnswer, target})
  80. }
  81. else if(value.type === 'answer') {
  82. const remoteAnswer = new RTCSessionDescription(value)
  83. await rpc.setRemoteDescription(remoteAnswer).catch(e => e)
  84. }
  85. else if(value.type === 'candidate') {
  86. const candidate = new RTCIceCandidate(value.candidate)
  87. await rpc.addIceCandidate(candidate).catch(e => e)
  88. }
  89. }
  90. function destroyConnection(username) {
  91. if(streams[username]) {
  92. streams[username].getTracks().forEach(t => t.stop())
  93. delete streams[username]
  94. }
  95. if(datachannels[username]) {
  96. datachannels[username].close()
  97. delete datachannels[username]
  98. }
  99. if(connections[username]) {
  100. connections[username].getReceivers().forEach(r => r.track.stop())
  101. connections[username].close()
  102. delete connections[username]
  103. }
  104. }
  105. addEventListener('tracks', (e) => setTracks(e.detail.value))
  106. addEventListener('rpc', (e) => handlePeerInfo(e.detail))
  107. addEventListener('join', (e) => createConnection(e.detail.value))
  108. addEventListener('leave', (e) => destroyConnection(e.detail.value))
  109. addEventListener('load', () => doNotLog.add('rpc'))