21 #include <sys/types.h>
22 #include <sys/socket.h>
30 #include "safec_lib.h"
32 using namespace audiocapturemgr;
33 std::string SOCKNAME_PREFIX =
"/tmp/acm_ip_out_";
34 static unsigned int ticker;
35 static const int PIPE_READ_FD = 0;
36 static const int PIPE_WRITE_FD = 1;
37 static const unsigned int MAX_CONNECTIONS = 1;
39 static bool g_one_time_init_complete =
false;
47 static void * ip_out_thread_launcher(
void * data)
54 ip_out_client::ip_out_client(
q_mgr *mgr) :
audio_capture_client(mgr), m_listen_fd(-1), m_write_fd(-1), m_num_connections(0)
57 if(!g_one_time_init_complete)
60 struct sigaction sig_settings;
61 sig_settings.sa_handler = SIG_IGN;
62 sigemptyset(&sig_settings.sa_mask);
63 sig_settings.sa_flags = 0;
64 sigaction(SIGPIPE, &sig_settings, NULL);
65 m_control_pipe[PIPE_READ_FD] = 0;
66 m_control_pipe[PIPE_WRITE_FD] = 0;
67 g_one_time_init_complete =
true;
69 REPORT_IF_UNEQUAL(0, pipe2(m_control_pipe, O_NONBLOCK));
73 ip_out_client::~ip_out_client()
77 close(m_control_pipe[PIPE_WRITE_FD]);
78 close(m_control_pipe[PIPE_READ_FD]);
86 int ret = write(m_write_fd, buf->m_start_ptr, buf->m_size);
89 WARN(
"Write error! Closing socket. errno: 0x%x\n", errno);
90 perror(
"ip_out_client::data_callback() ");
96 else if(ret != buf->m_size)
98 WARN(
"Incomplete buffer write!\n");
106 std::string ip_out_client::get_data_path()
111 std::string ip_out_client::open_output()
114 if(!m_data_path.empty())
116 WARN(
"Already open.\n");
122 m_listen_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
123 if (m_listen_fd < 0) {
124 ERROR(
"Could not open socket.\n");
128 DEBUG(
"Socket created.\n");
130 unsigned int num_retries = 6;
135 std::string sockpath = SOCKNAME_PREFIX + get_suffix(ticker++);
137 struct sockaddr_un bind_path;
138 bind_path.sun_family = AF_UNIX;
139 rc = strcpy_s(bind_path.sun_path,
sizeof(bind_path.sun_path), sockpath.c_str());
145 INFO(
"Binding to path %s\n", bind_path.sun_path);
146 int ret = bind(m_listen_fd, (
const struct sockaddr *) &bind_path,
sizeof(bind_path));
149 if(EADDRINUSE == errno)
151 WARN(
"Retrying as the path is already in use.\n");
154 ERROR(
"Failed to bind to path. Error is %d\n", errno);
155 perror(
"bind error");
162 INFO(
"Bound successfully to path.\n");
163 m_data_path = sockpath;
164 REPORT_IF_UNEQUAL(0, listen(m_listen_fd, 3));
165 REPORT_IF_UNEQUAL(0, pthread_create(&m_thread, NULL, ip_out_thread_launcher, (
void *)
this));
175 void ip_out_client::close_output()
181 int message = MSG_EXIT;
182 int ret = write(m_control_pipe[PIPE_WRITE_FD], &message,
sizeof(message));
183 if(ret !=
sizeof(message))
185 ERROR(
"Couldn't trigger worker thread shutdown.\n");
189 INFO(
"Waiting for worker thread to join.\n");
190 REPORT_IF_UNEQUAL(0, pthread_join(m_thread, NULL));
191 INFO(
"Worker thread has joined.\n");
193 if(!m_data_path.empty())
200 INFO(
"Closed write fd. Total active connections now is %d\n", m_num_connections);
202 INFO(
"Removing named socket %s.\n", m_data_path.c_str());
203 unlink(m_data_path.c_str());
210 void ip_out_client::process_new_connection()
216 WARN(
"Trashing old write socket in favour of new one.\n");
222 DEBUG(
"Setting up a new connection.\n");
223 struct sockaddr_un incoming_addr;
224 int addrlen =
sizeof(incoming_addr);
225 m_write_fd = accept(m_listen_fd, (sockaddr *) &incoming_addr, (socklen_t *)&addrlen);
229 ERROR(
"Error accepting connection.\n");
234 INFO(
"Connected to new client.\n");
238 INFO(
"Starting data delivery.\n");
239 audio_capture_client::start();
248 void ip_out_client::worker_thread()
251 int control_fd = m_control_pipe[PIPE_READ_FD];
252 int max_fd = (m_listen_fd > control_fd ? m_listen_fd : control_fd);
255 bool check_fds =
true;
260 FD_ZERO(&poll_fd_set);
261 FD_SET(m_listen_fd, &poll_fd_set);
262 FD_SET(control_fd, &poll_fd_set);
264 int ret = select((max_fd + 1), &poll_fd_set, NULL, NULL, NULL);
265 DEBUG(
"Unblocking now. ret is 0x%x\n", ret);
268 ERROR(
"select() returned 0.\n");
273 if(0 != FD_ISSET(control_fd, &poll_fd_set))
275 INFO(
"Exiting monitor thread.\n");
278 if(0 != FD_ISSET(m_listen_fd, &poll_fd_set))
280 process_new_connection();
285 ERROR(
"Error polling monitor FD!\n");