* dvbiscovery.sh: NIT can take longer than 15s. * dvbiscovery_dvb-s.conf: Change...
[dvblast.git] / comm.c
blob1eafddce4f925b29dd1c49b91a6910ec2f85f7fc
1 /*****************************************************************************
2 * comm.c: Handles the communication socket (linux-dvb only)
3 *****************************************************************************
4 * Copyright (C) 2008 VideoLAN
5 * $Id$
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software. It comes without any warranty, to
10 * the extent permitted by applicable law. You can redistribute it
11 * and/or modify it under the terms of the Do What The Fuck You Want
12 * To Public License, Version 2, as published by Sam Hocevar. See
13 * http://sam.zoy.org/wtfpl/COPYING for more details.
14 *****************************************************************************/
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <stdint.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <sys/un.h>
28 #include <errno.h>
30 #include "dvblast.h"
31 #include "en50221.h"
32 #include "comm.h"
34 /*****************************************************************************
35 * Local declarations
36 *****************************************************************************/
37 int i_comm_fd = -1;
39 /*****************************************************************************
40 * comm_Open
41 *****************************************************************************/
42 void comm_Open( void )
44 int i_size = 65535;
45 struct sockaddr_un sun_server;
47 if ( (i_comm_fd = socket( AF_UNIX, SOCK_DGRAM, 0 )) == -1 )
49 msg_Err( NULL, "cannot create comm socket (%s)", strerror(errno) );
50 return;
53 setsockopt( i_comm_fd, SOL_SOCKET, SO_RCVBUF, &i_size, sizeof(i_size) );
55 memset( &sun_server, 0, sizeof(sun_server) );
56 sun_server.sun_family = AF_UNIX;
57 strncpy( sun_server.sun_path, psz_srv_socket, sizeof(sun_server.sun_path) );
58 sun_server.sun_path[sizeof(sun_server.sun_path) - 1] = '\0';
60 if ( bind( i_comm_fd, (struct sockaddr *)&sun_server,
61 SUN_LEN(&sun_server) ) < 0 )
63 msg_Err( NULL, "cannot bind comm socket (%s)", strerror(errno) );
64 close( i_comm_fd );
65 i_comm_fd = -1;
66 return;
70 /*****************************************************************************
71 * comm_Read
72 *****************************************************************************/
73 void comm_Read( void )
75 struct sockaddr_un sun_client;
76 socklen_t sun_length = sizeof(sun_client);
77 ssize_t i_size, i_answer_size = 0;
78 uint8_t p_buffer[COMM_BUFFER_SIZE], p_answer[COMM_BUFFER_SIZE];
79 uint8_t i_command, i_answer;
81 i_size = recvfrom( i_comm_fd, p_buffer, COMM_BUFFER_SIZE, 0,
82 (struct sockaddr *)&sun_client, &sun_length );
83 if ( i_size < COMM_HEADER_SIZE )
85 msg_Err( NULL, "cannot read comm socket (%d:%s)\n", i_size,
86 strerror(errno) );
87 return;
89 if ( sun_length == 0 || sun_length > sizeof(sun_client) )
91 msg_Err( NULL, "anonymous packet from comm socket\n" );
92 return;
95 if ( p_buffer[0] != COMM_HEADER_MAGIC )
97 msg_Err( NULL, "wrong protocol version 0x%x", p_buffer[0] );
98 return;
101 i_command = p_buffer[1];
103 switch ( i_command )
105 case CMD_RELOAD:
106 b_hup_received = 1;
107 i_answer = RET_OK;
108 i_answer_size = 0;
109 break;
111 case CMD_FRONTEND_STATUS:
112 i_answer = dvb_FrontendStatus( p_answer + COMM_HEADER_SIZE,
113 &i_answer_size );
114 break;
116 case CMD_MMI_STATUS:
117 i_answer = en50221_StatusMMI( p_answer + COMM_HEADER_SIZE,
118 &i_answer_size );
119 break;
121 case CMD_MMI_SLOT_STATUS:
122 i_answer = en50221_StatusMMISlot( p_buffer + COMM_HEADER_SIZE,
123 i_size - COMM_HEADER_SIZE,
124 p_answer + COMM_HEADER_SIZE,
125 &i_answer_size );
126 break;
128 case CMD_MMI_OPEN:
129 i_answer = en50221_OpenMMI( p_buffer + COMM_HEADER_SIZE,
130 i_size - COMM_HEADER_SIZE );
131 break;
133 case CMD_MMI_CLOSE:
134 i_answer = en50221_CloseMMI( p_buffer + COMM_HEADER_SIZE,
135 i_size - COMM_HEADER_SIZE );
136 break;
138 case CMD_MMI_RECV:
139 i_answer = en50221_GetMMIObject( p_buffer + COMM_HEADER_SIZE,
140 i_size - COMM_HEADER_SIZE,
141 p_answer + COMM_HEADER_SIZE,
142 &i_answer_size );
143 break;
145 case CMD_MMI_SEND:
146 i_answer = en50221_SendMMIObject( p_buffer + COMM_HEADER_SIZE,
147 i_size - COMM_HEADER_SIZE );
148 break;
150 case CMD_SHUTDOWN:
151 msg_Err( NULL, "shutdown via comm" );
152 exit(EXIT_SUCCESS);
153 /* this is a bit violent, but hey, closing everything cleanly
154 * would do approximately the same */
156 default:
157 msg_Err( NULL, "wrong command %u", i_command );
158 i_answer = RET_HUH;
159 i_answer_size = 0;
160 break;
163 p_answer[0] = COMM_HEADER_MAGIC;
164 p_answer[1] = i_answer;
165 p_answer[2] = 0;
166 p_answer[3] = 0;
167 msg_Dbg( NULL, "answering %d to %d with size %d", i_answer, i_command,
168 i_answer_size );
170 if ( sendto( i_comm_fd, p_answer, i_answer_size + COMM_HEADER_SIZE, 0,
171 (struct sockaddr *)&sun_client, sun_length ) < 0 )
172 msg_Err( NULL, "cannot send comm socket (%s)", strerror(errno) );