diff --git a/FunctionalTests/src/FunctionalTests.mxml b/FunctionalTests/src/FunctionalTests.mxml index 69d2538..fda7074 100644 --- a/FunctionalTests/src/FunctionalTests.mxml +++ b/FunctionalTests/src/FunctionalTests.mxml @@ -49,7 +49,7 @@ group.children.push(new RTMPBadRequests(this, hostDefault)); group.children.push(new RTMPLoad(this, hostDefault, applicationDefault, "RTMP")); group.children.push(new RTMPLoad(this, hostDefault, applicationDefault, "RTMPE")); - // TODO : group.children.push(new RTMPp2p(this, hostDefault, applicationDefault)); + group.children.push(new RTMPp2p(this, hostDefault, applicationDefault)); mapTests.push(group); group = new Test(this, "RTMFP", "List of RTMFP tests", true); group.children.push(new RTMFPLoad(this, hostDefault, applicationDefault)); diff --git a/FunctionalTests/src/RTMPp2p.as b/FunctionalTests/src/RTMPp2p.as new file mode 100644 index 0000000..436089b --- /dev/null +++ b/FunctionalTests/src/RTMPp2p.as @@ -0,0 +1,122 @@ +package +{ + import flash.events.Event; + import flash.events.NetStatusEvent; + import flash.events.TimerEvent; + import flash.net.NetConnection; + import flash.net.NetStream; + import flash.utils.ByteArray; + import flash.utils.Timer; + + public class RTMPp2p extends Test + { + private var _fullUrl:String; + private var _nc1:NetConnection = null; + private var _nc2:NetConnection = null; + + private var _tabNs:Array = new Array(); + + private var _nbPublishers:int=0; + private var _nbSubscribers:int=0; + + public function RTMPp2p(app:FunctionalTests, host:String, url:String) + { + super(app, "RTMPp2p", "Test p2p connections/deconnections between RTMP peers"); + _fullUrl = "rtmp://" + host + url; + } + + override public function run(onFinished:Function):void { + + super.run(onFinished); + + // Connect the 2 peers + _nc1 = new NetConnection(); + _nc1.addEventListener(NetStatusEvent.NET_STATUS, onStatus); + _nc1.connect(_fullUrl); + _nc2 = new NetConnection(); + _nc2.addEventListener(NetStatusEvent.NET_STATUS, onStatus); + _nc2.connect(_fullUrl); + + _nbPublishers=0; + _nbSubscribers=0; + } + + // Proper finished test + private function closeAll():void { + _nc1.removeEventListener(NetStatusEvent.NET_STATUS, onStatus); + _nc1.close(); + _nc1=null; + _nc2.removeEventListener(NetStatusEvent.NET_STATUS, onStatus); + _nc2.close(); + _nc2=null; + } + + public function onStatus(event:NetStatusEvent):void { + + _app.INFO("onStatus : "+event.info.code); + + switch(event.info.code) { + case "NetConnection.Connect.Success": + + // Begin publishing + var publisher:NetStream = new NetStream(NetConnection(event.target)); + publisher.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); + publisher.publish((event.target==_nc1)? "stream1" : "stream2"); + _tabNs.push(publisher); + + break; + default: // Disconnection + closeAll(); + onResult({err:"Unexpected event : "+event.info.code}); + } + } + + private function netStatusHandler(event:NetStatusEvent):void { + + switch(event.info.code) { + case "NetStream.Publish.Start": + _nbPublishers++; + + // All publishers are ready? => play + if (_nbPublishers==2) { + _app.INFO("Subscribing to stream1 and stream2..."); + + var subscriber1:NetStream = new NetStream(_nc1); + subscriber1.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); + subscriber1.play("stream2"); + _tabNs.push(subscriber1); + + var subscriber2:NetStream = new NetStream(_nc2); + subscriber2.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); + subscriber2.play("stream1"); + _tabNs.push(subscriber2); + } + break; + case "NetStream.Play.Start": + _nbSubscribers++; + + // All subscribtions OK? => subscribe a second time to stream1 + if (_nbSubscribers==2) { + _app.INFO("Subscribing a second time to stream1..."); + var subscriber:NetStream = new NetStream(_nc2); + subscriber.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); + subscriber.play("stream1"); + _tabNs.push(subscriber); + } else if (_nbSubscribers==3) { + _app.INFO("Closing connection 2..."); + _nc2.close(); + } + break; + case "NetStream.Play.Failed": + closeAll(); + if (_nbSubscribers==2) // Second subscription failed : Test OK! + onResult({}); + else + onResult({err:"Unexpected failed event (publishers : "+_nbPublishers+" ; subscribers : "+_nbSubscribers+")"}); + break; + default: + break; + } + } + } +} \ No newline at end of file diff --git a/FunctionalTests/www/FunctionalTests/FunctionalTests.swf b/FunctionalTests/www/FunctionalTests/FunctionalTests.swf index 9834541..5c9b2ee 100644 Binary files a/FunctionalTests/www/FunctionalTests/FunctionalTests.swf and b/FunctionalTests/www/FunctionalTests/FunctionalTests.swf differ diff --git a/MonaCore/sources/Publication.cpp b/MonaCore/sources/Publication.cpp index 11c616f..d1df243 100644 --- a/MonaCore/sources/Publication.cpp +++ b/MonaCore/sources/Publication.cpp @@ -51,7 +51,8 @@ Listener* Publication::addListener(Exception& ex, Client& client,Writer& writer) map::iterator it = _listeners.lower_bound(&client); if(it!=_listeners.end() && it->first==&client) { WARN("Already subscribed for publication ",_name); - return it->second; + ex.set(Exception::APPLICATION,"Already subscribed to ",_name); + return NULL; } if(it!=_listeners.begin()) --it; diff --git a/clients/samples/Meeting/VideoMeeting.swf b/clients/samples/Meeting/VideoMeeting.swf index e1603b0..0fb9723 100644 Binary files a/clients/samples/Meeting/VideoMeeting.swf and b/clients/samples/Meeting/VideoMeeting.swf differ diff --git a/clients/samples/Meeting/main.lua b/clients/samples/Meeting/main.lua index e8b4848..8b84176 100644 --- a/clients/samples/Meeting/main.lua +++ b/clients/samples/Meeting/main.lua @@ -3,23 +3,17 @@ meeters = {} function onConnection(client, userName, meeting) - if client.protocol == "RTMFP" or client.protocol == "RTMP" then - meeter = {} - meeter.userName = userName - meeter.meeting = meeting - - INFO("User connected: ", meeter.userName , " meeting: ", meeter.meeting) - - sendParticipantUpdate(meeter.meeting) - meeters[client] = meeter -- Add participant to the list - end - - function client:onRead(file) - if file == "" and client.protocol == "HTTP" then -- If file empty => return VideoMeeting.html - return "VideoMeeting.html" - end - end - + if client.protocol == "RTMFP" or client.protocol == "RTMP" then + meeter = {} + meeter.userName = userName + meeter.meeting = meeting + + INFO("User connected: ", meeter.userName , " meeting: ", meeter.meeting) + + sendParticipantUpdate(meeter.meeting) + meeters[client] = meeter -- Add participant to the list + end + function client:getParticipants(meeting) result = {} i = 0; @@ -44,6 +38,8 @@ function onConnection(client, userName, meeting) end end end + + return {index="VideoMeeting.html"} end function onDisconnection(client) diff --git a/doc/_static/time-system-preferences-icone-8704-48.png b/doc/_static/time-system-preferences-icone-8704-48.png new file mode 100644 index 0000000..81bb3da Binary files /dev/null and b/doc/_static/time-system-preferences-icone-8704-48.png differ diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html index a534ce0..7759bad 100644 --- a/doc/_templates/layout.html +++ b/doc/_templates/layout.html @@ -27,5 +27,12 @@ {# Add Mona's presentation from googledoc #} {% if pagename == 'quickstart' %} + {% elif pagename == 'contacts' %} +
+ + + + +
{% endif %} {% endblock %} \ No newline at end of file diff --git a/doc/api.rst b/doc/api.rst index b29bc99..4e024ba 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -675,10 +675,14 @@ Otherwise you can cutomize this message in raising one error in this context. .. code-block:: lua - function onPublish(client,publication) + function client:onPublish(publication) if not client.right then error("no rights to publish it") end + + function publication:onData(time,packet) + -- write code here + end end .. code-block:: as3 diff --git a/doc/conf.py b/doc/conf.py index 26f0348..9b99f84 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -122,7 +122,8 @@ 'navbar_links': [ (" Quick Start", "quickstart"), (" FAQ", "faq"), - (" Support", "contacts"), + (" Services", "contacts"), + (" Roadmap", "roadmap"), (" Documentation", "manual"), ], diff --git a/doc/contacts.rst b/doc/contacts.rst index f21ff08..5ba46cc 100644 --- a/doc/contacts.rst +++ b/doc/contacts.rst @@ -1,10 +1,10 @@ -Support & Contacts +Services & Contacts ############################## .. contents:: Table of Contents -Contacts +About us ******************************************* We are 2 french engineers specialists of c++11 and server communication. @@ -32,12 +32,51 @@ Thomas Jammet **Linkedin:** http://fr.linkedin.com/pub/thomas-jammet/5a/411/60b/ ================================ =================================================================== -Support +Development ******************************************* -If you are looking for a commercial licence or want to build a project based on Mona and you want some support please contact us by mail (mathieupoux@gmail.com or jammetthomas@gmail.com). +Mona is our full-time project. We develop according to our funding, trying to follow the `Roadmap <./roadmap.html>`_. +But we can also personalize Mona to your needs, or extend its features for your systems. +Or we can simply assist you and advise you in the deployment and the usage of Mona on your environment. -To report a bug or ask any question you can also use the `Github issue page`_. +Professional Support +******************************************* + +We are currently working on our support agreement document, so please contact jammetthomas@gmail.com if you are interested. The expected contract : + + ++------------------------------+--------------------------------+ +| | Professional Support | ++==============================+================================+ +| Max. initial response time | 3 business days | ++------------------------------+--------------------------------+ +| Price for 12 months | EUR 400 (approx. US-$ 489) | ++------------------------------+--------------------------------+ + + +Licence +******************************************* + +Mona is licensed under the `GNU General Public License`_. + +But if you are looking for a commercial licence or you want to build a project based on Mona we offer : + +EUR 5000 (approx. US-$ 6116) + +Please contact us mathieupoux@gmail.com or jammetthomas@gmail.com + + +Basic Support +******************************************* + +Mona is an open source collaborative project hosted on github, so you can participate to the development if you share your modifications (GPL). +You can also use the forum_ for questions and the `Github issue page`_ to report bugs. +Nevertheless we do not guarantee any response delay. + +Please remember that our development is open source, so contributions are greatly appreciated : + +.. _`GNU General Public License` : http://www.gnu.org/licenses/ .. _`Github issue page` : https://github.com/MonaSolutions/MonaServer/issues -.. _Cumulus : https://github.com/OpenRTMFP/Cumulus \ No newline at end of file +.. _Cumulus : https://github.com/OpenRTMFP/Cumulus +.. _forum : https://groups.google.com/forum/#!forum/monaserver \ No newline at end of file diff --git a/doc/index.rst b/doc/index.rst index 3f9a5d0..e070ca4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -23,7 +23,7 @@ Mona currently supports the following protocols: - **HTTP** (with **JSON-RPC** and XML-RPC_), **Websocket**. We expect to add many other protocols, such as **WebRTC**, **HLS**, **IPTV**, but please remember that our development is open source -so contributions are greatly appreciated: `us`_, `eu`_. +so contributions are greatly appreciated: `$`_, `€`_. Mona is licensed under the `GNU General Public License`_, please contact us for a commercial licence at mathieupoux@gmail.com or jammetthomas@gmail.com. @@ -39,6 +39,6 @@ For some samples running on a `Raspberry Pi`_ please visit the `Samples page <./ .. _LuaJIT : http://luajit.org/ .. _XML-RPC : http://xmlrpc.scripting.com/spec.html .. _`GNU General Public License` : http://www.gnu.org/licenses/ -.. _`us` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=M24B32EH2GV3A -.. _`eu` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QPWT9V67YWSGG +.. _`$` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=M24B32EH2GV3A +.. _`€` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QPWT9V67YWSGG .. _`Raspberry Pi` : http://www.raspberrypi.org/ \ No newline at end of file diff --git a/doc/installation.rst b/doc/installation.rst index 88981b2..06d73db 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -9,10 +9,9 @@ We would like to remind you that Mona is licensed under the `GNU General Public Binaries *********************************** -.. TODO -.. A `32-bit Windows binary `_ has been provided to quickly test MonaServer. We recommend -.. you compile a Linux version from the sources for production use. If you download the Windows 32-bit binary, then you can skip down to the -.. *Configurations* section of this document. +A `32-bit Windows binary `_ is provided to quickly test MonaServer. +We recommend you to clone the github version from the sources for production use. +If you download the Windows 32-bit binary, then you can skip down to the *Configurations* section of this document. Download *********************************** @@ -80,22 +79,12 @@ To build Mona: .. code-block:: sh - cd MonaBase - make - cd ../MonaCore - make - cd ../MonaServer - make + $ make To clean: .. code-block:: sh - $ cd MonaBase - $ make clean - $ cd ../MonaCore - $ make clean - $ cd ../MonaServer $ make clean Amazon EC2 AMI Build @@ -116,13 +105,6 @@ Connect to the AMI and execute the following script: wget https://github.com/MonaSolutions/MonaServer/archive/master.zip unzip Mona-master.zip cd Mona-master - cd MonaBase - make - cd .. - cd MonaCore - make - cd .. - cd MonaServer make sudo ./MonaServer --daemon diff --git a/doc/roadmap.rst b/doc/roadmap.rst new file mode 100644 index 0000000..6b89676 --- /dev/null +++ b/doc/roadmap.rst @@ -0,0 +1,19 @@ + +Roadmap +############################## + +Mona is our full-time project. We develop according to our funding, trying to follow the following **Roadmap**. +Here are listed the future evolutions of MonaServer and the time of development expected. +If you want to finance/accelerate a specific development you can contact us at mathieupoux@gmail.com or jammetthomas@gmail.com. +You can also make a donation for the project to allow us to continue the development : `$`_, `€`_. + +================================ =================================================================== ================================ +Name Details of the feature Time required +================================ =================================================================== ================================ +Recording Adding asynchronous recording feature using IOCP, libkqueue... 5 weeks +-------------------------------- ------------------------------------------------------------------- -------------------------------- +SSL Support To support HTTPS, WenSocketSSL and RTMPS 3 weeks +================================ =================================================================== ================================ + +.. _`$` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=M24B32EH2GV3A +.. _`€` : https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QPWT9V67YWSGG \ No newline at end of file