Asterisk WebRTC frontier: make client SIP Phone with sipML5 - Janus Gateway
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Polidori, Alessandro
We will analyze the steps to make audio & video communications (as SIP Phone WebRTC) into your WebApp, exploiting Asterisk WebRTC techology. The talk shows pros e cons of two different implementations: one using sipML5 library and one with Janus Gateway. Asterisk WebRTC technology open huge scenarios of applications for unified communications. In this session we will look at that technology to make a SIP Phone WebRTC directly integrated into your web browser to provide a real-time audio & video communication WebApp that serves hundreds of contemporary calls. We will consider two different solutions, sipML5 and Janus Gateway, showing pros and cons of both solutions.
 Thanks for being here. Thank you to you. It's a pleasure. Okay. Thanks for coming. And I'm going to explain how you can make a C-phone into your browser to make audio and video calls. And we are going to use WebRTC technologies with Asterisk and two different libraries. One is CPML5 and one is Janus Gateway. I'm Alessandro Polidori and I'm a senior software engineer at NetEase that is an Italian open source company. Here are some of my contacts. Okay. First of all, let's start speaking something about WebRTC. As the word suggests, it enables a communication between browsers in real-time peer-to-peer fashion. And it's not a single technology but a set of different technologies. It is composed by three fundamental APIs that are GetUserMedia, RTC, PeerConnection and RTC data channel. The first is used to access your media devices. The second does some operations such as the data negotiation. And the third does the real-time communication, the data transfer. Other API exists but it's not important for this talk. So some real-time protocols are used, some for the data transmission and other for the signal here. And in particular, we need some signal to negotiate and establish a session before the data transmission. And the most used protocol in this field is the SIP protocol. We can achieve the security to have encryption and message authenticity using the circumversion of the protocol. SDP is used to describe the session before the data transmission. And other protocols are used to overcome some network problems related to the NAT. For example, STAN is used to get your public IP address outside your local network. And the term does the media relay of all traffic. So it requires a lot of bandwidth. OK, this is the overall architecture of the system. And we can see from this picture that there are many components. And the two most important are the web application and the server PBX. But we're interested only on the web application because we want to make a SIP phone into the browser to make audio and video calls. OK, codec are another fundamental part. In the audio section, the most used are OPPOS and G711. And in the video section are the H264 and VP8. VP9 is not completely supported by the browsers. And AV1 seems to be the future. We at NetEase have made a FOSWitchWars system called NetVoice and NetCTI on top of it. That is a web application with the integrated web RTC phone to make the calls. During the years, we have made two different implementations in production on some thousands of customers. And now we are going to see the implementation that uses CipML5. CipML5 is a JavaScript library and it has been the first implementation of an HTML5 CIP client. It was presented at Google IE in 2012 and its characteristics are that it's 100% for JavaScript. It realizes a media stack, of course, based on WebRTC. It uses Cip protocol over WebSocket for the signaling. And with it, you can make audio video calls, but not only. You can realize also an instant messaging or scree sharing and so on. And it supports both desktop and mobile platforms. OK, this is the overall architecture that we have used, realizing the Cip phone with CipML5. The HTML5 client realizes both SDP and Cip stack that we have previously seen. And the SDP described the session, for example, which audio codec will be used. And Cip realized all the Cip stack that communicates over WebSocket transport. And after the session has been established, all the media data transmission is exchanged using some protocols and using WebRTC technologies. All of these components communicate with NetVoice PBX. OK. Now we are going to see how to implement a Cip phone using CipML5 with only four steps. So first of all, you have to initialize the engine. In this case, there is the global JavaScript object called CipML, and we call the init method. Then we start the Cip stack. At this point, we can register the phone extension to the server PBX, calling the new session API. And at the end, we can make a new audio and video call. OK. Some more code. Let's see it in more detail. First of all, of course, is the inclusion of the JavaScript library, only one file. Then we initialize the engine. So we call the init function, passing to it two parameters, two callbacks, one to manage the success of the operation and one for the failure. And if it all goes well, we are going to create the Cip stack, to start the Cip stack. And the parameters needed are the server address that can be on the cloud, and you can realize, for example, a cloud phone, or also on-premise. Then we pass the Cip extension URI that is composed by the protocol Cip, the extension Cip identifier, and the server address, the password of the extension. Pay attention to it, because we can find some scripts that try to register an extension with some simple passwords and make phone calls to some payment number. So it's very important to choose it carefully. The display name is the name that has been shown in the display of the phone when an incoming call arrives. And the WebSocket URL. The WebSocket URL contains customized port, 89, that obviously has to be reachable by the client, and the WebSocket secure protocol, so all the traffic is encrypted. We can attach an event listener to manage all the related events and call the start on the just created Cip stack. At this point, we register the phone extension, calling the new session API on the just created Cip stack, and passing to it the word register and other event listeners to manage the related events. And at the final, we call the register function. Here it is. At this point, if all goes well, we can make a new phone call, calling the new session function on the just created Cip stack, and passing to it some parameters that are only the HTML elements, so all uses Web standards. And at the end, we can make a new phone call. That's it. Okay. During the years, we have decided to switch the implementation of the Cifon using Janus Gateway. Okay. We're going to see this implementation. Janus is a general purpose gateway by Mithico Company, and it's a WebRTC gateway. Okay. It uses the JSON standard format for messages exchange. Its architecture is made by plug-in. We have used only the Cip plug-in, but other plug-in exists, of course. It provides some interfaces for communication and other tools for monitoring that are very, very important in production. In this picture, we can see the differences from that of CipML5, because previously CipML5 communicated directly with Asterisk. But now, the Janus client communicates with Janus Gateway component that is a backend component which in turn communicates with Asterisk using the Cip protocol. And all of this traffic is proxy passed by Apache Web server, and all traffic is encrypted, of course. The advantage of this architecture is that now we don't worry anymore about the change in the canalize from the development, the evolving of the WebRTC technology, because Janus takes care of it. Okay. Now we are going to see how to implement the Cifon using Janus. So also in this case, four steps are needed. The initialization of the engine. Now the JavaScript global object is called Janus. We create a session, attach a Cplugin. Only Cplugin is used, but other plugins exist. And at the end, we can make a new call creating a new offer. Okay. Let's go deeper to see more details. The inclusion of the library, we need only two libraries. One is Janus, of course, and another one is the adapter that resolves all WebRTC differences between different browsers. We initialize the engine calling the init method, passing to it the debug level and the callback function. And then we create a new session. Notice that now the server address uses the standard HTTPS port, so you don't need to open another port on the server, all using Web standards. And then we pass other callbacks as parameters. And at this point, we can attach the Cplugin to have a plugin handler to make a new phone call. In this slide, I deliberately cut off the code to generate confusion. So other callbacks as past as parameters. And at the end, if all goes well, we can make a new phone call invoking the create offer function on the just created plugin Cpendler. And we can specify the destination of the call. That's it. Now some few words about the server PB expert, because in this case, are another fundamental part to make the old components functioning. In this talk, I've used NetServer VoIP PBX that is based on Asterisk, free PBX project, and NetServer Linux distribution that is a completely open source available on GitHub. It has also a community of enthusiastic people that you can find it on community.netserver.org. You can participate in the project in whatever manner you want. And the enterprise version of the NetVoice, the switchboard system, is called NetVoice. And the next CTI on top of it, that is a web application with WebRTC phone. To give you an environment to start playing with WebRTC, I've created a virtual box machine that you can easily run using Vagrant. I give you a link in the next slide to know how you can easily run your private PBX at your home. Now I would like to show you an open source demo of an HTML5 SIP client to better understand what we have seen until now. So to recap, two steps are needed. We are going to run a server PBX, and for this you have to do only three operations. Clone the GitHub repository, skip into it, and run Vagrant up. At this point you have your server PBX completely configured. And we are going to open the WebRTC demo at this URL. Then we can insert some default values that you can find on GitHub. The parameters are the server address, the display name, extension identifier, and the password. Then I'm going to log in to click the login button to register the phone extension into the server PBX. And at this point we can make a phone call, of course, clicking the call button. And we will see a remote and local video. Call is on my local machine, of course, for simplicity. Cool. Okay, this is one session. Okay, I've already inserted the data and run in my own private server PBX on my local machine. So we specify the server address, the display name, extension and password. So in this session, I'm going to insert the extension 200 and login to the server PBX. At this point, the phone extension is registered and completely working. In another session, I insert the extension 201 and login. And at this point, I can make a new call to the extension 200, audio and video. Okay. Here I click the answer button and I have a new audio video call. Obviously, this is the remote part and other are my local part. It's the same image, of course, because all is in local machine. Okay. Okay, come back to presentation for a few slides. Okay, this slide is to show you only to understand that with WebRTC, you can make a real product for your customer. So this is the net CTI made by NetEase to make new audio video call with WebRTC. It abstracts many devices into one single user using a customized layer of REST API. That is independent from the specific version of the Asterisk. Okay, as I promised you, this is two links. The first contains all the important related links of this talk. And the second is a very interesting WebRTC blog made by Taki Levent Levy. Okay, it's very interesting. And if you want to discuss something about WebRTC, some development of the server or whatever, everything else, this is, these are all some of my contacts and I will be very happy to talk with you. Thank you. We do have time for a couple of questions, I believe. So does anybody have a question? Probably a stupid question, but Janus is not using IE or Sturner of Turn, is that correct? Yes, Janus can use IE and Sturn server. It depends on your network topology. For example, in this case, I have my local machine, so I configure Janus to operate in a NAT mode. But if you are connected to the Internet, you are behind a NAT, for example, you configure Janus differently and it can connect to some Sturn server to have your public IP address outside your local area network to make all functions. Of course, in some cases, you can have some problems, okay, it depends on your network topology. And you can use also a Turn server to relay all the media traffic. Of course, in this case, the Turn server requires a lot of bandwidth because it relay all the audio and video, very important for bandwidth, video traffic. Okay. You can have different configurations of Janus Gateway. So, for curious about the CPML-5, the project now, still by the Dubango project or how it's maintained these days? It was started by Dubango Telecom, that is a French company. Then also Google promoted it in about 2012. I don't know very well the details of what is the maintainer, but is present on GitHub. And I think that I think some Google developers works on it. I don't know very well, but probably also Dubango works on it. Thank you.
 Thanks for being here.  Thank you to you.  It's a pleasure.  Okay.  Thanks for coming.  And I'm going to explain how you can make a C-phone into your browser to make audio  and video calls.  And we are going to use WebRTC technologies with Asterisk and two different libraries.  One is CPML5 and one is Janus Gateway.  I'm Alessandro Polidori and I'm a senior software engineer at NetEase that is an Italian open  source company.  Here are some of my contacts.  Okay.  First of all, let's start speaking something about WebRTC.  As the word suggests, it enables a communication between browsers in real-time peer-to-peer  fashion.  And it's not a single technology but a set of different technologies.  It is composed by three fundamental APIs that are GetUserMedia, RTC, PeerConnection and  RTC data channel.  The first is used to access your media devices.  The second does some operations such as the data negotiation.  And the third does the real-time communication, the data transfer.  Other API exists but it's not important for this talk.  So some real-time protocols are used, some for the data transmission and other for the  signal here.  And in particular, we need some signal to negotiate and establish a session before the  data transmission.  And the most used protocol in this field is the SIP protocol.  We can achieve the security to have encryption and message authenticity using the circumversion  of the protocol.  SDP is used to describe the session before the data transmission.  And other protocols are used to overcome some network problems related to the NAT.  For example, STAN is used to get your public IP address outside your local network.  And the term does the media relay of all traffic.  So it requires a lot of bandwidth.  OK, this is the overall architecture of the system.  And we can see from this picture that there are many components.  And the two most important are the web application and the server PBX.  But we're interested only on the web application because we want to make a SIP phone into the  browser to make audio and video calls.  OK, codec are another fundamental part.  In the audio section, the most used are OPPOS and G711.  And in the video section are the H264 and VP8.  VP9 is not completely supported by the browsers.  And AV1 seems to be the future.  We at NetEase have made a FOSWitchWars system called NetVoice and NetCTI on top of it.  That is a web application with the integrated web RTC phone to make the calls.  During the years, we have made two different implementations in production on some thousands  of customers.  And now we are going to see the implementation that uses CipML5.  CipML5 is a JavaScript library and it has been the first implementation of an HTML5  CIP client.  It was presented at Google IE in 2012 and its characteristics are that it's 100% for  JavaScript.  It realizes a media stack, of course, based on WebRTC.  It uses Cip protocol over WebSocket for the signaling.  And with it, you can make audio video calls, but not only.  You can realize also an instant messaging or scree sharing and so on.  And it supports both desktop and mobile platforms.  OK, this is the overall architecture that we have used, realizing the Cip phone with  CipML5.  The HTML5 client realizes both SDP and Cip stack that we have previously seen.  And the SDP described the session, for example, which audio codec will be used.  And Cip realized all the Cip stack that communicates over WebSocket transport.  And after the session has been established, all the media data transmission is exchanged  using some protocols and using WebRTC technologies.  All of these components communicate with NetVoice PBX.  OK.  Now we are going to see how to implement a Cip phone using CipML5 with only four steps.  So first of all, you have to initialize the engine.  In this case, there is the global JavaScript object called CipML, and we call the init  method.  Then we start the Cip stack.  At this point, we can register the phone extension to the server PBX, calling the new  session API.  And at the end, we can make a new audio and video call.  OK.  Some more code.  Let's see it in more detail.  First of all, of course, is the inclusion of the JavaScript library, only one file.  Then we initialize the engine.  So we call the init function, passing to it two parameters, two callbacks, one to manage  the success of the operation and one for the failure.  And if it all goes well, we are going to create the Cip stack, to start the Cip stack.  And the parameters needed are the server address that can be on the cloud, and you can realize,  for example, a cloud phone, or also on-premise.  Then we pass the Cip extension URI that is composed by the protocol Cip, the extension  Cip identifier, and the server address, the password of the extension.  Pay attention to it, because we can find some scripts that try to register an extension  with some simple passwords and make phone calls to some payment number.  So it's very important to choose it carefully.  The display name is the name that has been shown in the display of the phone when an  incoming call arrives.  And the WebSocket URL.  The WebSocket URL contains customized port, 89, that obviously has to be reachable by  the client, and the WebSocket secure protocol, so all the traffic is encrypted.  We can attach an event listener to manage all the related events and call the start  on the just created Cip stack.  At this point, we register the phone extension, calling the new session API on the just created  Cip stack, and passing to it the word register and other event listeners to manage the related  events.  And at the final, we call the register function.  Here it is.  At this point, if all goes well, we can make a new phone call, calling the new session  function on the just created Cip stack, and passing to it some parameters that are only  the HTML elements, so all uses Web standards.  And at the end, we can make a new phone call.  That's it.  Okay.  During the years, we have decided to switch the implementation of the Cifon using Janus  Gateway.  Okay.  We're going to see this implementation.  Janus is a general purpose gateway by Mithico Company, and it's a WebRTC gateway.  Okay.  It uses the JSON standard format for messages exchange.  Its architecture is made by plug-in.  We have used only the Cip plug-in, but other plug-in exists, of course.  It provides some interfaces for communication and other tools for monitoring that are very,  very important in production.  In this picture, we can see the differences from that of CipML5, because previously CipML5  communicated directly with Asterisk.  But now, the Janus client communicates with Janus Gateway component that is a backend  component which in turn communicates with Asterisk using the Cip protocol.  And all of this traffic is proxy passed by Apache Web server, and all traffic is encrypted,  of course.  The advantage of this architecture is that now we don't worry anymore about the change  in the canalize from the development, the evolving of the WebRTC technology, because  Janus takes care of it.  Okay.  Now we are going to see how to implement the Cifon using Janus.  So also in this case, four steps are needed.  The initialization of the engine.  Now the JavaScript global object is called Janus.  We create a session, attach a Cplugin.  Only Cplugin is used, but other plugins exist.  And at the end, we can make a new call creating a new offer.  Okay.  Let's go deeper to see more details.  The inclusion of the library, we need only two libraries.  One is Janus, of course, and another one is the adapter that resolves all WebRTC differences  between different browsers.  We initialize the engine calling the init method, passing to it the debug level and  the callback function.  And then we create a new session.  Notice that now the server address uses the standard HTTPS port, so you don't need to  open another port on the server, all using Web standards.  And then we pass other callbacks as parameters.  And at this point, we can attach the Cplugin to have a plugin handler to make a new phone  call.  In this slide, I deliberately cut off the code to generate confusion.  So other callbacks as past as parameters.  And at the end, if all goes well, we can make a new phone call invoking the create offer  function on the just created plugin Cpendler.  And we can specify the destination of the call.  That's it.  Now some few words about the server PB expert, because in this case, are another fundamental  part to make the old components functioning.  In this talk, I've used NetServer VoIP PBX that is based on Asterisk, free PBX project,  and NetServer Linux distribution that is a completely open source available on GitHub.  It has also a community of enthusiastic people that you can find it on community.netserver.org.  You can participate in the project in whatever manner you want.  And the enterprise version of the NetVoice, the switchboard system, is called NetVoice.  And the next CTI on top of it, that is a web application with WebRTC phone.  To give you an environment to start playing with WebRTC, I've created a virtual box machine  that you can easily run using Vagrant.  I give you a link in the next slide to know how you can easily run your private PBX at  your home.  Now I would like to show you an open source demo of an HTML5 SIP client to better understand  what we have seen until now.  So to recap, two steps are needed.  We are going to run a server PBX, and for this you have to do only three operations.  Clone the GitHub repository, skip into it, and run Vagrant up.  At this point you have your server PBX completely configured.  And we are going to open the WebRTC demo at this URL.  Then we can insert some default values that you can find on GitHub.  The parameters are the server address, the display name, extension identifier, and the  password.  Then I'm going to log in to click the login button to register the phone extension into  the server PBX.  And at this point we can make a phone call, of course, clicking the call button.  And we will see a remote and local video.  Call is on my local machine, of course, for simplicity.  Cool.  Okay, this is one session.  Okay, I've already inserted the data and run in my own private server PBX on my local machine.  So we specify the server address, the display name, extension and password.  So in this session, I'm going to insert the extension 200 and login to the server PBX.  At this point, the phone extension is registered and completely working.  In another session, I insert the extension 201 and login.  And at this point, I can make a new call to the extension 200, audio and video.  Okay.  Here I click the answer button and I have a new audio video call.  Obviously, this is the remote part and other are my local part.  It's the same image, of course, because all is in local machine.  Okay.  Okay, come back to presentation for a few slides.  Okay, this slide is to show you only to understand that with WebRTC, you can make a real product for your customer.  So this is the net CTI made by NetEase to make new audio video call with WebRTC.  It abstracts many devices into one single user using a customized layer of REST API.  That is independent from the specific version of the Asterisk.  Okay, as I promised you, this is two links.  The first contains all the important related links of this talk.  And the second is a very interesting WebRTC blog made by Taki Levent Levy.  Okay, it's very interesting.  And if you want to discuss something about WebRTC, some development of the server or whatever, everything else,  this is, these are all some of my contacts and I will be very happy to talk with you.  Thank you.  We do have time for a couple of questions, I believe. So does anybody have a question?  Probably a stupid question, but Janus is not using IE or Sturner of Turn, is that correct?  Yes, Janus can use IE and Sturn server. It depends on your network topology.  For example, in this case, I have my local machine, so I configure Janus to operate in a NAT mode.  But if you are connected to the Internet, you are behind a NAT, for example, you configure Janus differently  and it can connect to some Sturn server to have your public IP address outside your local area network to make all functions.  Of course, in some cases, you can have some problems, okay, it depends on your network topology.  And you can use also a Turn server to relay all the media traffic.  Of course, in this case, the Turn server requires a lot of bandwidth because it relay all the audio and video,  very important for bandwidth, video traffic.  Okay.  You can have different configurations of Janus Gateway.  So, for curious about the CPML-5, the project now,  still by the Dubango project or how it's maintained these days?  It was started by Dubango Telecom, that is a French company.  Then also Google promoted it in about 2012.  I don't know very well the details of what is the maintainer, but is present on GitHub.  And I think that I think some Google developers works on it.  I don't know very well, but probably also Dubango works on it.  Thank you.
Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__0_155.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__156_935.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__936_1163.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__1164_2195.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__2196_3407.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__3408_4019.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__4020_8075.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__8076_8171.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__8172_8303.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__8304_8747.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__8748_13895.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__13896_14627.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__14628_15035.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__15036_15215.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__15216_15707.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__15708_16007.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__16008_18947.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__18948_19535.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__19536_21287.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__21288_21407.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__21408_21647.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__21648_22211.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__22212_24227.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24228_24503.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24504_24587.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24588_24635.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24636_24743.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24744_24815.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__24816_25487.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__25488_25919.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__25920_30107.png Asterisk_WebRTC_frontier__make_client_SIP_Phone_with_sipML5_and_Janus_Gateway_Analyzing_a_real_proj__30108_30255.png