ipcommunication.c
Go to the documentation of this file.
00001 // Copyright (c) 2010-2016 The YP-Spur Authors, except where otherwise indicated.
00002 //
00003 // Permission is hereby granted, free of charge, to any person obtaining a copy
00004 // of this software and associated documentation files (the "Software"), to
00005 // deal in the Software without restriction, including without limitation the
00006 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00007 // sell copies of the Software, and to permit persons to whom the Software is
00008 // furnished to do so, subject to the following conditions:
00009 //
00010 // The above copyright notice and this permission notice shall be included in
00011 // all copies or substantial portions of the Software.
00012 //
00013 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00016 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00019 // SOFTWARE.
00020 
00021 #include <fcntl.h>
00022 #include <stdint.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <sys/types.h>
00027 #include <unistd.h>
00028 #include <unistd.h>
00029 
00030 #if defined(__MINGW32__)
00031 #include <winsock2.h>
00032 #include <windows.h>
00033 #else
00034 #include <sys/socket.h>
00035 #include <netinet/in.h>
00036 #include <arpa/inet.h>
00037 #endif  // defined(__MINGW32__)
00038 
00039 #ifdef HAVE_CONFIG_H
00040 #include <config.h>
00041 #endif  // HAVE_CONFIG_H
00042 
00043 #include <ypparam.h>
00044 #include <msq.win32.h>
00045 #include <ipcommunication.h>
00046 #include <utility.h>
00047 #include <yprintf.h>
00048 
00049 #if defined(__MINGW32__)
00050 #define SOCK_SHUTDOWN_OPTION SD_BOTH
00051 #define SOCK_DATATYPE char *
00052 #define SIZE_TYPE int
00053 #else
00054 #define SOCK_SHUTDOWN_OPTION SHUT_RDWR
00055 #define SOCK_DATATYPE void *
00056 #define SIZE_TYPE unsigned int
00057 #endif  // defined(__MINGW32__)
00058 
00059 int ipcmd_open_msq(struct ipcmd_t *ipcmd, int key, int creat)
00060 {
00061   if (creat)
00062     creat = IPC_CREAT;
00063   /* メッセージ・キューのオープン */
00064   ipcmd->socket = msgget(key, 0666 | creat);
00065 
00066   ipcmd->send = ipcmd_send;
00067   ipcmd->recv = ipcmd_recv;
00068   ipcmd->flush = ipcmd_flush;
00069   if (ipcmd->socket == -1)
00070   {
00071     ipcmd->connection_error = 1;
00072     return -1;
00073   }
00074 
00075   /* 内部データの初期化 */
00076   ipcmd->pid = 0x07fff & getpid();
00077   if (creat)
00078     ipcmd->pid = YPSPUR_MSG_CMD;
00079   ipcmd->connection_error = 0;
00080   ipcmd->send = ipcmd_send_msq;
00081   ipcmd->recv = ipcmd_recv_msq;
00082   ipcmd->flush = ipcmd_flush_msq;
00083 
00084   ipcmd->type = IPCMD_MSQ;
00085 
00086   return 1;
00087 }
00088 
00089 int ipcmd_send_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00090 {
00091   size_t len = YPSPUR_MSG_SIZE;
00092 
00093   if (ipcmd == NULL || ipcmd->connection_error)
00094     return -1;
00095 
00096   if (msgsnd(ipcmd->socket, data, len, 0) < 0)
00097   {
00098     ipcmd->connection_error = 1;
00099     return -1;
00100   }
00101   return len;
00102 }
00103 
00104 int ipcmd_recv_msq(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00105 {
00106   int received;
00107   size_t len = YPSPUR_MSG_SIZE;
00108 
00109   if (ipcmd == NULL || ipcmd->connection_error)
00110     return -1;
00111 
00112   received = msgrcv(ipcmd->socket, data, len, ipcmd->pid, 0);
00113   if (received < 0)
00114   {
00115     ipcmd->connection_error = 1;
00116     return -1;
00117   }
00118   return received;
00119 }
00120 
00121 void ipcmd_flush_msq(struct ipcmd_t *ipcmd)
00122 {
00123   char dummy[128];
00124 
00125   if (ipcmd == NULL || ipcmd->connection_error)
00126     return;
00127 
00128   while (1)
00129   {
00130     if (msgrcv(ipcmd->socket, &dummy, 128, YPSPUR_MSG_CMD, IPC_NOWAIT) == -1)
00131     {
00132       break;
00133     }
00134   }
00135 }
00136 
00137 int ipcmd_open_tcp(struct ipcmd_t *ipcmd, char *host, int port)
00138 {
00139   struct sockaddr_in addr;
00140   int i;
00141 
00142 #if HAVE_LIBWS2_32
00143   WSADATA wsadata;
00144 
00145   if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
00146   {
00147     return -1;
00148   }
00149 #endif  // HAVE_LIBWS2_32
00150 
00151   ipcmd->send = ipcmd_send;
00152   ipcmd->recv = ipcmd_recv;
00153   ipcmd->flush = ipcmd_flush;
00154   memset(&addr, 0, sizeof(addr));
00155   addr.sin_port = htons(port);
00156   addr.sin_family = AF_INET;
00157 
00158   ipcmd->socket = socket(AF_INET, SOCK_STREAM, 0);
00159   for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
00160   {
00161     ipcmd->clients[i] = -1;
00162   }
00163 
00164   if (!host)
00165   {
00166     addr.sin_addr.s_addr = htonl(INADDR_ANY);
00167     bind(ipcmd->socket, (struct sockaddr *)&addr, sizeof(addr));
00168 
00169     listen(ipcmd->socket, YPSPUR_MAX_SOCKET);
00170     ipcmd->tcp_type = IPCMD_TCP_SERVER;
00171   }
00172   else
00173   {
00174     addr.sin_addr.s_addr = inet_addr(host);
00175 
00176     if (connect(ipcmd->socket, (struct sockaddr *)&addr, sizeof(addr)) == -1)
00177     {
00178       return -1;
00179     }
00180     ipcmd->tcp_type = IPCMD_TCP_CLIENT;
00181   }
00182 
00183   ipcmd->type = IPCMD_TCP;
00184   ipcmd->send = ipcmd_send_tcp;
00185   ipcmd->recv = ipcmd_recv_tcp;
00186   ipcmd->flush = ipcmd_flush_tcp;
00187 
00188   ipcmd->connection_error = 0;
00189 
00190   return 1;
00191 }
00192 
00193 int ipcmd_send_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00194 {
00195   int sock;
00196   size_t len = sizeof(YPSpur_msg);
00197 
00198   if (ipcmd == NULL || ipcmd->connection_error)
00199     return -1;
00200 
00201   if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
00202   {
00203     sock = ipcmd->socket;
00204   }
00205   else
00206   {
00207     sock = ipcmd->clients[(int)data->msg_type];
00208   }
00209   if (send(sock, (SOCK_DATATYPE)data, len, 0) < 0)
00210   {
00211     if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
00212     {
00213       shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
00214       ipcmd->connection_error = 1;
00215     }
00216     return -1;
00217   }
00218 
00219   return len;
00220 }
00221 
00222 int ipcmd_recv_tcp(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00223 {
00224   fd_set fds;
00225   struct sockaddr_in client;
00226   int sock;
00227   int i;
00228   size_t len = sizeof(YPSpur_msg);
00229 
00230   if (ipcmd == NULL || ipcmd->connection_error)
00231     return -1;
00232 
00233   do
00234   {
00235     int recved;
00236     while (1)
00237     {
00238       SIZE_TYPE addr_size;
00239       int nfds = 0;
00240 
00241       FD_ZERO(&fds);
00242       FD_SET(ipcmd->socket, &fds);
00243       if (nfds < ipcmd->socket)
00244         nfds = ipcmd->socket;
00245       for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
00246       {
00247         if (ipcmd->clients[i] != -1)
00248         {
00249           FD_SET(ipcmd->clients[i], &fds);
00250           if (nfds < ipcmd->clients[i])
00251             nfds = ipcmd->clients[i];
00252         }
00253       }
00254 
00255       nfds++;
00256       if (!select(nfds, &fds, NULL, NULL, NULL))
00257       {
00258         yprintf(OUTPUT_LV_ERROR, "Couldn't select the socket.\n");
00259         return -1;
00260       }
00261       if (!FD_ISSET(ipcmd->socket, &fds))
00262       {
00263         break;
00264       }
00265       if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
00266       {
00267         break;
00268       }
00269 
00270       addr_size = sizeof(client);
00271       sock = accept(ipcmd->socket, (struct sockaddr *)&client, &addr_size);
00272       if (sock <= 0)
00273       {
00274         yprintf(OUTPUT_LV_ERROR, "Invalid socket.\n");
00275         return -1;
00276       }
00277       for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
00278       {
00279         if (ipcmd->clients[i] == -1)
00280         {
00281           break;
00282         }
00283       }
00284       if (i == YPSPUR_MAX_SOCKET)
00285       {
00286         yprintf(OUTPUT_LV_ERROR, "Too many connection requests.\n");
00287         return -1;
00288       }
00289       ipcmd->clients[i] = sock;
00290       yprintf(OUTPUT_LV_INFO, "Connection %d accepted from %s.\n", i, inet_ntoa(client.sin_addr));
00291     }
00292 
00293     recved = -1;
00294     if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
00295     {
00296       recved = recv(ipcmd->socket, (SOCK_DATATYPE)data, len, 0);
00297       data->pid = 0;
00298     }
00299     else
00300     {
00301       for (i = 0; i < YPSPUR_MAX_SOCKET; i++)
00302       {
00303         if (FD_ISSET(ipcmd->clients[i], &fds))
00304         {
00305           recved = recv(ipcmd->clients[i], (SOCK_DATATYPE)data, len, 0);
00306           data->pid = i;
00307           break;
00308         }
00309       }
00310     }
00311     if (recved <= 0)
00312     {
00313       if (ipcmd->tcp_type == IPCMD_TCP_CLIENT)
00314       {
00315         yprintf(OUTPUT_LV_INFO, "Connection closed.\n");
00316         ipcmd->connection_error = 1;
00317         shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
00318         return -1;
00319       }
00320       yprintf(OUTPUT_LV_INFO, "Connection %d closed.\n", i);
00321       ipcmd->clients[i] = -1;
00322       continue;
00323     }
00324   } while (0);
00325   return len;
00326 }
00327 
00328 void ipcmd_flush_tcp(struct ipcmd_t *ipcmd)
00329 {
00330 }
00331 
00332 void ipcmd_close(struct ipcmd_t *ipcmd)
00333 {
00334   if (ipcmd == NULL)
00335     return;
00336   switch (ipcmd->type)
00337   {
00338     case IPCMD_MSQ:
00339       msgctl(ipcmd->socket, IPC_RMID, NULL);
00340       break;
00341     case IPCMD_TCP:
00342       shutdown(ipcmd->socket, SOCK_SHUTDOWN_OPTION);
00343 #if HAVE_LIBWS2_32
00344       WSACleanup();
00345 #endif  // HAVE_LIBWS2_32
00346       break;
00347   }
00348   ipcmd->send = ipcmd_send;
00349   ipcmd->recv = ipcmd_recv;
00350   ipcmd->flush = ipcmd_flush;
00351 }
00352 
00353 int ipcmd_send(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00354 {
00355   ipcmd->connection_error = 1;
00356   return -1;
00357 }
00358 
00359 int ipcmd_recv(struct ipcmd_t *ipcmd, YPSpur_msg *data)
00360 {
00361   ipcmd->connection_error = 1;
00362   return -1;
00363 }
00364 
00365 void ipcmd_flush(struct ipcmd_t *ipcmd)
00366 {
00367 }


yp-spur
Author(s):
autogenerated on Fri May 10 2019 02:52:19