AiCPlayer
Interface of aic vm - for rendering aspect, sensors, video records
host_gl.c
Go to the documentation of this file.
1 #include <errno.h> // for errno, EINTR
2 #include <pthread.h> // for pthread_mutex_lock, pthread_mutex_unlock
3 #include <stdint.h> // for uint8_t
4 #include <stdio.h> // for NULL
5 #include <stdlib.h> // for free
6 #include <string.h>
7 #include <sys/select.h> // for FD_ISSET, FD_SET, select, FD_ZERO, fd_set
8 #include <sys/socket.h> // for MSG_WAITALL
9 #include <unistd.h> // for close, usleep
10 
11 #include "socket.h"
12 #include "logger.h"
13 
14 #include "host_gl.h"
15 
16 #define LOG_TAG "gl"
17 
18 static pthread_mutex_t mtx;
19 static uint8_t start_conn_thread = 0;
20 
21 static int copy_socket(int fd_read, int fd_write, char* buff)
22 {
23  int rsize, towrite, wsize;
24 
25  rsize = read(fd_read, buff, BUFF_SIZE);
26  if (rsize <= 0)
27  {
28  close(fd_read);
29  close(fd_write);
30  return -1;
31  }
32 
33  towrite = rsize;
34 
35  while ((wsize = write(fd_write, buff, towrite)) > 0)
36  towrite -= wsize;
37  if (towrite > 0)
38  {
39  close(fd_read);
40  close(fd_write);
41  return -1;
42  }
43 
44  return 0;
45 }
46 
47 static void* conn_thread(void* arg)
48 {
49  struct conn_duo* cd = (struct conn_duo*) arg;
50  char* buff = (char*) calloc(BUFF_SIZE, sizeof(char));
51  if (!buff)
52  LOGE("Socket copy thread %u: Unable to alloc %d bytes", pthread_self(), BUFF_SIZE);
53 
54  while (1)
55  {
56  fd_set set_read;
57  int nfds;
58 
59  FD_ZERO(&set_read);
60  FD_SET(cd->local_socket, &set_read);
61  FD_SET(cd->host_socket, &set_read);
62 
63  if (cd->local_socket > cd->host_socket)
64  nfds = cd->local_socket + 1;
65  else
66  nfds = cd->host_socket + 1;
67 
68  if (select(nfds + 1, &set_read, NULL, NULL, NULL) < 0)
69  {
70  if (errno == EINTR)
71  continue;
72  break;
73  }
74 
75  if ((FD_ISSET(cd->local_socket, &set_read)) &&
76  (copy_socket(cd->local_socket, cd->host_socket, buff) < 0))
77  break;
78 
79  if ((FD_ISSET(cd->host_socket, &set_read)) &&
80  (copy_socket(cd->host_socket, cd->local_socket, buff) < 0))
81  break;
82  }
83 
84  LOGI("Socket copy thread %u: Stopping", pthread_self());
85 
86  free(buff);
87  close(cd->local_socket);
88  close(cd->host_socket);
89  free(cd);
90 
91  return NULL;
92 }
93 
94 static void* sync_conn_thread(void* arg)
95 {
96  socket_t main_socket = *((socket_t*) arg);
97 
98  int nop, written, cmd;
99 
100  do
101  {
102  recv(main_socket, &nop, sizeof(nop), MSG_WAITALL);
103  switch (nop)
104  {
105  case 1:
106  // 1: start a new copy_socket thread
107  pthread_mutex_lock(&mtx);
108  start_conn_thread = 1;
109  pthread_mutex_unlock(&mtx);
110  break;
111  case OPENGL_PING:
112  // PING: answer with a PONG
113  cmd = OPENGL_PONG;
114  written = write(main_socket, &cmd, sizeof(cmd));
115  if (written != sizeof(cmd))
116  LOGW("write() returned %d", written);
117  break;
118  default:
119  break;
120  }
121 
122  LOGD("sync thread: received %d ", nop);
123  } while (1);
124 
125  return NULL;
126 }
127 
128 int manage_socket_gl(void* arg)
129 {
130  pthread_mutex_init(&mtx, NULL);
131  char* vmip = arg;
132 
133  socket_t hw_socket;
134  socket_t main_socket;
135 
136  int rc;
137  pthread_t sync_thread_id;
138  pthread_t new_thread_id;
139 
140  do
141  {
142  main_socket = open_socket_reuseaddr(vmip, 25000);
143 
144  if (main_socket == SOCKET_ERROR)
145  {
146  LOGW("connect() error: %s", strerror(errno));
147  sleep(5);
148  }
149  } while (main_socket == SOCKET_ERROR);
150  LOGI("OpenGL management connected to socket %d", main_socket);
151 
152  unsigned int cmd = OPENGL_START_COMMAND;
153  if (write(main_socket, &cmd, sizeof(cmd)) == -1)
154  LOGW("Unable to write data port to main connection - error %d (%s)", errno,
155  strerror(errno));
156 
157  // Create the opengl socket monitoring thread
158  rc = pthread_create(&sync_thread_id, NULL, sync_conn_thread, &main_socket);
159 
160  if (rc)
161  LOGE("pthread_create returned %d", rc);
162 
163  while (1)
164  {
165  // connect for hw_socket connection
166  do
167  {
168  hw_socket = open_socket_nodelay(vmip, 22468);
169 
170  if (hw_socket == SOCKET_ERROR)
171  {
172  LOGW("connect() error: %s", strerror(errno));
173  sleep(5);
174  }
175  } while (hw_socket == SOCKET_ERROR);
176  LOGI(" Connected to the VM with socket %d", hw_socket);
177 
178  socket_t render_socket = open_socket_nodelay("127.0.0.1", 22468);
179 
180  struct conn_duo* new_cd = (struct conn_duo*) malloc(sizeof(struct conn_duo));
181  if (!new_cd)
182  {
183  LOGE("Cannot allocate memory");
184  return 0;
185  }
186 
187  new_cd->host_socket = hw_socket;
188  new_cd->local_socket = render_socket;
189 
190  rc = pthread_create(&new_thread_id, NULL, conn_thread, (void*) new_cd);
191 
192  if (rc)
193  {
194  close(new_cd->local_socket);
195  close(new_cd->host_socket);
196  free(new_cd);
197  LOGE("pthread_create returned %d", rc);
198  }
199 
200  LOGI("New gl thread created");
201 
202  while (!start_conn_thread)
203  {
204  struct timespec duration = {0, 100000};
205  nanosleep(&duration, NULL);
206  }
207 
208  pthread_mutex_lock(&mtx);
209  start_conn_thread = 0;
210  pthread_mutex_unlock(&mtx);
211  }
212 
213  return 0;
214 }
#define LOGD(...)
Log at DEBUG level.
Definition: logger.h:21
Data structure to hold the two connections.
Definition: host_gl.h:14
int local_socket
Definition: host_gl.h:17
#define OPENGL_PING
Command sent by the VM to check if we’re still alive.
Definition: host_gl.h:28
#define LOGE(...)
Log at ERROR level (makes the application abort)
Definition: logger.h:31
int socket_t
Alias to differenciate between regular ints and socket fds.
Definition: socket.h:13
#define BUFF_SIZE
Max size of opengl reads.
Definition: host_gl.h:23
socket_t open_socket_nodelay(const char *ip, short port)
Open a socket with TCP_NODELAY.
Definition: socket.c:34
int host_socket
Definition: host_gl.h:19
OpenGL proxy management.
Logging macros.
#define OPENGL_START_COMMAND
Command sent to initiate the remote graphics exchange.
Definition: host_gl.h:26
#define LOGW(...)
Log at WARNING level.
Definition: logger.h:27
int manage_socket_gl(void *arg)
Manage the remote OpenGL to the VM.
Definition: host_gl.c:128
socket_t open_socket_reuseaddr(const char *ip, short port)
Open a socket with SO_REUSEADDR.
Definition: socket.c:39
#define SOCKET_ERROR
Alias for the recv() return value in case of error.
Definition: socket.h:10
Define socket utilities to simplify networking.
#define LOGI(...)
Log at INFO level.
Definition: logger.h:23
#define OPENGL_PONG
Reply to make tell the VM we’re still alive.
Definition: host_gl.h:30