選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

rpc.js 3.6KB

5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
5年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. const allRPCs = {}
  2. // https://stackoverflow.com/a/2117523
  3. function uuidv4() {
  4. return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
  5. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  6. )
  7. }
  8. function rpcStatusCheck() {
  9. console.table(Object.values(allRPCs).map(({target, kind, rpc}) =>
  10. ({target, kind, status: rpc.iceConnectionState})
  11. ))
  12. }
  13. function rpcCleanUp(kind, target) {
  14. for([uid, info] of Object.entries(allRPCs)) {
  15. if(info.kind === kind && info.target === target) {
  16. info.rpc.close()
  17. delete allRPCs[uid]
  18. }
  19. }
  20. }
  21. addEventListener('rpc-needed', ({detail}) => {
  22. const {kind, target} = detail.value
  23. const isInitiatedLocally = !detail.source
  24. const uid = detail.value.uid || uuidv4()
  25. const rpc = new RTCPeerConnection(rpcConfig)
  26. rpc.onicecandidate = ({candidate}) => {
  27. if(candidate && candidate.candidate) {
  28. const cand = JSON.parse(JSON.stringify(candidate))
  29. wire({kind: 'ice-candidate', value: {...cand, uid}, target})
  30. }
  31. }
  32. rpc.ontrack = ({streams: [stream]}) => {
  33. stream.getTracks().forEach(track => {
  34. allRPCs[uid].receiver.addTrack(track, stream)
  35. })
  36. }
  37. rpc.oniceconnectionstatechange = (e) => {
  38. console.log(`${target} ${kind} ${rpc.iceConnectionState}`)
  39. }
  40. rpc.onnegotiationneeded = (e) => {
  41. // if(isInitiatedLocally) {
  42. // signal({kind: 'rpc-initiate', value: {uid}})
  43. // }
  44. }
  45. rpcCleanUp(kind, target)
  46. allRPCs[uid] = {kind, target, rpc, isInitiatedLocally}
  47. signal({kind: 'rpc-new', value: {kind, target, uid}})
  48. if(isInitiatedLocally) {
  49. wire({kind: 'rpc-needed', value: {kind, target: State.username, uid}, target})
  50. }
  51. })
  52. addEventListener('rpc-setup', async ({detail}) => {
  53. const {uid, sender, receiver} = detail.value
  54. const {rpc, isInitiatedLocally, hasOffer} = allRPCs[uid]
  55. allRPCs[uid].sender = sender
  56. allRPCs[uid].receiver = receiver
  57. if(sender) {
  58. sender.getTracks().forEach(tr => rpc.addTrack(tr, sender))
  59. }
  60. allRPCs[uid].isSetup = true
  61. if(isInitiatedLocally) {
  62. signal({kind: 'rpc-initiate', value: {uid}})
  63. }
  64. else if(hasOffer) {
  65. signal({kind: 'rpc-respond', value: {uid}})
  66. }
  67. })
  68. addEventListener('rpc-initiate', async({detail}) => {
  69. const {uid} = detail.value
  70. const {rpc, target} = allRPCs[uid]
  71. const localOffer = await rpc.createOffer()
  72. await rpc.setLocalDescription(localOffer)
  73. wire({kind: 'rpc-offer', value: {...localOffer, uid}, target})
  74. })
  75. addEventListener('rpc-offer', async ({detail}) => {
  76. const {uid} = detail.value
  77. const {rpc, isSetup} = allRPCs[uid]
  78. await rpc.setRemoteDescription(detail.value)
  79. allRPCs[uid].hasOffer = true
  80. if(isSetup) {
  81. signal({kind: 'rpc-respond', value: {uid}})
  82. }
  83. })
  84. addEventListener('rpc-respond', async({detail}) => {
  85. const {uid} = detail.value
  86. const {rpc, target} = allRPCs[uid]
  87. const localAnswer = await rpc.createAnswer()
  88. await rpc.setLocalDescription(localAnswer)
  89. wire({kind: 'rpc-answer', value: {...localAnswer, uid}, target})
  90. })
  91. addEventListener('rpc-answer', async ({detail}) => {
  92. const {uid} = detail.value
  93. await allRPCs[uid].rpc.setRemoteDescription(detail.value)
  94. })
  95. addEventListener('ice-candidate', async ({detail}) => {
  96. const {uid} = detail.value
  97. await allRPCs[uid].rpc.addIceCandidate(detail.value)
  98. })
  99. addEventListener('load', () => {
  100. doNotLog.add('rpc-needed')
  101. doNotLog.add('rpc-offer')
  102. doNotLog.add('rpc-answer')
  103. doNotLog.add('ice-candidate')
  104. })