ipcommunication.c
Go to the documentation of this file.
1 // Copyright (c) 2010-2016 The YP-Spur Authors, except where otherwise indicated.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #include <fcntl.h>
22 #include <stdint.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <unistd.h>
29 
30 #if defined(__MINGW32__)
31 #include <winsock2.h>
32 #include <windows.h>
33 #else
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #endif // defined(__MINGW32__)
38 
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif // HAVE_CONFIG_H
42 
43 #include <ypparam.h>
44 #include <msq.win32.h>
45 #include <ipcommunication.h>
46 #include <utility.h>
47 #include <yprintf.h>
48 
49 #if defined(__MINGW32__)
50 #define SOCK_SHUTDOWN_OPTION SD_BOTH
51 #define SOCK_DATATYPE char *
52 #define SIZE_TYPE int
53 #else
54 #define SOCK_SHUTDOWN_OPTION SHUT_RDWR
55 #define SOCK_DATATYPE void *
56 #define SIZE_TYPE unsigned int
57 #endif // defined(__MINGW32__)
58 
59 int ipcmd_open_msq(struct ipcmd_t *ipcmd, int key, int creat)
60 {
61  if (creat)
62  creat = IPC_CREAT;
63  /* メッセージ・キューのオープン */
64  ipcmd->socket = msgget(key, 0666 | creat);
65 
66  ipcmd->send = ipcmd_send;
67  ipcmd->recv = ipcmd_recv;
68  ipcmd->flush = ipcmd_flush;
69  if (ipcmd->socket == -1)
70  {
71  ipcmd->connection_error = 1;
72  return -1;
73  }
74 
75  /* 内部データの初期化 */
76  ipcmd->pid = 0x07fff & getpid();
77  if (creat)
78  ipcmd->pid = YPSPUR_MSG_CMD;
79  ipcmd->connection_error = 0;
80  ipcmd->send = ipcmd_send_msq;
81  ipcmd->recv = ipcmd_recv_msq;
82  ipcmd->flush = ipcmd_flush_msq;
83 
84  ipcmd->type = IPCMD_MSQ;
85 
86  return 1;
87 }
88 
89 int ipcmd_send_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
90 {
91  size_t len = YPSPUR_MSG_SIZE;
92 
93  if (ipcmd == NULL || ipcmd->connection_error)
94  return -1;
95 
96  if (msgsnd(ipcmd->socket, data, len, 0) < 0)
97  {
98  ipcmd->connection_error = 1;
99  return -1;
100  }
101  return len;
102 }
103 
104 int ipcmd_recv_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
105 {
106  int received;
107  size_t len = YPSPUR_MSG_SIZE;
108 
109  if (ipcmd == NULL || ipcmd->connection_error)
110  return -1;
111 
112  received = msgrcv(ipcmd->socket, data, len, ipcmd->pid, 0);
113  if (received < 0)
114  {
115  ipcmd->connection_error = 1;
116  return -1;
117  }
118  return received;
119 }
120 
121 void ipcmd_flush_msq(struct ipcmd_t *ipcmd)
122 {
123  char dummy[128];
124 
125  if (ipcmd == NULL || ipcmd->connection_error)
126  return;
127 
128  while (1)
129  {
130  if (msgrcv(ipcmd->socket, &dummy, 128, YPSPUR_MSG_CMD, IPC_NOWAIT) == -1)
131  {
132  break;
133  }
134  }
135 }
136 
137 int ipcmd_open_tcp(struct ipcmd_t *ipcmd, char *host, int port)
138 {
139  struct sockaddr_in addr;
140  int i;
141 
142 #if HAVE_LIBWS2_32
143  WSADATA wsadata;
144 
145  if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
146  {
147  return -1;
148  }
149 #endif // HAVE_LIBWS2_32
150 
151  ipcmd->send = ipcmd_send;
152  ipcmd->recv = ipcmd_recv;
153  ipcmd->flush = ipcmd_flush;
154  memset(&addr, 0, sizeof(addr));
155  addr.sin_port = htons(port);
156  addr.sin_family = AF_INET;
157 
158  ipcmd->socket = socket(AF_INET, SOCK_STREAM, 0);
159  for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
160  {
161  ipcmd->clients[i] = -1;
162  }
163 
164  if (!host)
165  {
166  addr.sin_addr.s_addr = htonl(INADDR_ANY);
167  bind(ipcmd->socket, (struct sockaddr *)&addr, sizeof(addr));
168 
169  listen(ipcmd->socket, YPSPUR_MAX_SOCKET);
170  ipcmd->tcp_type = IPCMD_TCP_SERVER;
171  }
172  else
173  {
174  addr.sin_addr.s_addr = inet_addr(host);
175 
176  if (connect(ipcmd->socket, (struct sockaddr *)&addr, sizeof(addr)) == -1)
177  {
178  return -1;
179  }
180  ipcmd->tcp_type = IPCMD_TCP_CLIENT;
181  }
182 
183  ipcmd->type = IPCMD_TCP;
184  ipcmd->send = ipcmd_send_tcp;
185  ipcmd->recv = ipcmd_recv_tcp;
186  ipcmd->flush = ipcmd_flush_tcp;
187 
188  ipcmd->connection_error = 0;
189 
190  return 1;
191 }
192 
193 int ipcmd_send_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
194 {
195  int sock;
196  size_t len = sizeof(YPSpur_msg);
197 
198  if (ipcmd == NULL || ipcmd->connection_error)
199  return -1;
200 
201  if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
202  {
203  sock = ipcmd->socket;
204  }
205  else
206  {
207  sock = ipcmd->clients[(int)data->msg_type];
208  }
209  if (send(sock, (SOCK_DATATYPE)data, len, 0) < 0)
210  {
211  if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
212  {
213  shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
214  ipcmd->connection_error = 1;
215  }
216  return -1;
217  }
218 
219  return len;
220 }
221 
222 int ipcmd_recv_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
223 {
224  fd_set fds;
225  struct sockaddr_in client;
226  int sock;
227  int i;
228  size_t len = sizeof(YPSpur_msg);
229 
230  if (ipcmd == NULL || ipcmd->connection_error)
231  return -1;
232 
233  do
234  {
235  int recved;
236  while (1)
237  {
238  SIZE_TYPE addr_size;
239  int nfds = 0;
240 
241  FD_ZERO(&fds);
242  FD_SET(ipcmd->socket, &fds);
243  if (nfds < ipcmd->socket)
244  nfds = ipcmd->socket;
245  for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
246  {
247  if (ipcmd->clients[i] != -1)
248  {
249  FD_SET(ipcmd->clients[i], &fds);
250  if (nfds < ipcmd->clients[i])
251  nfds = ipcmd->clients[i];
252  }
253  }
254 
255  nfds++;
256  if (!select(nfds, &fds, NULL, NULL, NULL))
257  {
258  yprintf(OUTPUT_LV_ERROR, "Couldn't select the socket.\n");
259  return -1;
260  }
261  if (!FD_ISSET(ipcmd->socket, &fds))
262  {
263  break;
264  }
265  if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
266  {
267  break;
268  }
269 
270  addr_size = sizeof(client);
271  sock = accept(ipcmd->socket, (struct sockaddr *)&client, &addr_size);
272  if (sock <= 0)
273  {
274  yprintf(OUTPUT_LV_ERROR, "Invalid socket.\n");
275  return -1;
276  }
277  for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
278  {
279  if (ipcmd->clients[i] == -1)
280  {
281  break;
282  }
283  }
284  if (i == YPSPUR_MAX_SOCKET)
285  {
286  yprintf(OUTPUT_LV_ERROR, "Too many connection requests.\n");
287  return -1;
288  }
289  ipcmd->clients[i] = sock;
290  yprintf(OUTPUT_LV_INFO, "Connection %d accepted from %s.\n", i, inet_ntoa(client.sin_addr));
291  }
292 
293  recved = -1;
294  if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
295  {
296  recved = recv(ipcmd->socket, (SOCK_DATATYPE)data, len, 0);
297  data->pid = 0;
298  }
299  else
300  {
301  for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
302  {
303  if (FD_ISSET(ipcmd->clients[i], &fds))
304  {
305  recved = recv(ipcmd->clients[i], (SOCK_DATATYPE)data, len, 0);
306  data->pid = i;
307  break;
308  }
309  }
310  }
311  if (recved <= 0)
312  {
313  if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
314  {
315  yprintf(OUTPUT_LV_INFO, "Connection closed.\n");
316  ipcmd->connection_error = 1;
317  shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
318  return -1;
319  }
320  yprintf(OUTPUT_LV_INFO, "Connection %d closed.\n", i);
321  ipcmd->clients[i] = -1;
322  continue;
323  }
324  } while (0);
325  return len;
326 }
327 
328 void ipcmd_flush_tcp(struct ipcmd_t *ipcmd)
329 {
330 }
331 
332 void ipcmd_close(struct ipcmd_t *ipcmd)
333 {
334  if (ipcmd == NULL)
335  return;
336  switch (ipcmd->type)
337  {
338  case IPCMD_MSQ:
339  msgctl(ipcmd->socket, IPC_RMID, NULL);
340  break;
341  case IPCMD_TCP:
342  shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
343 #if HAVE_LIBWS2_32
344  WSACleanup();
345 #endif // HAVE_LIBWS2_32
346  break;
347  }
348  ipcmd->send = ipcmd_send;
349  ipcmd->recv = ipcmd_recv;
350  ipcmd->flush = ipcmd_flush;
351 }
352 
353 int ipcmd_send(struct ipcmd_t *ipcmd, YPSpur_msg *data)
354 {
355  ipcmd->connection_error = 1;
356  return -1;
357 }
358 
359 int ipcmd_recv(struct ipcmd_t *ipcmd, YPSpur_msg *data)
360 {
361  ipcmd->connection_error = 1;
362  return -1;
363 }
364 
365 void ipcmd_flush(struct ipcmd_t *ipcmd)
366 {
367 }
#define YPSPUR_MSG_CMD
Definition: ypparam.h:516
int connection_error
Definition: ypparam.h:507
void ipcmd_flush_msq(struct ipcmd_t *ipcmd)
enum ipcmd_t::ipcmd_type_t type
#define YPSPUR_MAX_SOCKET
Definition: ypparam.h:491
#define SIZE_TYPE
void(* flush)(struct ipcmd_t *ipcmd)
Definition: ypparam.h:512
int clients[YPSPUR_MAX_SOCKET]
Definition: ypparam.h:506
int ipcmd_recv_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
pid_t pid
Definition: ypparam.h:508
int ipcmd_open_tcp(struct ipcmd_t *ipcmd, char *host, int port)
int ipcmd_recv(struct ipcmd_t *ipcmd, YPSpur_msg *data)
int ipcmd_send_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
int ipcmd_send_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
enum ipcmd_t::ipcmd_tcp_type_t tcp_type
#define SOCK_DATATYPE
int(* recv)(struct ipcmd_t *ipcmd, YPSpur_msg *data)
Definition: ypparam.h:511
long msg_type
Definition: ypparam.h:484
void yprintf(ParamOutputLv level, const char *format,...)
Definition: yprintf.c:32
#define YPSPUR_MSG_SIZE
Definition: ypparam.h:517
int socket
Definition: ypparam.h:505
void ipcmd_flush(struct ipcmd_t *ipcmd)
int ipcmd_send(struct ipcmd_t *ipcmd, YPSpur_msg *data)
void ipcmd_close(struct ipcmd_t *ipcmd)
void ipcmd_flush_tcp(struct ipcmd_t *ipcmd)
int(* send)(struct ipcmd_t *ipcmd, YPSpur_msg *data)
Definition: ypparam.h:510
int ipcmd_recv_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
#define SOCK_SHUTDOWN_OPTION
int ipcmd_open_msq(struct ipcmd_t *ipcmd, int key, int creat)


yp-spur
Author(s):
autogenerated on Sat May 11 2019 02:08:24