Advertisement
Chatenium

Untitled

Feb 5th, 2024 (edited)
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.16 KB | None | 0 0
  1. import { signal } from '@angular/core';
  2. import { websocketDef } from 'src/interfaces/interfaces';
  3. import { webSocket } from 'rxjs/webSocket';
  4. import { environment } from 'src/environments/environment.development';
  5.  
  6. export const Chats = signal<ChatService[]>([]);
  7. const ws = webSocket(`${environment.websocket_url}/chat/ws`)
  8.  
  9. export class ChatService {
  10. chatdata: Chat;
  11. peerconnections: PeerConnection[] = [];
  12. userid: string;
  13. peerid = Math.floor(Math.random() * 9999)
  14. constructor(chatdata: Chat, userid: string) {
  15. console.log(chatdata)
  16. this.chatdata = chatdata;
  17. this.userid = userid;
  18.  
  19. // Make user available
  20. ws.next({
  21. action: "makeUserAvailable",
  22. value: JSON.stringify({
  23. chatid: chatdata.chatid,
  24. peerid: this.peerid,
  25. })
  26. })
  27.  
  28. ws.subscribe(
  29. (message) => {
  30. let action = (message as websocketDef).action
  31.  
  32. switch (action) {
  33. case "peerids":
  34. let data = message as { peerids: number[] }
  35.  
  36. data.peerids.forEach((peerid) => {
  37. this.peerconnections.push(new PeerConnection(peerid, this.peerid, this.chatdata.chatid, true, null))
  38. })
  39. break;
  40.  
  41. case "chatOffer":
  42. console.log("Got offer")
  43. let offerData = message as offer;
  44.  
  45. let chat = this.peerconnections.find((conn) => conn.peerid == offerData.peerid);
  46.  
  47. if (chat && !this.amIPolite(this.peerid, offerData.peerid) && chat.status == "connected") {
  48. return;
  49. }
  50.  
  51. let peerChat = new PeerConnection(offerData.peerid, this.peerid, this.chatdata.chatid, false, offerData)
  52. if (!chat) {
  53. this.peerconnections.push(peerChat);
  54. }
  55. break;
  56.  
  57. case "chatAnswer":
  58. let answerData = message as answer;
  59.  
  60. let chatToApplyAnswer = this.peerconnections.find((conn) => conn.peerid == answerData.peerid);
  61.  
  62. if (chatToApplyAnswer) {
  63. chatToApplyAnswer.applyAnswer(answerData)
  64. }
  65. }
  66. }
  67. )
  68. }
  69.  
  70. amIPolite(peerid: number, remotePeerid: number): boolean {
  71. return peerid > remotePeerid;
  72. }
  73. }
  74.  
  75. class PeerConnection {
  76. config = {
  77. iceServers: [
  78. {
  79. urls: 'stun:stun.l.google.com:19302',
  80. },
  81. {
  82. urls: 'turn:213.181.206.131:3478',
  83. username: 'chatenium',
  84. credential: 'GeraErika01',
  85. },
  86. ],
  87. };
  88.  
  89. status: "initializing" | "connecting" | "connected" | "failed" = "initializing";
  90. error = "";
  91. peerconnection = new RTCPeerConnection(this.config);
  92. chatid: string;
  93. datachannel: RTCDataChannel | null = null;
  94. myPeerid: number;
  95. peerid: number;
  96.  
  97. constructor(peerid: number, myPeerid: number, chatid: string, offerer: boolean, offerData: offer | null) {
  98. this.myPeerid = myPeerid;
  99. this.peerid = peerid;
  100. this.chatid = chatid;
  101.  
  102. // Connect peers
  103. if (offerer) {
  104. this.connect();
  105. } else {
  106. if (!offerData) {
  107. return
  108. }
  109.  
  110. this.answer(offerData);
  111. }
  112.  
  113. this.peerconnection.ondatachannel = e => {
  114. console.log("Got datachannel!")
  115. }
  116.  
  117. this.peerconnection.onicecandidate = e => {
  118. console.log("Ice")
  119. }
  120.  
  121. this.peerconnection.onconnectionstatechange = e => {
  122. console.log(e)
  123. }
  124. }
  125.  
  126. async connect() {
  127. let datachannel = this.peerconnection.createDataChannel("DmMessage");
  128.  
  129. datachannel.onopen = e => {
  130. console.log("Offer: DataChannel Open")
  131. }
  132.  
  133. this.datachannel = datachannel;
  134.  
  135. let offer = await this.peerconnection.createOffer()
  136. await this.peerconnection.setLocalDescription(offer)
  137.  
  138. ws.next({
  139. action: "chatOffer",
  140. value: JSON.stringify({
  141. peerid: this.myPeerid,
  142. offer: JSON.stringify(offer),
  143. action: "chatOffer",
  144. chatid: this.chatid,
  145. })
  146. })
  147.  
  148. // Listen //
  149. setTimeout(() => {
  150. if (this.status != "connected") {
  151. this.status = "failed";
  152. this.error = "timeout"
  153. }
  154. }, 10000);
  155. }
  156.  
  157. async answer(offerData: offer) {
  158. console.log("Answer applied")
  159. this.peerconnection = new RTCPeerConnection(this.config)
  160.  
  161. await this.peerconnection.setRemoteDescription(JSON.parse(offerData.offer))
  162.  
  163. let answer = await this.peerconnection.createAnswer();
  164. await this.peerconnection.setLocalDescription(answer);
  165.  
  166. ws.next({
  167. action: 'chatAnswer',
  168. value: JSON.stringify({
  169. peerid: this.myPeerid,
  170. chatid: this.chatid,
  171. answer: JSON.stringify(answer),
  172. action: 'chatAnswer',
  173. }),
  174. });
  175. }
  176.  
  177. async applyAnswer(data: answer) {
  178. await this.peerconnection.setRemoteDescription(JSON.parse(data.answer))
  179. }
  180. }
  181.  
  182. export interface Chat {
  183. chatid: string;
  184. displayName: string;
  185. notif: number;
  186. pfp: string;
  187. userid: string;
  188. username: string;
  189. }
  190.  
  191. interface offer {
  192. chatid: string;
  193. offer: string;
  194. peerid: number;
  195. }
  196.  
  197. interface answer {
  198. answer: string;
  199. peerid: number;
  200. }
  201.  
  202. interface iceCandData {
  203. peerid: number;
  204. action: string;
  205. icecandidate: string;
  206. chatid: string;
  207. }
  208.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement