├── .gitignore ├── LICENSE ├── README.md ├── nodejsclient ├── assets │ └── js │ │ ├── api.js │ │ ├── enhancesdp.js │ │ ├── index.js │ │ └── socket.io.js └── index.html └── nodejsserver ├── .gitignore ├── assets └── js │ └── socket.io.js ├── package-lock.json ├── package.json ├── public └── beep.mp3 └── videochat.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | nodejsserver/node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wowza-webrtc-group-call-and-chat 2 | Wowza Webrtc Group Call Sample, it's n to n webrtc sample application with chat room feautures. 3 | 4 | You can join existing room or create a new room. 5 | 6 | Simple webrtc group chat application that using Wowza as SFU 7 | 8 | ![Room Page](https://image.prntscr.com/image/u5-KbF4HRWS1EA5_9ODcxA.png) 9 | 10 | 11 | Wowza Streaming Engine installation 12 | --------------------------------- 13 | Download the Wowza Streaming Engine from [WOWZA STREAMING ENGINE] 14 | 15 | You can find webrtc installation guide on wowza docs [WOWZA WEBRTC INSTALL] 16 | 17 | 18 | INSTALLATION 19 | --------------------------------- 20 | ``` 21 | git clone git@github.com:Lethea/wowza-webrtc-group-call-and-chat.git 22 | ``` 23 | 24 | There is two project 25 | 1. Nodejs Client : This includes index.html + wowza webrtc websocket connect api ( api.js ) 26 | * Wowza Streaming Engine WEBRTC websocket api send publish / play request to the wowza streaming engine 27 | * Listen wowza webrtc websocket response 28 | * Connect Nodejs server for chat room operation such as login / disconnect 29 | 30 | 2. Nodejs Server : This provide login to chat room, listen events, messaging 31 | * This is for chatroom application 32 | * Allows user to login to the given room 33 | * Allows user to public chat 34 | * Listen login / disconnect event 35 | 36 | On Nodejs Server Run Following Command 37 | ``` 38 | 39 | npm install --save express 40 | 41 | npm install --save socket.io 42 | 43 | or basically 44 | 45 | npm install 46 | 47 | ``` 48 | 49 | CONFIGURATION 50 | ---------------------------------- 51 | As you know, webrtc isn't allowed when the page is not safe ( https ) 52 | 53 | Please install ssl to your wowza streaming engine or proxy pass the request to the wowza webrtc websocket 54 | 55 | Change the Wowza Webrtc websocket url in _**nodeclientjs/assets/js/api.js**_ with your own 56 | 57 | ``` 58 | var wsURL = "wss://59cb91f751ff5.streamlock.net:9443/webrtc-session.json"; 59 | ``` 60 | 61 | Change the nodejs websocket url in _**nodejsclient/index.html**_ 62 | 63 | ``` 64 | var socketIoConnectionUrl = "https://10.6.1.136"; 65 | ``` 66 | *By default, the nodejs application run on port 3000, 67 | define ssl to nodejs or proxy pass the 443 with socket.io path to 3000* 68 | 69 | CONNECT TO CHAT ROOM 70 | ----------------------------- 71 | 72 | ``` 73 | cd nodejsserver 74 | 75 | node videochat.js 76 | ``` 77 | 78 | Open your nodejsclient with https with browser ( chrome preferred ) 79 | 80 | ```` 81 | https://your_web_server_ip/nodejsclient/index.html 82 | ```` 83 | 84 | Login Page 85 | 86 | ![Login Page](https://image.prntscr.com/image/i0Xlxv4dTZa39FT3ywhIzA.png) 87 | 88 | * Enter your nickname (English Characters & Numbers without space required) 89 | * Enter your Room Name (English Characters & Numbers without space required) 90 | 91 | ![Room Page](https://image.prntscr.com/image/u5-KbF4HRWS1EA5_9ODcxA.png) 92 | 93 | ![Wowza Image](https://image.prntscr.com/image/gy_wmKXTSQWPbgQ3Y-GHbg.png) 94 | 95 | Note 96 | ------------- 97 | For proxy pass you can use nginx as well 98 | 99 | Features 100 | ------------- 101 | - [x] Login 102 | - [x] Dynamic Chat Room 103 | - [x] Text Chat 104 | - [x] Play / Publish Implementation 105 | - [x] PeerConnection / Icecandidate etc webrtc stuff implemented 106 | - [ ] Selecting Camera / Microphone 107 | - [ ] Publish Stream Button ( Now starting automatically ) 108 | - [ ] Webrtc Api Implementation for local user must be changed 109 | - [ ] External Player Link For Hls Playback 110 | - [ ] Typo Control 111 | - [ ] Test 112 | 113 | Contact 114 | ------------ 115 | ```` 116 | Mail : emre.karatasoglu@hotmail.com 117 | Phone / Whatsapp / Telegram : +90 532 346 67 79 118 | Donate : 1HxYXXDNQen9kDHjdjPrHkj1xS64fkENes ( BTC ) 119 | Ld8BNcvP69146jgT5hVbTzSsnL7q6WoUSg ( LTC ) 120 | 0x77935c829b0f12b05151ec7bce31d58a97f735e8 ( ETH ) 121 | ```` 122 | 123 | 124 | 125 | 126 | 127 | 128 | [WOWZA STREAMING ENGINE]:https://www.wowza.com/pricing/installer 129 | [WOWZA WEBRTC INSTALL]:https://www.wowza.com/docs/how-to-use-webrtc-with-wowza-streaming-engine 130 | -------------------------------------------------------------------------------- /nodejsclient/assets/js/api.js: -------------------------------------------------------------------------------- 1 | var wsURL = "wss://59cb91f751ff5.streamlock.net:9443/webrtc-session.json"; 2 | var application = "webrtc"; 3 | var wsConnection = null; 4 | var localUser = null; 5 | var localVideo = null; 6 | var peerConnectionConfig = {'iceServers': []}; 7 | var localStream = null; 8 | var peerConnections = []; 9 | var videoBitrate = 360; 10 | var audioBitrate = 64; 11 | var videoFrameRate = "29.97"; 12 | var players = []; 13 | 14 | 15 | /* 16 | * Browser get User Media 17 | * */ 18 | navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia; 19 | window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; 20 | window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate; 21 | window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription; 22 | 23 | /* 24 | * Browser get User Media 25 | * */ 26 | 27 | 28 | function openCameraAndMicrophone() { 29 | 30 | localVideo = document.getElementById('localVideo'); 31 | 32 | var constraints = 33 | { 34 | video: true, 35 | audio: true, 36 | }; 37 | 38 | if (navigator.mediaDevices.getUserMedia) { 39 | navigator.mediaDevices.getUserMedia(constraints).then(getUserMediaSuccess).catch(errorHandler); 40 | newAPI = false; 41 | } else if (navigator.getUserMedia) { 42 | navigator.getUserMedia(constraints, getUserMediaSuccess, errorHandler); 43 | } else { 44 | alert('Your browser does not support getUserMedia API'); 45 | } 46 | } 47 | 48 | /* 49 | * GET USER MEDIA CALL THIS WITH STREAM 50 | * */ 51 | function getUserMediaSuccess(stream) { 52 | console.log("getUserMediaSuccess: " + stream); 53 | localStream = stream; 54 | try { 55 | localVideo.srcObject = stream; 56 | } catch (error) { 57 | localVideo.src = window.URL.createObjectURL(stream); 58 | } 59 | connectWebSocket(wsURL).then(function (wsConnectionFrom) { 60 | 61 | listenWebSocketEvents(); 62 | 63 | peerConnections[localUser] = new RTCPeerConnection(peerConnectionConfig); 64 | peerConnections[localUser].onicecandidate = localIceCandidate; 65 | 66 | peerConnections[localUser].addStream(localStream); 67 | peerConnections[localUser].createOffer(gotLocalDescription, errorHandler); 68 | 69 | 70 | }); 71 | } 72 | 73 | function errorHandler(error) { 74 | console.log(error); 75 | } 76 | 77 | 78 | /* 79 | * 80 | * Connect Wowza WebSocket 81 | * 82 | * */ 83 | 84 | function connectWebSocket(url) { 85 | return new Promise(function (resolve, reject) { 86 | if (wsConnection == null) { 87 | console.log("NO WEBSOCKET WE GONNA GENERATE NEW ONE") 88 | wsConnection = new WebSocket(url); 89 | wsConnection.binaryType = 'arraybuffer'; 90 | 91 | wsConnection.onopen = function () { 92 | console.log("WS CONNECTION OPENED"); 93 | resolve(wsConnection); 94 | } 95 | } else { 96 | console.log("USING EXISTING WS"); 97 | resolve(wsConnection); 98 | } 99 | }) 100 | 101 | 102 | } 103 | 104 | function listenWebSocketEvents() { 105 | wsConnection.onmessage = function (evt) { 106 | console.log("Wowza Web Socket Response : " + evt.data); 107 | 108 | var msgJSON = JSON.parse(evt.data); 109 | 110 | var msgStatus = Number(msgJSON['status']); 111 | var msgCommand = msgJSON['command']; 112 | 113 | if (msgJSON.direction == "publish") { 114 | 115 | if (msgJSON.command == "sendOffer") { 116 | 117 | console.log("Send Offer Sdp Type Answer", msgJSON["sdp"]); 118 | 119 | peerConnections[localUser].setRemoteDescription(new RTCSessionDescription(msgJSON["sdp"]), function () { 120 | 121 | }, errorHandler) 122 | 123 | var iceCandidates = msgJSON['iceCandidates']; 124 | if (iceCandidates !== undefined) { 125 | for (var index in iceCandidates) { 126 | console.log('iceCandidates: ' + iceCandidates[index]); 127 | peerConnections[localUser].addIceCandidate(new RTCIceCandidate(iceCandidates[index])); 128 | } 129 | } 130 | 131 | } 132 | 133 | //wsConnection.close(); 134 | //wsConnection = null; 135 | 136 | 137 | } else if (msgJSON.direction == "play") { 138 | var remStreamName = msgJSON.streamInfo.streamName; 139 | var remSessionId = msgJSON.streamInfo.sessionId; 140 | 141 | if (msgCommand == "getOffer") { 142 | 143 | 144 | 145 | players[remStreamName].plSetRemoteDescription(new RTCSessionDescription(msgJSON.sdp),remSessionId); 146 | 147 | } else if (msgCommand == "sendResponse") { 148 | var iceCandidates = msgJSON['iceCandidates']; 149 | if (iceCandidates !== undefined) { 150 | for (var index in iceCandidates) { 151 | console.log(' sendResponse iceCandidates: ' + JSON.stringify(iceCandidates[index])); 152 | players[remStreamName].addIceCandidate(new RTCIceCandidate(iceCandidates[index])); 153 | } 154 | } 155 | } 156 | 157 | 158 | } 159 | 160 | } 161 | } 162 | 163 | 164 | function gotLocalDescription(description) { 165 | 166 | var enhanceData = new Object(); 167 | 168 | if (audioBitrate !== undefined) 169 | enhanceData.audioBitrate = Number(audioBitrate); 170 | if (videoBitrate !== undefined) 171 | enhanceData.videoBitrate = Number(videoBitrate); 172 | if (videoFrameRate !== undefined) 173 | enhanceData.videoFrameRate = Number(videoFrameRate); 174 | 175 | 176 | description.sdp = enhanceSDP(description.sdp, enhanceData); 177 | 178 | console.log('gotLocalDescription: ' + JSON.stringify({'sdp': description})); 179 | 180 | peerConnections[localUser].setLocalDescription(description, function () { 181 | let streamInfo = {applicationName: application, streamName: localUser, sessionId: "[empty]"} 182 | 183 | wsConnection.send('{"direction":"publish", "command":"sendOffer", "streamInfo":' + JSON.stringify(streamInfo) + ', "sdp":' + JSON.stringify(description) + ', "userData":' + JSON.stringify({}) + '}'); 184 | 185 | }, function () { 186 | console.log('set description error') 187 | }); 188 | 189 | } 190 | 191 | function localIceCandidate(event) { 192 | if (event.candidate != null) { 193 | console.log('localIceCandidate: ' + JSON.stringify({'ice': event.candidate})); 194 | } 195 | } 196 | 197 | function remoteIceCandidate(event) { 198 | if (event.candidate != null) { 199 | console.log('remoteIceCandidate: ' + JSON.stringify({'ice': event.candidate})); 200 | } 201 | } 202 | 203 | 204 | /* 205 | * START PLAYING 206 | * 207 | * */ 208 | 209 | 210 | function startPlay(streamName) { 211 | 212 | players[streamName] = new Player(streamName); 213 | 214 | 215 | connectWebSocket(wsURL).then(function (connectWebSocketResponse) { 216 | 217 | listenWebSocketEvents(); 218 | 219 | players[streamName].sendPlayOffer(streamName); 220 | 221 | }); 222 | 223 | 224 | } 225 | 226 | function closeStream(videoTag){ 227 | if(players[videoTag]) { 228 | players[videoTag].stop(); 229 | delete players[videoTag]; 230 | } 231 | } 232 | 233 | function Player(streamName) { 234 | 235 | var remoteVideo = document.getElementById(streamName); 236 | 237 | var remPeerConnection = new RTCPeerConnection(peerConnectionConfig); 238 | remPeerConnection.onicecandidate = remoteIceCandidate; 239 | remPeerConnection.onaddstream = gotRemoteStream; 240 | 241 | this.sendPlayOffer = sendPlayGetOffer; 242 | this.plSetRemoteDescription = plSetRemoteDescription ; 243 | this.addIceCandidate = addIceCandidate ; 244 | this.stop = stopStream; 245 | 246 | 247 | function stopStream(){ 248 | remPeerConnection.close(); 249 | } 250 | 251 | function addIceCandidate(candidate){ 252 | console.log("Player#addIceCandidate--"+streamName,candidate); 253 | remPeerConnection.addIceCandidate(candidate); 254 | } 255 | 256 | 257 | function plSetRemoteDescription(sdp, sessionId) { 258 | console.log("plSetRemoteDescription", sdp); 259 | remPeerConnection.setRemoteDescription(sdp).then(function () { 260 | return remPeerConnection.createAnswer(); 261 | }) 262 | .then(function (remoteDescription) { 263 | return remPeerConnection.setLocalDescription(remoteDescription); 264 | }) 265 | .then(function(){ 266 | let streamInfo = {applicationName: application, streamName: streamName, sessionId: sessionId}; 267 | wsConnection.send('{"direction":"play", "command":"sendResponse", "streamInfo":' + JSON.stringify(streamInfo) + ', "sdp":' + JSON.stringify(remPeerConnection.localDescription) + ', "userData":' + JSON.stringify({}) + '}'); 268 | 269 | }) 270 | } 271 | 272 | function remoteIceCandidate(event) { 273 | if (event.candidate != null) { 274 | console.log('remoteIceCandidate: ' + JSON.stringify({'ice': event.candidate})); 275 | } 276 | } 277 | 278 | function gotRemoteStream(event) { 279 | 280 | console.log('gotRemoteStream', event.stream); 281 | 282 | try { 283 | remoteVideo.srcObject = event.stream; 284 | } catch (error) { 285 | remoteVideo.src = window.URL.createObjectURL(event.stream); 286 | } 287 | 288 | } 289 | 290 | function sendPlayGetOffer(streamName) { 291 | 292 | let streamInfo = {applicationName: application, streamName: streamName, sessionId: "[empty]"}; 293 | 294 | console.log("sendPlayGetOffer: " + JSON.stringify(streamInfo)); 295 | 296 | wsConnection.send('{"direction":"play", "command":"getOffer", "streamInfo":' + JSON.stringify(streamInfo) + ', "userData":' + JSON.stringify({}) + '}'); 297 | 298 | } 299 | 300 | 301 | } 302 | -------------------------------------------------------------------------------- /nodejsclient/assets/js/enhancesdp.js: -------------------------------------------------------------------------------- 1 | var SDPOutput = new Object(); 2 | var videoChoice = "42e01f"; 3 | var audioChoice = "opus"; 4 | var videoIndex = -1; 5 | var audioIndex = -1; 6 | function addAudio(sdpStr, audioLine) 7 | { 8 | var sdpLines = sdpStr.split(/\r\n/); 9 | var sdpSection = 'header'; 10 | var hitMID = false; 11 | var sdpStrRet = ''; 12 | var done = false; 13 | 14 | for(var sdpIndex in sdpLines) 15 | { 16 | var sdpLine = sdpLines[sdpIndex]; 17 | 18 | if (sdpLine.length <= 0) 19 | continue; 20 | 21 | 22 | sdpStrRet +=sdpLine; 23 | sdpStrRet += '\r\n'; 24 | 25 | if ( 'a=rtcp-mux'.localeCompare(sdpLine) == 0 && done == false ) 26 | { 27 | sdpStrRet +=audioLine; 28 | done = true; 29 | } 30 | 31 | 32 | } 33 | return sdpStrRet; 34 | } 35 | 36 | function addVideo(sdpStr, videoLine) 37 | { 38 | var sdpLines = sdpStr.split(/\r\n/); 39 | var sdpSection = 'header'; 40 | var hitMID = false; 41 | var sdpStrRet = ''; 42 | var done = false; 43 | 44 | var rtcpSize = false; 45 | var rtcpMux = false; 46 | 47 | for(var sdpIndex in sdpLines) 48 | { 49 | var sdpLine = sdpLines[sdpIndex]; 50 | 51 | if (sdpLine.length <= 0) 52 | continue; 53 | 54 | if ( sdpLine.includes("a=rtcp-rsize") ) 55 | { 56 | rtcpSize = true; 57 | } 58 | 59 | if ( sdpLine.includes("a=rtcp-mux") ) 60 | { 61 | rtcpMux = true; 62 | } 63 | 64 | } 65 | 66 | for(var sdpIndex in sdpLines) 67 | { 68 | var sdpLine = sdpLines[sdpIndex]; 69 | 70 | sdpStrRet +=sdpLine; 71 | sdpStrRet += '\r\n'; 72 | 73 | if ( ('a=rtcp-rsize'.localeCompare(sdpLine) == 0 ) && done == false && rtcpSize == true) 74 | { 75 | sdpStrRet +=videoLine; 76 | done = true; 77 | } 78 | 79 | if ( 'a=rtcp-mux'.localeCompare(sdpLine) == 0 && done == true && rtcpSize == false) 80 | { 81 | sdpStrRet +=videoLine; 82 | done = true; 83 | } 84 | 85 | if ( 'a=rtcp-mux'.localeCompare(sdpLine) == 0 && done == false && rtcpSize == false ) 86 | { 87 | done = true; 88 | } 89 | 90 | } 91 | return sdpStrRet; 92 | } 93 | 94 | function enhanceSDP(sdpStr, enhanceData) 95 | { 96 | var sdpLines = sdpStr.split(/\r\n/); 97 | var sdpSection = 'header'; 98 | var hitMID = false; 99 | var sdpStrRet = ''; 100 | 101 | //console.log("Original SDP: "+sdpStr); 102 | 103 | // Firefox provides a reasonable SDP, Chrome is just odd 104 | // so we have to doing a little mundging to make it all work 105 | if ( !sdpStr.includes("THIS_IS_SDPARTA") || videoChoice.includes("VP9") ) 106 | { 107 | for(var sdpIndex in sdpLines) 108 | { 109 | var sdpLine = sdpLines[sdpIndex]; 110 | 111 | if (sdpLine.length <= 0) 112 | continue; 113 | 114 | var doneCheck = checkLine(sdpLine); 115 | if ( !doneCheck ) 116 | continue; 117 | 118 | sdpStrRet +=sdpLine; 119 | sdpStrRet += '\r\n'; 120 | 121 | } 122 | sdpStrRet = addAudio(sdpStrRet, deliverCheckLine(audioChoice,"audio")); 123 | sdpStrRet = addVideo(sdpStrRet, deliverCheckLine(videoChoice,"video")); 124 | sdpStr = sdpStrRet; 125 | sdpLines = sdpStr.split(/\r\n/); 126 | sdpStrRet = ''; 127 | } 128 | 129 | for(var sdpIndex in sdpLines) 130 | { 131 | var sdpLine = sdpLines[sdpIndex]; 132 | 133 | if (sdpLine.length <= 0) 134 | continue; 135 | 136 | if ( sdpLine.indexOf("m=audio") ==0 && audioIndex !=-1 ) 137 | { 138 | audioMLines = sdpLine.split(" "); 139 | sdpStrRet+=audioMLines[0]+" "+audioMLines[1]+" "+audioMLines[2]+" "+audioIndex+"\r\n"; 140 | continue; 141 | } 142 | 143 | if ( sdpLine.indexOf("m=video") == 0 && videoIndex !=-1 ) 144 | { 145 | audioMLines = sdpLine.split(" "); 146 | sdpStrRet+=audioMLines[0]+" "+audioMLines[1]+" "+audioMLines[2]+" "+videoIndex+"\r\n"; 147 | continue; 148 | } 149 | 150 | sdpStrRet += sdpLine; 151 | 152 | if (sdpLine.indexOf("m=audio") === 0) 153 | { 154 | sdpSection = 'audio'; 155 | hitMID = false; 156 | } 157 | else if (sdpLine.indexOf("m=video") === 0) 158 | { 159 | sdpSection = 'video'; 160 | hitMID = false; 161 | } 162 | else if (sdpLine.indexOf("a=rtpmap") == 0 ) 163 | { 164 | sdpSection = 'bandwidth'; 165 | hitMID = false; 166 | } 167 | 168 | if (sdpLine.indexOf("a=mid:") === 0 || sdpLine.indexOf("a=rtpmap") == 0 ) 169 | { 170 | if (!hitMID) 171 | { 172 | if ('audio'.localeCompare(sdpSection) == 0) 173 | { 174 | if (enhanceData.audioBitrate !== undefined) 175 | { 176 | sdpStrRet += '\r\nb=CT:' + (enhanceData.audioBitrate); 177 | sdpStrRet += '\r\nb=AS:' + (enhanceData.audioBitrate); 178 | } 179 | hitMID = true; 180 | } 181 | else if ('video'.localeCompare(sdpSection) == 0) 182 | { 183 | if (enhanceData.videoBitrate !== undefined) 184 | { 185 | sdpStrRet += '\r\nb=CT:' + (enhanceData.videoBitrate); 186 | sdpStrRet += '\r\nb=AS:' + (enhanceData.videoBitrate); 187 | if ( enhanceData.videoFrameRate !== undefined ) 188 | { 189 | sdpStrRet += '\r\na=framerate:'+enhanceData.videoFrameRate; 190 | } 191 | } 192 | hitMID = true; 193 | } 194 | else if ('bandwidth'.localeCompare(sdpSection) == 0 ) 195 | { 196 | var rtpmapID; 197 | rtpmapID = getrtpMapID(sdpLine); 198 | if ( rtpmapID !== null ) 199 | { 200 | var match = rtpmapID[2].toLowerCase(); 201 | if ( ('vp9'.localeCompare(match) == 0 ) || ('vp8'.localeCompare(match) == 0 ) || ('h264'.localeCompare(match) == 0 ) || 202 | ('red'.localeCompare(match) == 0 ) || ('ulpfec'.localeCompare(match) == 0 ) || ('rtx'.localeCompare(match) == 0 ) ) 203 | { 204 | if (enhanceData.videoBitrate !== undefined) 205 | { 206 | sdpStrRet+='\r\na=fmtp:'+rtpmapID[1]+' x-google-min-bitrate='+(enhanceData.videoBitrate)+';x-google-max-bitrate='+(enhanceData.videoBitrate); 207 | } 208 | } 209 | 210 | if ( ('opus'.localeCompare(match) == 0 ) || ('isac'.localeCompare(match) == 0 ) || ('g722'.localeCompare(match) == 0 ) || ('pcmu'.localeCompare(match) == 0 ) || 211 | ('pcma'.localeCompare(match) == 0 ) || ('cn'.localeCompare(match) == 0 )) 212 | { 213 | if (enhanceData.audioBitrate !== undefined) 214 | { 215 | sdpStrRet+='\r\na=fmtp:'+rtpmapID[1]+' x-google-min-bitrate='+(enhanceData.audioBitrate)+';x-google-max-bitrate='+(enhanceData.audioBitrate); 216 | } 217 | } 218 | } 219 | } 220 | } 221 | } 222 | sdpStrRet += '\r\n'; 223 | } 224 | // console.log("Resuling SDP: "+sdpStrRet); 225 | return sdpStrRet; 226 | } 227 | 228 | function deliverCheckLine(profile,type) 229 | { 230 | var outputString = ""; 231 | for(var line in SDPOutput) 232 | { 233 | var lineInUse = SDPOutput[line]; 234 | outputString+=line; 235 | if ( lineInUse.includes(profile) ) 236 | { 237 | if ( profile.includes("VP9") || profile.includes("VP8")) 238 | { 239 | var output = ""; 240 | var outputs = lineInUse.split(/\r\n/); 241 | for(var position in outputs) 242 | { 243 | var transport = outputs[position]; 244 | if (transport.indexOf("transport-cc") !== -1 || transport.indexOf("goog-remb") !== -1 || transport.indexOf("nack") !== -1) 245 | { 246 | continue; 247 | } 248 | output+=transport; 249 | output+="\r\n"; 250 | } 251 | 252 | if (type.includes("audio") ) 253 | { 254 | audioIndex = line; 255 | } 256 | 257 | if (type.includes("video") ) 258 | { 259 | videoIndex = line; 260 | } 261 | 262 | return output; 263 | } 264 | if (type.includes("audio") ) 265 | { 266 | audioIndex = line; 267 | } 268 | 269 | if (type.includes("video") ) 270 | { 271 | videoIndex = line; 272 | } 273 | return lineInUse; 274 | } 275 | } 276 | return outputString; 277 | } 278 | 279 | function checkLine(line) 280 | { 281 | if ( line.startsWith("a=rtpmap") || line.startsWith("a=rtcp-fb") || line.startsWith("a=fmtp")) 282 | { 283 | var res = line.split(":"); 284 | 285 | if ( res.length>1 ) 286 | { 287 | var number = res[1].split(" "); 288 | if ( !isNaN(number[0]) ) 289 | { 290 | if ( !number[1].startsWith("http") && !number[1].startsWith("ur") ) 291 | { 292 | var currentString = SDPOutput[number[0]]; 293 | if (!currentString) 294 | { 295 | currentString = ""; 296 | } 297 | currentString+=line+"\r\n"; 298 | SDPOutput[number[0]]=currentString; 299 | return false; 300 | } 301 | } 302 | } 303 | } 304 | 305 | return true; 306 | } 307 | 308 | function getrtpMapID(line) 309 | { 310 | var findid = new RegExp('a=rtpmap:(\\d+) (\\w+)/(\\d+)'); 311 | var found = line.match(findid); 312 | return (found && found.length >= 3) ? found: null; 313 | } 314 | -------------------------------------------------------------------------------- /nodejsclient/assets/js/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lethea/wowza-webrtc-group-call-and-chat/19b11b897c9efa4923f4a69693d1cda808f419c2/nodejsclient/assets/js/index.js -------------------------------------------------------------------------------- /nodejsclient/assets/js/socket.io.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Socket.IO v2.2.0 3 | * (c) 2014-2018 Guillermo Rauch 4 | * Released under the MIT License. 5 | */ 6 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t,e){"object"===("undefined"==typeof t?"undefined":o(t))&&(e=t,t=void 0),e=e||{};var n,r=i(t),s=r.source,u=r.id,h=r.path,f=p[u]&&h in p[u].nsps,l=e.forceNew||e["force new connection"]||!1===e.multiplex||f;return l?(c("ignoring socket cache for %s",s),n=a(s,e)):(p[u]||(c("new io instance for %s",s),p[u]=a(s,e)),n=p[u]),r.query&&!e.query&&(e.query=r.query),n.socket(r.path,e)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=n(1),s=n(7),a=n(12),c=n(3)("socket.io-client");t.exports=e=r;var p=e.managers={};e.protocol=s.protocol,e.connect=r,e.Manager=n(12),e.Socket=n(36)},function(t,e,n){"use strict";function r(t,e){var n=t;e=e||"undefined"!=typeof location&&location,null==t&&(t=e.protocol+"//"+e.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?e.protocol+t:e.host+t),/^(https?|wss?):\/\//.test(t)||(i("protocol-less url %s",t),t="undefined"!=typeof e?e.protocol+"//"+t:"https://"+t),i("parse %s",t),n=o(t)),n.port||(/^(http|ws)$/.test(n.protocol)?n.port="80":/^(http|ws)s$/.test(n.protocol)&&(n.port="443")),n.path=n.path||"/";var r=n.host.indexOf(":")!==-1,s=r?"["+n.host+"]":n.host;return n.id=n.protocol+"://"+s+":"+n.port,n.href=n.protocol+"://"+s+(e&&e.port===n.port?"":":"+n.port),n}var o=n(2),i=n(3)("socket.io-client:url");t.exports=r},function(t,e){var n=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,r=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s=n.exec(t||""),a={},c=14;c--;)a[r[c]]=s[c]||"";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,":"),a.authority=a.authority.replace("[","").replace("]","").replace(/;/g,":"),a.ipv6uri=!0),a}},function(t,e,n){(function(r){function o(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"==typeof navigator||!navigator.userAgent||!navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))&&("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))}function i(t){var n=this.useColors;if(t[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+t[0]+(n?"%c ":" ")+"+"+e.humanize(this.diff),n){var r="color: "+this.color;t.splice(1,0,r,"color: inherit");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,function(t){"%%"!==t&&(o++,"%c"===t&&(i=o))}),t.splice(i,0,r)}}function s(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function a(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(n){}}function c(){var t;try{t=e.storage.debug}catch(n){}return!t&&"undefined"!=typeof r&&"env"in r&&(t=r.env.DEBUG),t}function p(){try{return window.localStorage}catch(t){}}e=t.exports=n(5),e.log=s,e.formatArgs=i,e.save=a,e.load=c,e.useColors=o,e.storage="undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage?chrome.storage.local:p(),e.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},e.enable(c())}).call(e,n(4))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(h===clearTimeout)return clearTimeout(t);if((h===r||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(t);try{return h(t)}catch(e){try{return h.call(null,t)}catch(e){return h.call(this,t)}}}function s(){y&&l&&(y=!1,l.length?d=l.concat(d):m=-1,d.length&&a())}function a(){if(!y){var t=o(s);y=!0;for(var e=d.length;e;){for(l=d,d=[];++m1)for(var n=1;n100)){var e=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(e){var n=parseFloat(e[1]),r=(e[2]||"ms").toLowerCase();switch(r){case"years":case"year":case"yrs":case"yr":case"y":return n*u;case"days":case"day":case"d":return n*p;case"hours":case"hour":case"hrs":case"hr":case"h":return n*c;case"minutes":case"minute":case"mins":case"min":case"m":return n*a;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}function r(t){return t>=p?Math.round(t/p)+"d":t>=c?Math.round(t/c)+"h":t>=a?Math.round(t/a)+"m":t>=s?Math.round(t/s)+"s":t+"ms"}function o(t){return i(t,p,"day")||i(t,c,"hour")||i(t,a,"minute")||i(t,s,"second")||t+" ms"}function i(t,e,n){if(!(t0)return n(t);if("number"===i&&isNaN(t)===!1)return e["long"]?o(t):r(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e,n){function r(){}function o(t){var n=""+t.type;if(e.BINARY_EVENT!==t.type&&e.BINARY_ACK!==t.type||(n+=t.attachments+"-"),t.nsp&&"/"!==t.nsp&&(n+=t.nsp+","),null!=t.id&&(n+=t.id),null!=t.data){var r=i(t.data);if(r===!1)return g;n+=r}return f("encoded %j as %s",t,n),n}function i(t){try{return JSON.stringify(t)}catch(e){return!1}}function s(t,e){function n(t){var n=d.deconstructPacket(t),r=o(n.packet),i=n.buffers;i.unshift(r),e(i)}d.removeBlobs(t,n)}function a(){this.reconstructor=null}function c(t){var n=0,r={type:Number(t.charAt(0))};if(null==e.types[r.type])return h("unknown packet type "+r.type);if(e.BINARY_EVENT===r.type||e.BINARY_ACK===r.type){for(var o="";"-"!==t.charAt(++n)&&(o+=t.charAt(n),n!=t.length););if(o!=Number(o)||"-"!==t.charAt(n))throw new Error("Illegal attachments");r.attachments=Number(o)}if("/"===t.charAt(n+1))for(r.nsp="";++n;){var i=t.charAt(n);if(","===i)break;if(r.nsp+=i,n===t.length)break}else r.nsp="/";var s=t.charAt(n+1);if(""!==s&&Number(s)==s){for(r.id="";++n;){var i=t.charAt(n);if(null==i||Number(i)!=i){--n;break}if(r.id+=t.charAt(n),n===t.length)break}r.id=Number(r.id)}if(t.charAt(++n)){var a=p(t.substr(n)),c=a!==!1&&(r.type===e.ERROR||y(a));if(!c)return h("invalid payload");r.data=a}return f("decoded %s as %j",t,r),r}function p(t){try{return JSON.parse(t)}catch(e){return!1}}function u(t){this.reconPack=t,this.buffers=[]}function h(t){return{type:e.ERROR,data:"parser error: "+t}}var f=n(3)("socket.io-parser"),l=n(8),d=n(9),y=n(10),m=n(11);e.protocol=4,e.types=["CONNECT","DISCONNECT","EVENT","ACK","ERROR","BINARY_EVENT","BINARY_ACK"],e.CONNECT=0,e.DISCONNECT=1,e.EVENT=2,e.ACK=3,e.ERROR=4,e.BINARY_EVENT=5,e.BINARY_ACK=6,e.Encoder=r,e.Decoder=a;var g=e.ERROR+'"encode error"';r.prototype.encode=function(t,n){if(f("encoding packet %j",t),e.BINARY_EVENT===t.type||e.BINARY_ACK===t.type)s(t,n);else{var r=o(t);n([r])}},l(a.prototype),a.prototype.add=function(t){var n;if("string"==typeof t)n=c(t),e.BINARY_EVENT===n.type||e.BINARY_ACK===n.type?(this.reconstructor=new u(n),0===this.reconstructor.reconPack.attachments&&this.emit("decoded",n)):this.emit("decoded",n);else{if(!m(t)&&!t.base64)throw new Error("Unknown type: "+t);if(!this.reconstructor)throw new Error("got binary data when not reconstructing a packet");n=this.reconstructor.takeBinaryData(t),n&&(this.reconstructor=null,this.emit("decoded",n))}},a.prototype.destroy=function(){this.reconstructor&&this.reconstructor.finishedReconstruction()},u.prototype.takeBinaryData=function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=d.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null},u.prototype.finishedReconstruction=function(){this.reconPack=null,this.buffers=[]}},function(t,e,n){function r(t){if(t)return o(t)}function o(t){for(var e in r.prototype)t[e]=r.prototype[e];return t}t.exports=r,r.prototype.on=r.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},r.prototype.once=function(t,e){function n(){this.off(t,n),e.apply(this,arguments)}return n.fn=e,this.on(t,n),this},r.prototype.off=r.prototype.removeListener=r.prototype.removeAllListeners=r.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var r,o=0;o0&&!this.encoding){var t=this.packetBuffer.shift();this.packet(t)}},r.prototype.cleanup=function(){h("cleanup");for(var t=this.subs.length,e=0;e=this._reconnectionAttempts)h("reconnect failed"),this.backoff.reset(),this.emitAll("reconnect_failed"),this.reconnecting=!1;else{var e=this.backoff.duration();h("will wait %dms before reconnect attempt",e),this.reconnecting=!0;var n=setTimeout(function(){t.skipReconnect||(h("attempting reconnect"),t.emitAll("reconnect_attempt",t.backoff.attempts),t.emitAll("reconnecting",t.backoff.attempts),t.skipReconnect||t.open(function(e){e?(h("reconnect attempt error"),t.reconnecting=!1,t.reconnect(),t.emitAll("reconnect_error",e.data)):(h("reconnect success"),t.onreconnect())}))},e);this.subs.push({destroy:function(){clearTimeout(n)}})}},r.prototype.onreconnect=function(){var t=this.backoff.attempts;this.reconnecting=!1,this.backoff.reset(),this.updateSocketIds(),this.emitAll("reconnect",t)}},function(t,e,n){t.exports=n(14),t.exports.parser=n(21)},function(t,e,n){function r(t,e){return this instanceof r?(e=e||{},t&&"object"==typeof t&&(e=t,t=null),t?(t=u(t),e.hostname=t.host,e.secure="https"===t.protocol||"wss"===t.protocol,e.port=t.port,t.query&&(e.query=t.query)):e.host&&(e.hostname=u(e.host).host),this.secure=null!=e.secure?e.secure:"undefined"!=typeof location&&"https:"===location.protocol,e.hostname&&!e.port&&(e.port=this.secure?"443":"80"),this.agent=e.agent||!1,this.hostname=e.hostname||("undefined"!=typeof location?location.hostname:"localhost"),this.port=e.port||("undefined"!=typeof location&&location.port?location.port:this.secure?443:80),this.query=e.query||{},"string"==typeof this.query&&(this.query=h.decode(this.query)),this.upgrade=!1!==e.upgrade,this.path=(e.path||"/engine.io").replace(/\/$/,"")+"/",this.forceJSONP=!!e.forceJSONP,this.jsonp=!1!==e.jsonp,this.forceBase64=!!e.forceBase64,this.enablesXDR=!!e.enablesXDR,this.timestampParam=e.timestampParam||"t",this.timestampRequests=e.timestampRequests,this.transports=e.transports||["polling","websocket"],this.transportOptions=e.transportOptions||{},this.readyState="",this.writeBuffer=[],this.prevBufferLen=0,this.policyPort=e.policyPort||843,this.rememberUpgrade=e.rememberUpgrade||!1,this.binaryType=null,this.onlyBinaryUpgrades=e.onlyBinaryUpgrades,this.perMessageDeflate=!1!==e.perMessageDeflate&&(e.perMessageDeflate||{}),!0===this.perMessageDeflate&&(this.perMessageDeflate={}),this.perMessageDeflate&&null==this.perMessageDeflate.threshold&&(this.perMessageDeflate.threshold=1024),this.pfx=e.pfx||null,this.key=e.key||null,this.passphrase=e.passphrase||null,this.cert=e.cert||null,this.ca=e.ca||null,this.ciphers=e.ciphers||null,this.rejectUnauthorized=void 0===e.rejectUnauthorized||e.rejectUnauthorized,this.forceNode=!!e.forceNode,this.isReactNative="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase(),("undefined"==typeof self||this.isReactNative)&&(e.extraHeaders&&Object.keys(e.extraHeaders).length>0&&(this.extraHeaders=e.extraHeaders),e.localAddress&&(this.localAddress=e.localAddress)),this.id=null,this.upgrades=null,this.pingInterval=null,this.pingTimeout=null,this.pingIntervalTimer=null,this.pingTimeoutTimer=null,void this.open()):new r(t,e)}function o(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}var i=n(15),s=n(8),a=n(3)("engine.io-client:socket"),c=n(35),p=n(21),u=n(2),h=n(29);t.exports=r,r.priorWebsocketSuccess=!1,s(r.prototype),r.protocol=p.protocol,r.Socket=r,r.Transport=n(20),r.transports=n(15),r.parser=n(21),r.prototype.createTransport=function(t){a('creating transport "%s"',t);var e=o(this.query);e.EIO=p.protocol,e.transport=t;var n=this.transportOptions[t]||{};this.id&&(e.sid=this.id);var r=new i[t]({query:e,socket:this,agent:n.agent||this.agent,hostname:n.hostname||this.hostname,port:n.port||this.port,secure:n.secure||this.secure,path:n.path||this.path,forceJSONP:n.forceJSONP||this.forceJSONP,jsonp:n.jsonp||this.jsonp,forceBase64:n.forceBase64||this.forceBase64,enablesXDR:n.enablesXDR||this.enablesXDR,timestampRequests:n.timestampRequests||this.timestampRequests,timestampParam:n.timestampParam||this.timestampParam,policyPort:n.policyPort||this.policyPort,pfx:n.pfx||this.pfx,key:n.key||this.key,passphrase:n.passphrase||this.passphrase,cert:n.cert||this.cert,ca:n.ca||this.ca,ciphers:n.ciphers||this.ciphers,rejectUnauthorized:n.rejectUnauthorized||this.rejectUnauthorized,perMessageDeflate:n.perMessageDeflate||this.perMessageDeflate,extraHeaders:n.extraHeaders||this.extraHeaders,forceNode:n.forceNode||this.forceNode,localAddress:n.localAddress||this.localAddress,requestTimeout:n.requestTimeout||this.requestTimeout,protocols:n.protocols||void 0,isReactNative:this.isReactNative});return r},r.prototype.open=function(){var t;if(this.rememberUpgrade&&r.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1)t="websocket";else{if(0===this.transports.length){var e=this;return void setTimeout(function(){e.emit("error","No transports available")},0)}t=this.transports[0]}this.readyState="opening";try{t=this.createTransport(t)}catch(n){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t)},r.prototype.setTransport=function(t){a("setting transport %s",t.name);var e=this;this.transport&&(a("clearing existing transport %s",this.transport.name),this.transport.removeAllListeners()),this.transport=t,t.on("drain",function(){e.onDrain()}).on("packet",function(t){e.onPacket(t)}).on("error",function(t){e.onError(t)}).on("close",function(){e.onClose("transport close")})},r.prototype.probe=function(t){function e(){if(f.onlyBinaryUpgrades){var e=!this.supportsBinary&&f.transport.supportsBinary;h=h||e}h||(a('probe transport "%s" opened',t),u.send([{type:"ping",data:"probe"}]),u.once("packet",function(e){if(!h)if("pong"===e.type&&"probe"===e.data){if(a('probe transport "%s" pong',t),f.upgrading=!0,f.emit("upgrading",u),!u)return;r.priorWebsocketSuccess="websocket"===u.name,a('pausing current transport "%s"',f.transport.name),f.transport.pause(function(){h||"closed"!==f.readyState&&(a("changing transport and sending upgrade packet"),p(),f.setTransport(u),u.send([{type:"upgrade"}]),f.emit("upgrade",u),u=null,f.upgrading=!1,f.flush())})}else{a('probe transport "%s" failed',t);var n=new Error("probe error");n.transport=u.name,f.emit("upgradeError",n)}}))}function n(){h||(h=!0,p(),u.close(),u=null)}function o(e){var r=new Error("probe error: "+e);r.transport=u.name,n(),a('probe transport "%s" failed because of error: %s',t,e),f.emit("upgradeError",r)}function i(){o("transport closed")}function s(){o("socket closed")}function c(t){u&&t.name!==u.name&&(a('"%s" works - aborting "%s"',t.name,u.name),n())}function p(){u.removeListener("open",e),u.removeListener("error",o),u.removeListener("close",i),f.removeListener("close",s),f.removeListener("upgrading",c)}a('probing transport "%s"',t);var u=this.createTransport(t,{probe:1}),h=!1,f=this;r.priorWebsocketSuccess=!1,u.once("open",e),u.once("error",o),u.once("close",i),this.once("close",s),this.once("upgrading",c),u.open()},r.prototype.onOpen=function(){if(a("socket open"),this.readyState="open",r.priorWebsocketSuccess="websocket"===this.transport.name,this.emit("open"),this.flush(),"open"===this.readyState&&this.upgrade&&this.transport.pause){a("starting upgrade probes");for(var t=0,e=this.upgrades.length;t1?{type:b[o],data:t.substring(1)}:{type:b[o]}:w}var i=new Uint8Array(t),o=i[0],s=f(t,1);return k&&"blob"===n&&(s=new k([s])),{type:b[o],data:s}},e.decodeBase64Packet=function(t,e){var n=b[t.charAt(0)];if(!p)return{type:n,data:{base64:!0,data:t.substr(1)}};var r=p.decode(t.substr(1));return"blob"===e&&k&&(r=new k([r])),{type:n,data:r}},e.encodePayload=function(t,n,r){function o(t){return t.length+":"+t}function i(t,r){e.encodePacket(t,!!s&&n,!1,function(t){r(null,o(t))})}"function"==typeof n&&(r=n,n=null);var s=h(t);return n&&s?k&&!g?e.encodePayloadAsBlob(t,r):e.encodePayloadAsArrayBuffer(t,r):t.length?void c(t,i,function(t,e){return r(e.join(""))}):r("0:")},e.decodePayload=function(t,n,r){if("string"!=typeof t)return e.decodePayloadAsBinary(t,n,r);"function"==typeof n&&(r=n,n=null);var o;if(""===t)return r(w,0,1);for(var i,s,a="",c=0,p=t.length;c0;){for(var s=new Uint8Array(o),a=0===s[0],c="",p=1;255!==s[p];p++){if(c.length>310)return r(w,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var u=f(o,0,c);if(a)try{u=String.fromCharCode.apply(null,new Uint8Array(u))}catch(h){var l=new Uint8Array(u);u="";for(var p=0;pr&&(n=r),e>=r||e>=n||0===r)return new ArrayBuffer(0);for(var o=new Uint8Array(t),i=new Uint8Array(n-e),s=e,a=0;s=55296&&e<=56319&&o65535&&(e-=65536,o+=d(e>>>10&1023|55296),e=56320|1023&e),o+=d(e);return o}function o(t,e){if(t>=55296&&t<=57343){if(e)throw Error("Lone surrogate U+"+t.toString(16).toUpperCase()+" is not a scalar value");return!1}return!0}function i(t,e){return d(t>>e&63|128)}function s(t,e){if(0==(4294967168&t))return d(t);var n="";return 0==(4294965248&t)?n=d(t>>6&31|192):0==(4294901760&t)?(o(t,e)||(t=65533),n=d(t>>12&15|224),n+=i(t,6)):0==(4292870144&t)&&(n=d(t>>18&7|240),n+=i(t,12),n+=i(t,6)),n+=d(63&t|128)}function a(t,e){e=e||{};for(var r,o=!1!==e.strict,i=n(t),a=i.length,c=-1,p="";++c=f)throw Error("Invalid byte index");var t=255&h[l];if(l++,128==(192&t))return 63&t;throw Error("Invalid continuation byte")}function p(t){var e,n,r,i,s;if(l>f)throw Error("Invalid byte index");if(l==f)return!1;if(e=255&h[l],l++,0==(128&e))return e;if(192==(224&e)){if(n=c(),s=(31&e)<<6|n,s>=128)return s;throw Error("Invalid continuation byte")}if(224==(240&e)){if(n=c(),r=c(),s=(15&e)<<12|n<<6|r,s>=2048)return o(s,t)?s:65533;throw Error("Invalid continuation byte")}if(240==(248&e)&&(n=c(),r=c(),i=c(),s=(7&e)<<18|n<<12|r<<6|i,s>=65536&&s<=1114111))return s;throw Error("Invalid UTF-8 detected")}function u(t,e){e=e||{};var o=!1!==e.strict;h=n(t),f=h.length,l=0;for(var i,s=[];(i=p(o))!==!1;)s.push(i);return r(s)}/*! https://mths.be/utf8js v2.1.2 by @mathias */ 8 | var h,f,l,d=String.fromCharCode;t.exports={version:"2.1.2",encode:a,decode:u}},function(t,e){!function(){"use strict";for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=new Uint8Array(256),r=0;r>2],i+=t[(3&r[n])<<4|r[n+1]>>4],i+=t[(15&r[n+1])<<2|r[n+2]>>6],i+=t[63&r[n+2]];return o%3===2?i=i.substring(0,i.length-1)+"=":o%3===1&&(i=i.substring(0,i.length-2)+"=="),i},e.decode=function(t){var e,r,o,i,s,a=.75*t.length,c=t.length,p=0;"="===t[t.length-1]&&(a--,"="===t[t.length-2]&&a--);var u=new ArrayBuffer(a),h=new Uint8Array(u);for(e=0;e>4,h[p++]=(15&o)<<4|i>>2,h[p++]=(3&i)<<6|63&s;return u}}()},function(t,e){function n(t){return t.map(function(t){if(t.buffer instanceof ArrayBuffer){var e=t.buffer;if(t.byteLength!==e.byteLength){var n=new Uint8Array(t.byteLength);n.set(new Uint8Array(e,t.byteOffset,t.byteLength)),e=n.buffer}return e}return t})}function r(t,e){e=e||{};var r=new i;return n(t).forEach(function(t){r.append(t)}),e.type?r.getBlob(e.type):r.getBlob()}function o(t,e){return new Blob(n(t),e||{})}var i="undefined"!=typeof i?i:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:"undefined"!=typeof MSBlobBuilder?MSBlobBuilder:"undefined"!=typeof MozBlobBuilder&&MozBlobBuilder,s=function(){try{var t=new Blob(["hi"]);return 2===t.size}catch(e){return!1}}(),a=s&&function(){try{var t=new Blob([new Uint8Array([1,2])]);return 2===t.size}catch(e){return!1}}(),c=i&&i.prototype.append&&i.prototype.getBlob;"undefined"!=typeof Blob&&(r.prototype=Blob.prototype,o.prototype=Blob.prototype),t.exports=function(){return s?a?Blob:o:c?r:void 0}()},function(t,e){e.encode=function(t){var e="";for(var n in t)t.hasOwnProperty(n)&&(e.length&&(e+="&"),e+=encodeURIComponent(n)+"="+encodeURIComponent(t[n]));return e},e.decode=function(t){for(var e={},n=t.split("&"),r=0,o=n.length;r0);return e}function r(t){var e=0;for(u=0;u';i=document.createElement(e)}catch(t){i=document.createElement("iframe"),i.name=o.iframeId,i.src="javascript:0"}i.id=o.iframeId,o.form.appendChild(i),o.iframe=i}var o=this;if(!this.form){var i,s=document.createElement("form"),a=document.createElement("textarea"),c=this.iframeId="eio_iframe_"+this.index;s.className="socketio",s.style.position="absolute",s.style.top="-1000px",s.style.left="-1000px",s.target=c,s.method="POST",s.setAttribute("accept-charset","utf-8"),a.name="d",s.appendChild(a),document.body.appendChild(s),this.form=s,this.area=a}this.form.action=this.uri(),r(),t=t.replace(u,"\\\n"),this.area.value=t.replace(p,"\\n");try{this.form.submit()}catch(h){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){"complete"===o.iframe.readyState&&n()}:this.iframe.onload=n}}).call(e,function(){return this}())},function(t,e,n){function r(t){var e=t&&t.forceBase64;e&&(this.supportsBinary=!1),this.perMessageDeflate=t.perMessageDeflate,this.usingBrowserWebSocket=o&&!t.forceNode,this.protocols=t.protocols,this.usingBrowserWebSocket||(l=i),s.call(this,t)}var o,i,s=n(20),a=n(21),c=n(29),p=n(30),u=n(31),h=n(3)("engine.io-client:websocket");if("undefined"==typeof self)try{i=n(34)}catch(f){}else o=self.WebSocket||self.MozWebSocket;var l=o||i;t.exports=r,p(r,s),r.prototype.name="websocket",r.prototype.supportsBinary=!0,r.prototype.doOpen=function(){if(this.check()){var t=this.uri(),e=this.protocols,n={agent:this.agent,perMessageDeflate:this.perMessageDeflate};n.pfx=this.pfx,n.key=this.key,n.passphrase=this.passphrase,n.cert=this.cert,n.ca=this.ca,n.ciphers=this.ciphers,n.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(n.headers=this.extraHeaders),this.localAddress&&(n.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket&&!this.isReactNative?e?new l(t,e):new l(t):new l(t,e,n)}catch(r){return this.emit("error",r)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType="nodebuffer"):this.ws.binaryType="arraybuffer",this.addEventListeners()}},r.prototype.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.onOpen()},this.ws.onclose=function(){t.onClose()},this.ws.onmessage=function(e){t.onData(e.data)},this.ws.onerror=function(e){t.onError("websocket error",e)}},r.prototype.write=function(t){function e(){n.emit("flush"),setTimeout(function(){n.writable=!0,n.emit("drain")},0)}var n=this;this.writable=!1;for(var r=t.length,o=0,i=r;o0&&t.jitter<=1?t.jitter:0,this.attempts=0}t.exports=n,n.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n}return 0|Math.min(t,this.max)},n.prototype.reset=function(){this.attempts=0},n.prototype.setMin=function(t){this.ms=t},n.prototype.setMax=function(t){this.max=t},n.prototype.setJitter=function(t){this.jitter=t}}])}); 9 | //# sourceMappingURL=socket.io.js.map 10 | -------------------------------------------------------------------------------- /nodejsclient/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 13 | 16 | 19 | 20 | 21 | 22 | 23 | Wowza Sample 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 49 | 50 | 51 | 52 | 53 |
54 | 61 |
62 |
63 |
64 |
65 |
66 | 82 |
83 |
84 |
85 | 88 | 92 | 93 | 108 |
109 | 110 | 111 | 112 | 113 | 114 | 124 | 125 | 213 | -------------------------------------------------------------------------------- /nodejsserver/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /nodejsserver/assets/js/socket.io.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Socket.IO v2.2.0 3 | * (c) 2014-2018 Guillermo Rauch 4 | * Released under the MIT License. 5 | */ 6 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t,e){"object"===("undefined"==typeof t?"undefined":o(t))&&(e=t,t=void 0),e=e||{};var n,r=i(t),s=r.source,u=r.id,h=r.path,f=p[u]&&h in p[u].nsps,l=e.forceNew||e["force new connection"]||!1===e.multiplex||f;return l?(c("ignoring socket cache for %s",s),n=a(s,e)):(p[u]||(c("new io instance for %s",s),p[u]=a(s,e)),n=p[u]),r.query&&!e.query&&(e.query=r.query),n.socket(r.path,e)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=n(1),s=n(7),a=n(12),c=n(3)("socket.io-client");t.exports=e=r;var p=e.managers={};e.protocol=s.protocol,e.connect=r,e.Manager=n(12),e.Socket=n(36)},function(t,e,n){"use strict";function r(t,e){var n=t;e=e||"undefined"!=typeof location&&location,null==t&&(t=e.protocol+"//"+e.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?e.protocol+t:e.host+t),/^(https?|wss?):\/\//.test(t)||(i("protocol-less url %s",t),t="undefined"!=typeof e?e.protocol+"//"+t:"https://"+t),i("parse %s",t),n=o(t)),n.port||(/^(http|ws)$/.test(n.protocol)?n.port="80":/^(http|ws)s$/.test(n.protocol)&&(n.port="443")),n.path=n.path||"/";var r=n.host.indexOf(":")!==-1,s=r?"["+n.host+"]":n.host;return n.id=n.protocol+"://"+s+":"+n.port,n.href=n.protocol+"://"+s+(e&&e.port===n.port?"":":"+n.port),n}var o=n(2),i=n(3)("socket.io-client:url");t.exports=r},function(t,e){var n=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,r=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s=n.exec(t||""),a={},c=14;c--;)a[r[c]]=s[c]||"";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,":"),a.authority=a.authority.replace("[","").replace("]","").replace(/;/g,":"),a.ipv6uri=!0),a}},function(t,e,n){(function(r){function o(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"==typeof navigator||!navigator.userAgent||!navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))&&("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))}function i(t){var n=this.useColors;if(t[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+t[0]+(n?"%c ":" ")+"+"+e.humanize(this.diff),n){var r="color: "+this.color;t.splice(1,0,r,"color: inherit");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,function(t){"%%"!==t&&(o++,"%c"===t&&(i=o))}),t.splice(i,0,r)}}function s(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function a(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(n){}}function c(){var t;try{t=e.storage.debug}catch(n){}return!t&&"undefined"!=typeof r&&"env"in r&&(t=r.env.DEBUG),t}function p(){try{return window.localStorage}catch(t){}}e=t.exports=n(5),e.log=s,e.formatArgs=i,e.save=a,e.load=c,e.useColors=o,e.storage="undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage?chrome.storage.local:p(),e.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},e.enable(c())}).call(e,n(4))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(h===clearTimeout)return clearTimeout(t);if((h===r||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(t);try{return h(t)}catch(e){try{return h.call(null,t)}catch(e){return h.call(this,t)}}}function s(){y&&l&&(y=!1,l.length?d=l.concat(d):m=-1,d.length&&a())}function a(){if(!y){var t=o(s);y=!0;for(var e=d.length;e;){for(l=d,d=[];++m1)for(var n=1;n100)){var e=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(e){var n=parseFloat(e[1]),r=(e[2]||"ms").toLowerCase();switch(r){case"years":case"year":case"yrs":case"yr":case"y":return n*u;case"days":case"day":case"d":return n*p;case"hours":case"hour":case"hrs":case"hr":case"h":return n*c;case"minutes":case"minute":case"mins":case"min":case"m":return n*a;case"seconds":case"second":case"secs":case"sec":case"s":return n*s;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}function r(t){return t>=p?Math.round(t/p)+"d":t>=c?Math.round(t/c)+"h":t>=a?Math.round(t/a)+"m":t>=s?Math.round(t/s)+"s":t+"ms"}function o(t){return i(t,p,"day")||i(t,c,"hour")||i(t,a,"minute")||i(t,s,"second")||t+" ms"}function i(t,e,n){if(!(t0)return n(t);if("number"===i&&isNaN(t)===!1)return e["long"]?o(t):r(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e,n){function r(){}function o(t){var n=""+t.type;if(e.BINARY_EVENT!==t.type&&e.BINARY_ACK!==t.type||(n+=t.attachments+"-"),t.nsp&&"/"!==t.nsp&&(n+=t.nsp+","),null!=t.id&&(n+=t.id),null!=t.data){var r=i(t.data);if(r===!1)return g;n+=r}return f("encoded %j as %s",t,n),n}function i(t){try{return JSON.stringify(t)}catch(e){return!1}}function s(t,e){function n(t){var n=d.deconstructPacket(t),r=o(n.packet),i=n.buffers;i.unshift(r),e(i)}d.removeBlobs(t,n)}function a(){this.reconstructor=null}function c(t){var n=0,r={type:Number(t.charAt(0))};if(null==e.types[r.type])return h("unknown packet type "+r.type);if(e.BINARY_EVENT===r.type||e.BINARY_ACK===r.type){for(var o="";"-"!==t.charAt(++n)&&(o+=t.charAt(n),n!=t.length););if(o!=Number(o)||"-"!==t.charAt(n))throw new Error("Illegal attachments");r.attachments=Number(o)}if("/"===t.charAt(n+1))for(r.nsp="";++n;){var i=t.charAt(n);if(","===i)break;if(r.nsp+=i,n===t.length)break}else r.nsp="/";var s=t.charAt(n+1);if(""!==s&&Number(s)==s){for(r.id="";++n;){var i=t.charAt(n);if(null==i||Number(i)!=i){--n;break}if(r.id+=t.charAt(n),n===t.length)break}r.id=Number(r.id)}if(t.charAt(++n)){var a=p(t.substr(n)),c=a!==!1&&(r.type===e.ERROR||y(a));if(!c)return h("invalid payload");r.data=a}return f("decoded %s as %j",t,r),r}function p(t){try{return JSON.parse(t)}catch(e){return!1}}function u(t){this.reconPack=t,this.buffers=[]}function h(t){return{type:e.ERROR,data:"parser error: "+t}}var f=n(3)("socket.io-parser"),l=n(8),d=n(9),y=n(10),m=n(11);e.protocol=4,e.types=["CONNECT","DISCONNECT","EVENT","ACK","ERROR","BINARY_EVENT","BINARY_ACK"],e.CONNECT=0,e.DISCONNECT=1,e.EVENT=2,e.ACK=3,e.ERROR=4,e.BINARY_EVENT=5,e.BINARY_ACK=6,e.Encoder=r,e.Decoder=a;var g=e.ERROR+'"encode error"';r.prototype.encode=function(t,n){if(f("encoding packet %j",t),e.BINARY_EVENT===t.type||e.BINARY_ACK===t.type)s(t,n);else{var r=o(t);n([r])}},l(a.prototype),a.prototype.add=function(t){var n;if("string"==typeof t)n=c(t),e.BINARY_EVENT===n.type||e.BINARY_ACK===n.type?(this.reconstructor=new u(n),0===this.reconstructor.reconPack.attachments&&this.emit("decoded",n)):this.emit("decoded",n);else{if(!m(t)&&!t.base64)throw new Error("Unknown type: "+t);if(!this.reconstructor)throw new Error("got binary data when not reconstructing a packet");n=this.reconstructor.takeBinaryData(t),n&&(this.reconstructor=null,this.emit("decoded",n))}},a.prototype.destroy=function(){this.reconstructor&&this.reconstructor.finishedReconstruction()},u.prototype.takeBinaryData=function(t){if(this.buffers.push(t),this.buffers.length===this.reconPack.attachments){var e=d.reconstructPacket(this.reconPack,this.buffers);return this.finishedReconstruction(),e}return null},u.prototype.finishedReconstruction=function(){this.reconPack=null,this.buffers=[]}},function(t,e,n){function r(t){if(t)return o(t)}function o(t){for(var e in r.prototype)t[e]=r.prototype[e];return t}t.exports=r,r.prototype.on=r.prototype.addEventListener=function(t,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+t]=this._callbacks["$"+t]||[]).push(e),this},r.prototype.once=function(t,e){function n(){this.off(t,n),e.apply(this,arguments)}return n.fn=e,this.on(t,n),this},r.prototype.off=r.prototype.removeListener=r.prototype.removeAllListeners=r.prototype.removeEventListener=function(t,e){if(this._callbacks=this._callbacks||{},0==arguments.length)return this._callbacks={},this;var n=this._callbacks["$"+t];if(!n)return this;if(1==arguments.length)return delete this._callbacks["$"+t],this;for(var r,o=0;o0&&!this.encoding){var t=this.packetBuffer.shift();this.packet(t)}},r.prototype.cleanup=function(){h("cleanup");for(var t=this.subs.length,e=0;e=this._reconnectionAttempts)h("reconnect failed"),this.backoff.reset(),this.emitAll("reconnect_failed"),this.reconnecting=!1;else{var e=this.backoff.duration();h("will wait %dms before reconnect attempt",e),this.reconnecting=!0;var n=setTimeout(function(){t.skipReconnect||(h("attempting reconnect"),t.emitAll("reconnect_attempt",t.backoff.attempts),t.emitAll("reconnecting",t.backoff.attempts),t.skipReconnect||t.open(function(e){e?(h("reconnect attempt error"),t.reconnecting=!1,t.reconnect(),t.emitAll("reconnect_error",e.data)):(h("reconnect success"),t.onreconnect())}))},e);this.subs.push({destroy:function(){clearTimeout(n)}})}},r.prototype.onreconnect=function(){var t=this.backoff.attempts;this.reconnecting=!1,this.backoff.reset(),this.updateSocketIds(),this.emitAll("reconnect",t)}},function(t,e,n){t.exports=n(14),t.exports.parser=n(21)},function(t,e,n){function r(t,e){return this instanceof r?(e=e||{},t&&"object"==typeof t&&(e=t,t=null),t?(t=u(t),e.hostname=t.host,e.secure="https"===t.protocol||"wss"===t.protocol,e.port=t.port,t.query&&(e.query=t.query)):e.host&&(e.hostname=u(e.host).host),this.secure=null!=e.secure?e.secure:"undefined"!=typeof location&&"https:"===location.protocol,e.hostname&&!e.port&&(e.port=this.secure?"443":"80"),this.agent=e.agent||!1,this.hostname=e.hostname||("undefined"!=typeof location?location.hostname:"localhost"),this.port=e.port||("undefined"!=typeof location&&location.port?location.port:this.secure?443:80),this.query=e.query||{},"string"==typeof this.query&&(this.query=h.decode(this.query)),this.upgrade=!1!==e.upgrade,this.path=(e.path||"/engine.io").replace(/\/$/,"")+"/",this.forceJSONP=!!e.forceJSONP,this.jsonp=!1!==e.jsonp,this.forceBase64=!!e.forceBase64,this.enablesXDR=!!e.enablesXDR,this.timestampParam=e.timestampParam||"t",this.timestampRequests=e.timestampRequests,this.transports=e.transports||["polling","websocket"],this.transportOptions=e.transportOptions||{},this.readyState="",this.writeBuffer=[],this.prevBufferLen=0,this.policyPort=e.policyPort||843,this.rememberUpgrade=e.rememberUpgrade||!1,this.binaryType=null,this.onlyBinaryUpgrades=e.onlyBinaryUpgrades,this.perMessageDeflate=!1!==e.perMessageDeflate&&(e.perMessageDeflate||{}),!0===this.perMessageDeflate&&(this.perMessageDeflate={}),this.perMessageDeflate&&null==this.perMessageDeflate.threshold&&(this.perMessageDeflate.threshold=1024),this.pfx=e.pfx||null,this.key=e.key||null,this.passphrase=e.passphrase||null,this.cert=e.cert||null,this.ca=e.ca||null,this.ciphers=e.ciphers||null,this.rejectUnauthorized=void 0===e.rejectUnauthorized||e.rejectUnauthorized,this.forceNode=!!e.forceNode,this.isReactNative="undefined"!=typeof navigator&&"string"==typeof navigator.product&&"reactnative"===navigator.product.toLowerCase(),("undefined"==typeof self||this.isReactNative)&&(e.extraHeaders&&Object.keys(e.extraHeaders).length>0&&(this.extraHeaders=e.extraHeaders),e.localAddress&&(this.localAddress=e.localAddress)),this.id=null,this.upgrades=null,this.pingInterval=null,this.pingTimeout=null,this.pingIntervalTimer=null,this.pingTimeoutTimer=null,void this.open()):new r(t,e)}function o(t){var e={};for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}var i=n(15),s=n(8),a=n(3)("engine.io-client:socket"),c=n(35),p=n(21),u=n(2),h=n(29);t.exports=r,r.priorWebsocketSuccess=!1,s(r.prototype),r.protocol=p.protocol,r.Socket=r,r.Transport=n(20),r.transports=n(15),r.parser=n(21),r.prototype.createTransport=function(t){a('creating transport "%s"',t);var e=o(this.query);e.EIO=p.protocol,e.transport=t;var n=this.transportOptions[t]||{};this.id&&(e.sid=this.id);var r=new i[t]({query:e,socket:this,agent:n.agent||this.agent,hostname:n.hostname||this.hostname,port:n.port||this.port,secure:n.secure||this.secure,path:n.path||this.path,forceJSONP:n.forceJSONP||this.forceJSONP,jsonp:n.jsonp||this.jsonp,forceBase64:n.forceBase64||this.forceBase64,enablesXDR:n.enablesXDR||this.enablesXDR,timestampRequests:n.timestampRequests||this.timestampRequests,timestampParam:n.timestampParam||this.timestampParam,policyPort:n.policyPort||this.policyPort,pfx:n.pfx||this.pfx,key:n.key||this.key,passphrase:n.passphrase||this.passphrase,cert:n.cert||this.cert,ca:n.ca||this.ca,ciphers:n.ciphers||this.ciphers,rejectUnauthorized:n.rejectUnauthorized||this.rejectUnauthorized,perMessageDeflate:n.perMessageDeflate||this.perMessageDeflate,extraHeaders:n.extraHeaders||this.extraHeaders,forceNode:n.forceNode||this.forceNode,localAddress:n.localAddress||this.localAddress,requestTimeout:n.requestTimeout||this.requestTimeout,protocols:n.protocols||void 0,isReactNative:this.isReactNative});return r},r.prototype.open=function(){var t;if(this.rememberUpgrade&&r.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1)t="websocket";else{if(0===this.transports.length){var e=this;return void setTimeout(function(){e.emit("error","No transports available")},0)}t=this.transports[0]}this.readyState="opening";try{t=this.createTransport(t)}catch(n){return this.transports.shift(),void this.open()}t.open(),this.setTransport(t)},r.prototype.setTransport=function(t){a("setting transport %s",t.name);var e=this;this.transport&&(a("clearing existing transport %s",this.transport.name),this.transport.removeAllListeners()),this.transport=t,t.on("drain",function(){e.onDrain()}).on("packet",function(t){e.onPacket(t)}).on("error",function(t){e.onError(t)}).on("close",function(){e.onClose("transport close")})},r.prototype.probe=function(t){function e(){if(f.onlyBinaryUpgrades){var e=!this.supportsBinary&&f.transport.supportsBinary;h=h||e}h||(a('probe transport "%s" opened',t),u.send([{type:"ping",data:"probe"}]),u.once("packet",function(e){if(!h)if("pong"===e.type&&"probe"===e.data){if(a('probe transport "%s" pong',t),f.upgrading=!0,f.emit("upgrading",u),!u)return;r.priorWebsocketSuccess="websocket"===u.name,a('pausing current transport "%s"',f.transport.name),f.transport.pause(function(){h||"closed"!==f.readyState&&(a("changing transport and sending upgrade packet"),p(),f.setTransport(u),u.send([{type:"upgrade"}]),f.emit("upgrade",u),u=null,f.upgrading=!1,f.flush())})}else{a('probe transport "%s" failed',t);var n=new Error("probe error");n.transport=u.name,f.emit("upgradeError",n)}}))}function n(){h||(h=!0,p(),u.close(),u=null)}function o(e){var r=new Error("probe error: "+e);r.transport=u.name,n(),a('probe transport "%s" failed because of error: %s',t,e),f.emit("upgradeError",r)}function i(){o("transport closed")}function s(){o("socket closed")}function c(t){u&&t.name!==u.name&&(a('"%s" works - aborting "%s"',t.name,u.name),n())}function p(){u.removeListener("open",e),u.removeListener("error",o),u.removeListener("close",i),f.removeListener("close",s),f.removeListener("upgrading",c)}a('probing transport "%s"',t);var u=this.createTransport(t,{probe:1}),h=!1,f=this;r.priorWebsocketSuccess=!1,u.once("open",e),u.once("error",o),u.once("close",i),this.once("close",s),this.once("upgrading",c),u.open()},r.prototype.onOpen=function(){if(a("socket open"),this.readyState="open",r.priorWebsocketSuccess="websocket"===this.transport.name,this.emit("open"),this.flush(),"open"===this.readyState&&this.upgrade&&this.transport.pause){a("starting upgrade probes");for(var t=0,e=this.upgrades.length;t1?{type:b[o],data:t.substring(1)}:{type:b[o]}:w}var i=new Uint8Array(t),o=i[0],s=f(t,1);return k&&"blob"===n&&(s=new k([s])),{type:b[o],data:s}},e.decodeBase64Packet=function(t,e){var n=b[t.charAt(0)];if(!p)return{type:n,data:{base64:!0,data:t.substr(1)}};var r=p.decode(t.substr(1));return"blob"===e&&k&&(r=new k([r])),{type:n,data:r}},e.encodePayload=function(t,n,r){function o(t){return t.length+":"+t}function i(t,r){e.encodePacket(t,!!s&&n,!1,function(t){r(null,o(t))})}"function"==typeof n&&(r=n,n=null);var s=h(t);return n&&s?k&&!g?e.encodePayloadAsBlob(t,r):e.encodePayloadAsArrayBuffer(t,r):t.length?void c(t,i,function(t,e){return r(e.join(""))}):r("0:")},e.decodePayload=function(t,n,r){if("string"!=typeof t)return e.decodePayloadAsBinary(t,n,r);"function"==typeof n&&(r=n,n=null);var o;if(""===t)return r(w,0,1);for(var i,s,a="",c=0,p=t.length;c0;){for(var s=new Uint8Array(o),a=0===s[0],c="",p=1;255!==s[p];p++){if(c.length>310)return r(w,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var u=f(o,0,c);if(a)try{u=String.fromCharCode.apply(null,new Uint8Array(u))}catch(h){var l=new Uint8Array(u);u="";for(var p=0;pr&&(n=r),e>=r||e>=n||0===r)return new ArrayBuffer(0);for(var o=new Uint8Array(t),i=new Uint8Array(n-e),s=e,a=0;s=55296&&e<=56319&&o65535&&(e-=65536,o+=d(e>>>10&1023|55296),e=56320|1023&e),o+=d(e);return o}function o(t,e){if(t>=55296&&t<=57343){if(e)throw Error("Lone surrogate U+"+t.toString(16).toUpperCase()+" is not a scalar value");return!1}return!0}function i(t,e){return d(t>>e&63|128)}function s(t,e){if(0==(4294967168&t))return d(t);var n="";return 0==(4294965248&t)?n=d(t>>6&31|192):0==(4294901760&t)?(o(t,e)||(t=65533),n=d(t>>12&15|224),n+=i(t,6)):0==(4292870144&t)&&(n=d(t>>18&7|240),n+=i(t,12),n+=i(t,6)),n+=d(63&t|128)}function a(t,e){e=e||{};for(var r,o=!1!==e.strict,i=n(t),a=i.length,c=-1,p="";++c=f)throw Error("Invalid byte index");var t=255&h[l];if(l++,128==(192&t))return 63&t;throw Error("Invalid continuation byte")}function p(t){var e,n,r,i,s;if(l>f)throw Error("Invalid byte index");if(l==f)return!1;if(e=255&h[l],l++,0==(128&e))return e;if(192==(224&e)){if(n=c(),s=(31&e)<<6|n,s>=128)return s;throw Error("Invalid continuation byte")}if(224==(240&e)){if(n=c(),r=c(),s=(15&e)<<12|n<<6|r,s>=2048)return o(s,t)?s:65533;throw Error("Invalid continuation byte")}if(240==(248&e)&&(n=c(),r=c(),i=c(),s=(7&e)<<18|n<<12|r<<6|i,s>=65536&&s<=1114111))return s;throw Error("Invalid UTF-8 detected")}function u(t,e){e=e||{};var o=!1!==e.strict;h=n(t),f=h.length,l=0;for(var i,s=[];(i=p(o))!==!1;)s.push(i);return r(s)}/*! https://mths.be/utf8js v2.1.2 by @mathias */ 8 | var h,f,l,d=String.fromCharCode;t.exports={version:"2.1.2",encode:a,decode:u}},function(t,e){!function(){"use strict";for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=new Uint8Array(256),r=0;r>2],i+=t[(3&r[n])<<4|r[n+1]>>4],i+=t[(15&r[n+1])<<2|r[n+2]>>6],i+=t[63&r[n+2]];return o%3===2?i=i.substring(0,i.length-1)+"=":o%3===1&&(i=i.substring(0,i.length-2)+"=="),i},e.decode=function(t){var e,r,o,i,s,a=.75*t.length,c=t.length,p=0;"="===t[t.length-1]&&(a--,"="===t[t.length-2]&&a--);var u=new ArrayBuffer(a),h=new Uint8Array(u);for(e=0;e>4,h[p++]=(15&o)<<4|i>>2,h[p++]=(3&i)<<6|63&s;return u}}()},function(t,e){function n(t){return t.map(function(t){if(t.buffer instanceof ArrayBuffer){var e=t.buffer;if(t.byteLength!==e.byteLength){var n=new Uint8Array(t.byteLength);n.set(new Uint8Array(e,t.byteOffset,t.byteLength)),e=n.buffer}return e}return t})}function r(t,e){e=e||{};var r=new i;return n(t).forEach(function(t){r.append(t)}),e.type?r.getBlob(e.type):r.getBlob()}function o(t,e){return new Blob(n(t),e||{})}var i="undefined"!=typeof i?i:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:"undefined"!=typeof MSBlobBuilder?MSBlobBuilder:"undefined"!=typeof MozBlobBuilder&&MozBlobBuilder,s=function(){try{var t=new Blob(["hi"]);return 2===t.size}catch(e){return!1}}(),a=s&&function(){try{var t=new Blob([new Uint8Array([1,2])]);return 2===t.size}catch(e){return!1}}(),c=i&&i.prototype.append&&i.prototype.getBlob;"undefined"!=typeof Blob&&(r.prototype=Blob.prototype,o.prototype=Blob.prototype),t.exports=function(){return s?a?Blob:o:c?r:void 0}()},function(t,e){e.encode=function(t){var e="";for(var n in t)t.hasOwnProperty(n)&&(e.length&&(e+="&"),e+=encodeURIComponent(n)+"="+encodeURIComponent(t[n]));return e},e.decode=function(t){for(var e={},n=t.split("&"),r=0,o=n.length;r0);return e}function r(t){var e=0;for(u=0;u';i=document.createElement(e)}catch(t){i=document.createElement("iframe"),i.name=o.iframeId,i.src="javascript:0"}i.id=o.iframeId,o.form.appendChild(i),o.iframe=i}var o=this;if(!this.form){var i,s=document.createElement("form"),a=document.createElement("textarea"),c=this.iframeId="eio_iframe_"+this.index;s.className="socketio",s.style.position="absolute",s.style.top="-1000px",s.style.left="-1000px",s.target=c,s.method="POST",s.setAttribute("accept-charset","utf-8"),a.name="d",s.appendChild(a),document.body.appendChild(s),this.form=s,this.area=a}this.form.action=this.uri(),r(),t=t.replace(u,"\\\n"),this.area.value=t.replace(p,"\\n");try{this.form.submit()}catch(h){}this.iframe.attachEvent?this.iframe.onreadystatechange=function(){"complete"===o.iframe.readyState&&n()}:this.iframe.onload=n}}).call(e,function(){return this}())},function(t,e,n){function r(t){var e=t&&t.forceBase64;e&&(this.supportsBinary=!1),this.perMessageDeflate=t.perMessageDeflate,this.usingBrowserWebSocket=o&&!t.forceNode,this.protocols=t.protocols,this.usingBrowserWebSocket||(l=i),s.call(this,t)}var o,i,s=n(20),a=n(21),c=n(29),p=n(30),u=n(31),h=n(3)("engine.io-client:websocket");if("undefined"==typeof self)try{i=n(34)}catch(f){}else o=self.WebSocket||self.MozWebSocket;var l=o||i;t.exports=r,p(r,s),r.prototype.name="websocket",r.prototype.supportsBinary=!0,r.prototype.doOpen=function(){if(this.check()){var t=this.uri(),e=this.protocols,n={agent:this.agent,perMessageDeflate:this.perMessageDeflate};n.pfx=this.pfx,n.key=this.key,n.passphrase=this.passphrase,n.cert=this.cert,n.ca=this.ca,n.ciphers=this.ciphers,n.rejectUnauthorized=this.rejectUnauthorized,this.extraHeaders&&(n.headers=this.extraHeaders),this.localAddress&&(n.localAddress=this.localAddress);try{this.ws=this.usingBrowserWebSocket&&!this.isReactNative?e?new l(t,e):new l(t):new l(t,e,n)}catch(r){return this.emit("error",r)}void 0===this.ws.binaryType&&(this.supportsBinary=!1),this.ws.supports&&this.ws.supports.binary?(this.supportsBinary=!0,this.ws.binaryType="nodebuffer"):this.ws.binaryType="arraybuffer",this.addEventListeners()}},r.prototype.addEventListeners=function(){var t=this;this.ws.onopen=function(){t.onOpen()},this.ws.onclose=function(){t.onClose()},this.ws.onmessage=function(e){t.onData(e.data)},this.ws.onerror=function(e){t.onError("websocket error",e)}},r.prototype.write=function(t){function e(){n.emit("flush"),setTimeout(function(){n.writable=!0,n.emit("drain")},0)}var n=this;this.writable=!1;for(var r=t.length,o=0,i=r;o0&&t.jitter<=1?t.jitter:0,this.attempts=0}t.exports=n,n.prototype.duration=function(){var t=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),n=Math.floor(e*this.jitter*t);t=0==(1&Math.floor(10*e))?t-n:t+n}return 0|Math.min(t,this.max)},n.prototype.reset=function(){this.attempts=0},n.prototype.setMin=function(t){this.ms=t},n.prototype.setMax=function(t){this.max=t},n.prototype.setJitter=function(t){this.jitter=t}}])}); 9 | //# sourceMappingURL=socket.io.js.map -------------------------------------------------------------------------------- /nodejsserver/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wowza-webrtc-group-call", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.5", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", 10 | "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", 11 | "requires": { 12 | "mime-types": "2.1.22", 13 | "negotiator": "0.6.1" 14 | } 15 | }, 16 | "after": { 17 | "version": "0.8.2", 18 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 19 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 20 | }, 21 | "array-flatten": { 22 | "version": "1.1.1", 23 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 24 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 25 | }, 26 | "arraybuffer.slice": { 27 | "version": "0.0.7", 28 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 29 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 30 | }, 31 | "async-limiter": { 32 | "version": "1.0.0", 33 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", 34 | "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" 35 | }, 36 | "backo2": { 37 | "version": "1.0.2", 38 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 39 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 40 | }, 41 | "base64-arraybuffer": { 42 | "version": "0.1.5", 43 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 44 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 45 | }, 46 | "base64id": { 47 | "version": "1.0.0", 48 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", 49 | "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" 50 | }, 51 | "better-assert": { 52 | "version": "1.0.2", 53 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 54 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 55 | "requires": { 56 | "callsite": "1.0.0" 57 | } 58 | }, 59 | "blob": { 60 | "version": "0.0.5", 61 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 62 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 63 | }, 64 | "body-parser": { 65 | "version": "1.18.3", 66 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", 67 | "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", 68 | "requires": { 69 | "bytes": "3.0.0", 70 | "content-type": "1.0.4", 71 | "debug": "2.6.9", 72 | "depd": "1.1.2", 73 | "http-errors": "1.6.3", 74 | "iconv-lite": "0.4.23", 75 | "on-finished": "2.3.0", 76 | "qs": "6.5.2", 77 | "raw-body": "2.3.3", 78 | "type-is": "1.6.16" 79 | } 80 | }, 81 | "bytes": { 82 | "version": "3.0.0", 83 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 84 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 85 | }, 86 | "callsite": { 87 | "version": "1.0.0", 88 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 89 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 90 | }, 91 | "component-bind": { 92 | "version": "1.0.0", 93 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 94 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 95 | }, 96 | "component-emitter": { 97 | "version": "1.2.1", 98 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 99 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 100 | }, 101 | "component-inherit": { 102 | "version": "0.0.3", 103 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 104 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 105 | }, 106 | "content-disposition": { 107 | "version": "0.5.2", 108 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", 109 | "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" 110 | }, 111 | "content-type": { 112 | "version": "1.0.4", 113 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 114 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 115 | }, 116 | "cookie": { 117 | "version": "0.3.1", 118 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 119 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 120 | }, 121 | "cookie-signature": { 122 | "version": "1.0.6", 123 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 124 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 125 | }, 126 | "debug": { 127 | "version": "2.6.9", 128 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 129 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 130 | "requires": { 131 | "ms": "2.0.0" 132 | } 133 | }, 134 | "depd": { 135 | "version": "1.1.2", 136 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 137 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 138 | }, 139 | "destroy": { 140 | "version": "1.0.4", 141 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 142 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 143 | }, 144 | "ee-first": { 145 | "version": "1.1.1", 146 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 147 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 148 | }, 149 | "encodeurl": { 150 | "version": "1.0.2", 151 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 152 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 153 | }, 154 | "engine.io": { 155 | "version": "3.3.2", 156 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", 157 | "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", 158 | "requires": { 159 | "accepts": "1.3.5", 160 | "base64id": "1.0.0", 161 | "cookie": "0.3.1", 162 | "debug": "3.1.0", 163 | "engine.io-parser": "2.1.3", 164 | "ws": "6.1.4" 165 | }, 166 | "dependencies": { 167 | "debug": { 168 | "version": "3.1.0", 169 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 170 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 171 | "requires": { 172 | "ms": "2.0.0" 173 | } 174 | } 175 | } 176 | }, 177 | "engine.io-client": { 178 | "version": "3.3.2", 179 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", 180 | "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", 181 | "requires": { 182 | "component-emitter": "1.2.1", 183 | "component-inherit": "0.0.3", 184 | "debug": "3.1.0", 185 | "engine.io-parser": "2.1.3", 186 | "has-cors": "1.1.0", 187 | "indexof": "0.0.1", 188 | "parseqs": "0.0.5", 189 | "parseuri": "0.0.5", 190 | "ws": "6.1.4", 191 | "xmlhttprequest-ssl": "1.5.5", 192 | "yeast": "0.1.2" 193 | }, 194 | "dependencies": { 195 | "debug": { 196 | "version": "3.1.0", 197 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 198 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 199 | "requires": { 200 | "ms": "2.0.0" 201 | } 202 | } 203 | } 204 | }, 205 | "engine.io-parser": { 206 | "version": "2.1.3", 207 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", 208 | "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", 209 | "requires": { 210 | "after": "0.8.2", 211 | "arraybuffer.slice": "0.0.7", 212 | "base64-arraybuffer": "0.1.5", 213 | "blob": "0.0.5", 214 | "has-binary2": "1.0.3" 215 | } 216 | }, 217 | "escape-html": { 218 | "version": "1.0.3", 219 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 220 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 221 | }, 222 | "etag": { 223 | "version": "1.8.1", 224 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 225 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 226 | }, 227 | "express": { 228 | "version": "4.16.4", 229 | "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", 230 | "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", 231 | "requires": { 232 | "accepts": "1.3.5", 233 | "array-flatten": "1.1.1", 234 | "body-parser": "1.18.3", 235 | "content-disposition": "0.5.2", 236 | "content-type": "1.0.4", 237 | "cookie": "0.3.1", 238 | "cookie-signature": "1.0.6", 239 | "debug": "2.6.9", 240 | "depd": "1.1.2", 241 | "encodeurl": "1.0.2", 242 | "escape-html": "1.0.3", 243 | "etag": "1.8.1", 244 | "finalhandler": "1.1.1", 245 | "fresh": "0.5.2", 246 | "merge-descriptors": "1.0.1", 247 | "methods": "1.1.2", 248 | "on-finished": "2.3.0", 249 | "parseurl": "1.3.2", 250 | "path-to-regexp": "0.1.7", 251 | "proxy-addr": "2.0.4", 252 | "qs": "6.5.2", 253 | "range-parser": "1.2.0", 254 | "safe-buffer": "5.1.2", 255 | "send": "0.16.2", 256 | "serve-static": "1.13.2", 257 | "setprototypeof": "1.1.0", 258 | "statuses": "1.4.0", 259 | "type-is": "1.6.16", 260 | "utils-merge": "1.0.1", 261 | "vary": "1.1.2" 262 | } 263 | }, 264 | "finalhandler": { 265 | "version": "1.1.1", 266 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", 267 | "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", 268 | "requires": { 269 | "debug": "2.6.9", 270 | "encodeurl": "1.0.2", 271 | "escape-html": "1.0.3", 272 | "on-finished": "2.3.0", 273 | "parseurl": "1.3.2", 274 | "statuses": "1.4.0", 275 | "unpipe": "1.0.0" 276 | } 277 | }, 278 | "forwarded": { 279 | "version": "0.1.2", 280 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 281 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 282 | }, 283 | "fresh": { 284 | "version": "0.5.2", 285 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 286 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 287 | }, 288 | "has-binary2": { 289 | "version": "1.0.3", 290 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 291 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 292 | "requires": { 293 | "isarray": "2.0.1" 294 | } 295 | }, 296 | "has-cors": { 297 | "version": "1.1.0", 298 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 299 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 300 | }, 301 | "http-errors": { 302 | "version": "1.6.3", 303 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", 304 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 305 | "requires": { 306 | "depd": "1.1.2", 307 | "inherits": "2.0.3", 308 | "setprototypeof": "1.1.0", 309 | "statuses": "1.4.0" 310 | } 311 | }, 312 | "iconv-lite": { 313 | "version": "0.4.23", 314 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 315 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 316 | "requires": { 317 | "safer-buffer": "2.1.2" 318 | } 319 | }, 320 | "indexof": { 321 | "version": "0.0.1", 322 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 323 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 324 | }, 325 | "inherits": { 326 | "version": "2.0.3", 327 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 328 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 329 | }, 330 | "ipaddr.js": { 331 | "version": "1.8.0", 332 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", 333 | "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" 334 | }, 335 | "isarray": { 336 | "version": "2.0.1", 337 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 338 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 339 | }, 340 | "media-typer": { 341 | "version": "0.3.0", 342 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 343 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 344 | }, 345 | "merge-descriptors": { 346 | "version": "1.0.1", 347 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 348 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 349 | }, 350 | "methods": { 351 | "version": "1.1.2", 352 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 353 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 354 | }, 355 | "mime": { 356 | "version": "1.4.1", 357 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", 358 | "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" 359 | }, 360 | "mime-db": { 361 | "version": "1.38.0", 362 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", 363 | "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" 364 | }, 365 | "mime-types": { 366 | "version": "2.1.22", 367 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", 368 | "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", 369 | "requires": { 370 | "mime-db": "1.38.0" 371 | } 372 | }, 373 | "ms": { 374 | "version": "2.0.0", 375 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 376 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 377 | }, 378 | "negotiator": { 379 | "version": "0.6.1", 380 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", 381 | "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" 382 | }, 383 | "object-component": { 384 | "version": "0.0.3", 385 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 386 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 387 | }, 388 | "on-finished": { 389 | "version": "2.3.0", 390 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 391 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 392 | "requires": { 393 | "ee-first": "1.1.1" 394 | } 395 | }, 396 | "parseqs": { 397 | "version": "0.0.5", 398 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 399 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 400 | "requires": { 401 | "better-assert": "1.0.2" 402 | } 403 | }, 404 | "parseuri": { 405 | "version": "0.0.5", 406 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 407 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 408 | "requires": { 409 | "better-assert": "1.0.2" 410 | } 411 | }, 412 | "parseurl": { 413 | "version": "1.3.2", 414 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", 415 | "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" 416 | }, 417 | "path-to-regexp": { 418 | "version": "0.1.7", 419 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 420 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 421 | }, 422 | "proxy-addr": { 423 | "version": "2.0.4", 424 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", 425 | "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", 426 | "requires": { 427 | "forwarded": "0.1.2", 428 | "ipaddr.js": "1.8.0" 429 | } 430 | }, 431 | "qs": { 432 | "version": "6.5.2", 433 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 434 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 435 | }, 436 | "range-parser": { 437 | "version": "1.2.0", 438 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", 439 | "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" 440 | }, 441 | "raw-body": { 442 | "version": "2.3.3", 443 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", 444 | "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", 445 | "requires": { 446 | "bytes": "3.0.0", 447 | "http-errors": "1.6.3", 448 | "iconv-lite": "0.4.23", 449 | "unpipe": "1.0.0" 450 | } 451 | }, 452 | "safe-buffer": { 453 | "version": "5.1.2", 454 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 455 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 456 | }, 457 | "safer-buffer": { 458 | "version": "2.1.2", 459 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 460 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 461 | }, 462 | "send": { 463 | "version": "0.16.2", 464 | "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", 465 | "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", 466 | "requires": { 467 | "debug": "2.6.9", 468 | "depd": "1.1.2", 469 | "destroy": "1.0.4", 470 | "encodeurl": "1.0.2", 471 | "escape-html": "1.0.3", 472 | "etag": "1.8.1", 473 | "fresh": "0.5.2", 474 | "http-errors": "1.6.3", 475 | "mime": "1.4.1", 476 | "ms": "2.0.0", 477 | "on-finished": "2.3.0", 478 | "range-parser": "1.2.0", 479 | "statuses": "1.4.0" 480 | } 481 | }, 482 | "serve-static": { 483 | "version": "1.13.2", 484 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", 485 | "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", 486 | "requires": { 487 | "encodeurl": "1.0.2", 488 | "escape-html": "1.0.3", 489 | "parseurl": "1.3.2", 490 | "send": "0.16.2" 491 | } 492 | }, 493 | "setprototypeof": { 494 | "version": "1.1.0", 495 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", 496 | "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" 497 | }, 498 | "socket.io": { 499 | "version": "2.2.0", 500 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", 501 | "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", 502 | "requires": { 503 | "debug": "4.1.1", 504 | "engine.io": "3.3.2", 505 | "has-binary2": "1.0.3", 506 | "socket.io-adapter": "1.1.1", 507 | "socket.io-client": "2.2.0", 508 | "socket.io-parser": "3.3.0" 509 | }, 510 | "dependencies": { 511 | "debug": { 512 | "version": "4.1.1", 513 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 514 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 515 | "requires": { 516 | "ms": "2.1.1" 517 | } 518 | }, 519 | "ms": { 520 | "version": "2.1.1", 521 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 522 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 523 | } 524 | } 525 | }, 526 | "socket.io-adapter": { 527 | "version": "1.1.1", 528 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", 529 | "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" 530 | }, 531 | "socket.io-client": { 532 | "version": "2.2.0", 533 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", 534 | "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", 535 | "requires": { 536 | "backo2": "1.0.2", 537 | "base64-arraybuffer": "0.1.5", 538 | "component-bind": "1.0.0", 539 | "component-emitter": "1.2.1", 540 | "debug": "3.1.0", 541 | "engine.io-client": "3.3.2", 542 | "has-binary2": "1.0.3", 543 | "has-cors": "1.1.0", 544 | "indexof": "0.0.1", 545 | "object-component": "0.0.3", 546 | "parseqs": "0.0.5", 547 | "parseuri": "0.0.5", 548 | "socket.io-parser": "3.3.0", 549 | "to-array": "0.1.4" 550 | }, 551 | "dependencies": { 552 | "debug": { 553 | "version": "3.1.0", 554 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 555 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 556 | "requires": { 557 | "ms": "2.0.0" 558 | } 559 | } 560 | } 561 | }, 562 | "socket.io-parser": { 563 | "version": "3.3.0", 564 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", 565 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", 566 | "requires": { 567 | "component-emitter": "1.2.1", 568 | "debug": "3.1.0", 569 | "isarray": "2.0.1" 570 | }, 571 | "dependencies": { 572 | "debug": { 573 | "version": "3.1.0", 574 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 575 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 576 | "requires": { 577 | "ms": "2.0.0" 578 | } 579 | } 580 | } 581 | }, 582 | "statuses": { 583 | "version": "1.4.0", 584 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", 585 | "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" 586 | }, 587 | "to-array": { 588 | "version": "0.1.4", 589 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 590 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 591 | }, 592 | "type-is": { 593 | "version": "1.6.16", 594 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", 595 | "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", 596 | "requires": { 597 | "media-typer": "0.3.0", 598 | "mime-types": "2.1.22" 599 | } 600 | }, 601 | "unpipe": { 602 | "version": "1.0.0", 603 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 604 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 605 | }, 606 | "utils-merge": { 607 | "version": "1.0.1", 608 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 609 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 610 | }, 611 | "vary": { 612 | "version": "1.1.2", 613 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 614 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 615 | }, 616 | "ws": { 617 | "version": "6.1.4", 618 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 619 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 620 | "requires": { 621 | "async-limiter": "1.0.0" 622 | } 623 | }, 624 | "xmlhttprequest-ssl": { 625 | "version": "1.5.5", 626 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 627 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 628 | }, 629 | "yeast": { 630 | "version": "0.1.2", 631 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 632 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 633 | } 634 | } 635 | } 636 | -------------------------------------------------------------------------------- /nodejsserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wowza-webrtc-group-call", 3 | "version": "1.0.0", 4 | "description": "Wowza Webrtc Group Call Sample", 5 | "main": "videochat.js", 6 | "dependencies": { 7 | "express": "^4.16.4", 8 | "socket.io": "^2.2.0" 9 | }, 10 | "devDependencies": {}, 11 | "scripts": { 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [ 15 | "Wowza", 16 | "Webrtc", 17 | "Group", 18 | "Call" 19 | ], 20 | "author": "Emre Karataşoğlu", 21 | "license": "MIT" 22 | } 23 | -------------------------------------------------------------------------------- /nodejsserver/public/beep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lethea/wowza-webrtc-group-call-and-chat/19b11b897c9efa4923f4a69693d1cda808f419c2/nodejsserver/public/beep.mp3 -------------------------------------------------------------------------------- /nodejsserver/videochat.js: -------------------------------------------------------------------------------- 1 | var express = require('express') 2 | var app = express(); 3 | var server = require('http').createServer(app); 4 | var io = require('socket.io').listen(server); 5 | var roomMembers = new Array(); 6 | 7 | app.use(express.static('public')); 8 | 9 | server.listen(3000); 10 | console.log('Server started.'); 11 | 12 | 13 | io.sockets.on('connection', clientConnected); 14 | 15 | 16 | function clientConnected(socket) { 17 | 18 | socket.on('disconnect', function () { 19 | console.log('Client ' + socket.handshake.address + ' disconnected.'); 20 | io.to(socket.room).emit("message", {type: "user_left", data: socket.nickname}); 21 | if (roomMembers[socket.room]) { 22 | roomMembers[socket.room].splice(roomMembers[socket.room].indexOf(socket.nickname), 1); 23 | updateRoomMembers(socket.room); 24 | } 25 | }); 26 | socket.on('login', function (data) { 27 | console.log('Client Login ', data); 28 | socket.nickname = data.nickname; 29 | socket.room = data.room; 30 | socket.join(data.nickname); 31 | socket.join(data.room); 32 | socket.broadcast.to(data.room).emit("message", {type: "new_user_login", data: data.nickname}); 33 | 34 | if (!roomMembers[socket.room]) { 35 | roomMembers[socket.room] = []; 36 | } 37 | roomMembers[socket.room].push(data.nickname); 38 | updateRoomMembers(socket.room); 39 | 40 | 41 | }); 42 | 43 | socket.on('getRoomClients', function () { 44 | io.sockets.to(socket.nickname).emit("message", {type: "get_user_list", data: roomMembers[socket.room]}); 45 | }) 46 | 47 | socket.on('sendMessage', function (message) { 48 | io.sockets.to(socket.room).emit("message", { 49 | type: "get_message", 50 | data: {nickname: socket.nickname, message: message} 51 | }) 52 | }); 53 | 54 | 55 | } 56 | 57 | function updateRoomMembers(room) { 58 | 59 | } 60 | 61 | 62 | --------------------------------------------------------------------------------