1 /*****************************************************************************
2 * comm.c: Handles the communication socket
3 *****************************************************************************
4 * Copyright (C) 2008, 2015 VideoLAN
6 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * This program is free software. It comes without any warranty, to
9 * the extent permitted by applicable law. You can redistribute it
10 * and/or modify it under the terms of the Do What The Fuck You Want
11 * To Public License, Version 2, as published by Sam Hocevar. See
12 * http://sam.zoy.org/wtfpl/COPYING for more details.
13 *****************************************************************************/
22 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
35 /*****************************************************************************
37 *****************************************************************************/
38 static int i_comm_fd
= -1;
39 static struct ev_io comm_watcher
;
41 /*****************************************************************************
43 *****************************************************************************/
44 static void comm_Read(struct ev_loop
*loop
, struct ev_io
*w
, int revents
);
46 /*****************************************************************************
48 *****************************************************************************/
49 void comm_Open( void )
51 int i_size
= COMM_MAX_MSG_CHUNK
;
52 struct sockaddr_un sun_server
;
54 unlink( psz_srv_socket
);
56 if ( (i_comm_fd
= socket( AF_UNIX
, SOCK_DGRAM
, 0 )) == -1 )
58 msg_Err( NULL
, "cannot create comm socket (%s)", strerror(errno
) );
62 setsockopt( i_comm_fd
, SOL_SOCKET
, SO_RCVBUF
, &i_size
, sizeof(i_size
) );
64 memset( &sun_server
, 0, sizeof(sun_server
) );
65 sun_server
.sun_family
= AF_UNIX
;
66 strncpy( sun_server
.sun_path
, psz_srv_socket
, sizeof(sun_server
.sun_path
) );
67 sun_server
.sun_path
[sizeof(sun_server
.sun_path
) - 1] = '\0';
69 if ( bind( i_comm_fd
, (struct sockaddr
*)&sun_server
,
70 SUN_LEN(&sun_server
) ) < 0 )
72 msg_Err( NULL
, "cannot bind comm socket (%s)", strerror(errno
) );
78 ev_io_init(&comm_watcher
, comm_Read
, i_comm_fd
, EV_READ
);
79 ev_io_start(event_loop
, &comm_watcher
);
82 /*****************************************************************************
84 *****************************************************************************/
85 static void comm_Read(struct ev_loop
*loop
, struct ev_io
*w
, int revents
)
87 struct sockaddr_un sun_client
;
88 socklen_t sun_length
= sizeof(sun_client
);
89 ssize_t i_size
, i_answer_size
= 0;
90 uint8_t p_buffer
[COMM_BUFFER_SIZE
], p_answer
[COMM_BUFFER_SIZE
];
91 uint8_t i_command
, i_answer
;
92 uint8_t *p_packed_section
;
93 unsigned int i_packed_section_size
;
94 uint8_t *p_input
= p_buffer
+ COMM_HEADER_SIZE
;
95 uint8_t *p_output
= p_answer
+ COMM_HEADER_SIZE
;
97 i_size
= recvfrom( i_comm_fd
, p_buffer
, COMM_BUFFER_SIZE
, 0,
98 (struct sockaddr
*)&sun_client
, &sun_length
);
99 if ( i_size
< COMM_HEADER_SIZE
)
101 msg_Err( NULL
, "cannot read comm socket (%zd:%s)\n", i_size
,
105 if ( sun_length
== 0 || sun_length
> sizeof(sun_client
) )
107 msg_Err( NULL
, "anonymous packet from comm socket\n" );
111 if ( p_buffer
[0] != COMM_HEADER_MAGIC
)
113 msg_Err( NULL
, "wrong protocol version 0x%x", p_buffer
[0] );
117 i_command
= p_buffer
[1];
119 if ( i_frequency
== 0 ) /* ASI or UDP, disable DVB only commands */
123 case CMD_FRONTEND_STATUS
:
125 case CMD_MMI_SLOT_STATUS
:
129 case CMD_MMI_SEND_TEXT
:
130 case CMD_MMI_SEND_CHOICE
:
131 i_answer
= RET_NODATA
;
145 #ifdef HAVE_DVB_SUPPORT
146 case CMD_FRONTEND_STATUS
:
147 i_answer
= dvb_FrontendStatus( p_answer
+ COMM_HEADER_SIZE
,
152 i_answer
= en50221_StatusMMI( p_answer
+ COMM_HEADER_SIZE
,
156 case CMD_MMI_SLOT_STATUS
:
157 i_answer
= en50221_StatusMMISlot( p_input
, i_size
- COMM_HEADER_SIZE
,
158 p_answer
+ COMM_HEADER_SIZE
,
163 i_answer
= en50221_OpenMMI( p_input
, i_size
- COMM_HEADER_SIZE
);
167 i_answer
= en50221_CloseMMI( p_input
, i_size
- COMM_HEADER_SIZE
);
171 i_answer
= en50221_GetMMIObject( p_input
, i_size
- COMM_HEADER_SIZE
,
172 p_answer
+ COMM_HEADER_SIZE
,
176 case CMD_MMI_SEND_TEXT
:
177 case CMD_MMI_SEND_CHOICE
:
178 i_answer
= en50221_SendMMIObject( p_input
, i_size
- COMM_HEADER_SIZE
);
183 ev_break(loop
, EVBREAK_ALL
);
193 #define CASE_TABLE(x) \
196 i_answer = RET_##x; \
197 p_packed_section = demux_get_current_packed_##x(&i_packed_section_size); \
209 if ( p_packed_section
&& i_packed_section_size
)
211 if ( i_packed_section_size
<= COMM_BUFFER_SIZE
- COMM_HEADER_SIZE
)
213 i_answer_size
= i_packed_section_size
;
214 memcpy( p_answer
+ COMM_HEADER_SIZE
, p_packed_section
, i_packed_section_size
);
216 msg_Err( NULL
, "section size is too big (%u)\n", i_packed_section_size
);
217 i_answer
= RET_NODATA
;
219 free( p_packed_section
);
221 i_answer
= RET_NODATA
;
229 if ( i_size
< COMM_HEADER_SIZE
+ 2 )
231 msg_Err( NULL
, "command packet is too short (%zd)\n", i_size
);
235 uint16_t i_sid
= (uint16_t)((p_input
[0] << 8) | p_input
[1]);
236 p_packed_section
= demux_get_packed_PMT(i_sid
, &i_packed_section_size
);
238 if ( p_packed_section
&& i_packed_section_size
)
241 i_answer_size
= i_packed_section_size
;
242 memcpy( p_answer
+ COMM_HEADER_SIZE
, p_packed_section
, i_packed_section_size
);
243 free( p_packed_section
);
245 i_answer
= RET_NODATA
;
254 i_answer_size
= sizeof(struct cmd_pid_info
);
255 demux_get_PIDS_info( p_output
);
261 if ( i_size
< COMM_HEADER_SIZE
+ 2 )
263 msg_Err( NULL
, "command packet is too short (%zd)\n", i_size
);
267 uint16_t i_pid
= (uint16_t)((p_input
[0] << 8) | p_input
[1]);
268 if ( i_pid
>= MAX_PIDS
) {
269 i_answer
= RET_NODATA
;
272 i_answer_size
= sizeof(ts_pid_info_t
);
273 demux_get_PID_info( i_pid
, p_output
);
279 msg_Err( NULL
, "wrong command %u", i_command
);
286 p_answer
[0] = COMM_HEADER_MAGIC
;
287 p_answer
[1] = i_answer
;
290 uint32_t *p_size
= (uint32_t *)&p_answer
[4];
291 *p_size
= i_answer_size
+ COMM_HEADER_SIZE
;
293 /* msg_Dbg( NULL, "answering %d to %d with size %zd", i_answer, i_command,
296 #define min(a, b) (a < b ? a : b)
297 ssize_t i_sended
= 0;
298 ssize_t i_to_send
= i_answer_size
+ COMM_HEADER_SIZE
;
300 ssize_t i_sent
= sendto( i_comm_fd
, p_answer
+ i_sended
,
301 min(i_to_send
, COMM_MAX_MSG_CHUNK
), 0,
302 (struct sockaddr
*)&sun_client
, sun_length
);
305 msg_Err( NULL
, "cannot send comm socket (%s)", strerror(errno
) );
311 } while ( i_to_send
> 0 );
315 /*****************************************************************************
317 *****************************************************************************/
318 void comm_Close( void )
322 ev_io_stop(event_loop
, &comm_watcher
);
324 unlink(psz_srv_socket
);