Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / server / supernova / utilities / osc_server.hpp
blob92d35333a118c9430ff8680306cd41d43555e40f
1 // osc responder class
2 // Copyright (C) 2008 Tim Blechmann
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; see the file COPYING. If not, write to
16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 // Boston, MA 02111-1307, USA.
19 #ifndef OSC_SERVER_HPP
20 #define OSC_SERVER_HPP
22 #include <string>
23 #include <iostream>
24 #include <thread>
26 #include <boost/asio.hpp>
27 #include <boost/array.hpp>
28 #include <boost/bind.hpp>
30 #include "branch_hints.hpp"
31 #include "osc_dispatcher.hpp"
33 #include "static_allocator.hpp"
34 #include "nova-tt/semaphore.hpp"
35 #include "nova-tt/thread_priority.hpp"
36 #include "nova-tt/name_thread.hpp"
38 namespace nova {
40 namespace detail {
41 using namespace boost::asio;
42 using namespace boost::asio::ip;
44 class network_thread
46 public:
47 void start_receive(void)
49 thread_ = std::move(std::thread(network_thread::start, this));
50 sem.wait();
53 ~network_thread(void)
55 if (!thread_.joinable())
56 return;
57 io_service_.stop();
58 thread_.join();
61 io_service & get_io_service(void)
63 return io_service_;
66 void send_udp(const char * data, unsigned int size, udp::endpoint const & receiver)
68 udp::socket socket(io_service_);
69 socket.open(udp::v4());
70 socket.send_to(boost::asio::buffer(data, size), receiver);
73 private:
74 static void start(network_thread * self)
76 #ifdef NOVA_TT_PRIORITY_RT
77 thread_set_priority_rt(thread_priority_interval_rt().first);
78 #endif
79 name_thread("Network Receive");
80 self->run();
83 void run(void)
85 sem.post();
87 io_service::work work(io_service_);
88 io_service_.run();
91 protected:
92 io_service io_service_;
94 private:
95 semaphore sem;
96 std::thread thread_;
99 class osc_server:
100 private network_thread,
101 private osc_dispatcher
103 public:
104 osc_server(unsigned int port):
105 socket_(network_thread::io_service_, udp::endpoint(udp::v4(), port))
107 network_thread::start_receive();
108 start_receive();
111 void add_responder(std::string const & address, osc_responder * resp)
113 osc_dispatcher::add_responder(address, resp);
116 void remove_responder(std::string const & address, osc_responder * resp)
118 osc_dispatcher::remove_responder(address, resp);
121 private:
122 void start_receive(void)
124 socket_.async_receive_from(
125 buffer(recv_buffer_), remote_endpoint_,
126 boost::bind(&osc_server::handle_receive, this,
127 placeholders::error, placeholders::bytes_transferred));
130 void handle_receive(const boost::system::error_code& error,
131 std::size_t bytes_transferred)
133 if (unlikely(error == error::operation_aborted))
134 return; /* we're done */
136 if (error == error::message_size)
138 overflow_vector.insert(overflow_vector.end(),
139 recv_buffer_.begin(), recv_buffer_.end());
140 return;
143 if (error)
145 std::cout << "osc_server received error code " << error << std::endl;
146 start_receive();
147 return;
150 if (overflow_vector.empty())
151 osc_dispatcher::handle_packet(recv_buffer_.begin(), bytes_transferred);
152 else
154 overflow_vector.insert(overflow_vector.end(),
155 recv_buffer_.begin(), recv_buffer_.end());
157 osc_dispatcher::handle_packet(overflow_vector.data(), overflow_vector.size());
159 overflow_vector.clear();
162 start_receive();
163 return;
166 udp::socket socket_;
167 boost::array<char, 1<<13 > recv_buffer_;
168 udp::endpoint remote_endpoint_;
170 typedef static_allocator<char, 1<<20> string_allocator; /* 1 MB memory pool ...
172 * not thread-safe, but that is
173 * not required here
175 * */
176 /* typedef std::basic_string<char, std::char_traits<char>, string_allocator> string; */
177 typedef std::string string;
178 string overflow_vector;
181 } /* namespace */
183 using detail::network_thread;
184 using detail::osc_server;
186 } /* namespace nova */
188 #endif /* OSC_SERVER_HPP */