00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 }