1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
8 * \brief Implements socket-pipes
19 #include <yaz/xmalloc.h>
22 #include <yaz/spipe.h>
30 #define YAZ_INVALID_SOCKET INVALID_SOCKET
32 #define YAZ_INVALID_SOCKET -1
37 #include <netinet/in.h>
43 #include <arpa/inet.h>
45 #if HAVE_NETINET_TCP_H
46 #include <netinet/tcp.h>
49 #include <sys/socket.h>
53 #include <netinet/in.h>
59 #include <arpa/inet.h>
61 #if HAVE_NETINET_TCP_H
62 #include <netinet/tcp.h>
70 static void yaz_spipe_close(int *fd)
73 if (*fd != YAZ_INVALID_SOCKET)
76 if (*fd != YAZ_INVALID_SOCKET)
79 *fd = YAZ_INVALID_SOCKET;
82 static int nonblock(int s)
85 unsigned long tru = 1;
86 if (ioctlsocket(s, FIONBIO, &tru))
89 if (fcntl(s, F_SETFL, O_NONBLOCK))
95 yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg)
97 yaz_spipe_t p = xmalloc(sizeof(*p));
102 WORD wVersionRequested = MAKEWORD(2, 0);
103 if (WSAStartup( wVersionRequested, &wsaData))
106 wrbuf_printf(*err_msg, "WSAStartup failed");
112 p->m_fd[0] = p->m_fd[1] = YAZ_INVALID_SOCKET;
113 p->m_socket = YAZ_INVALID_SOCKET;
117 struct sockaddr_in add;
118 struct sockaddr *addr = 0;
120 struct sockaddr caddr;
122 int caddr_len = sizeof(caddr);
124 socklen_t caddr_len = sizeof(caddr);
128 /* create server socket */
129 p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
130 if (p->m_socket == YAZ_INVALID_SOCKET)
133 wrbuf_printf(*err_msg, "socket call failed");
134 yaz_spipe_destroy(p);
139 unsigned long one = 1;
140 if (setsockopt(p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)
144 wrbuf_printf(*err_msg, "setsockopt call failed");
145 yaz_spipe_destroy(p);
150 /* bind server socket */
151 add.sin_family = AF_INET;
152 add.sin_port = htons(port_to_use);
153 add.sin_addr.s_addr = INADDR_ANY;
154 addr = ( struct sockaddr *) &add;
156 if (bind(p->m_socket, addr, sizeof(struct sockaddr_in)))
159 wrbuf_printf(*err_msg, "could not bind to socket");
160 yaz_spipe_destroy(p);
164 if (listen(p->m_socket, 3) < 0)
167 wrbuf_printf(*err_msg, "could not listen on socket");
168 yaz_spipe_destroy(p);
173 tmpadd = (unsigned) inet_addr("127.0.0.1");
177 wrbuf_printf(*err_msg, "inet_addr failed");
178 yaz_spipe_destroy(p);
182 memcpy(&add.sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
183 p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
184 if (p->m_fd[1] == YAZ_INVALID_SOCKET)
187 wrbuf_printf(*err_msg, "socket call failed (2)");
188 yaz_spipe_destroy(p);
191 nonblock(p->m_fd[1]);
193 if (connect(p->m_fd[1], addr, sizeof(*addr)))
197 WSAGetLastError() != WSAEWOULDBLOCK
204 wrbuf_printf(*err_msg, "connect call failed");
205 yaz_spipe_destroy(p);
211 p->m_fd[0] = accept(p->m_socket, &caddr, &caddr_len);
212 if (p->m_fd[0] == YAZ_INVALID_SOCKET)
215 wrbuf_printf(*err_msg, "accept failed");
216 yaz_spipe_destroy(p);
220 /* complete connect */
222 FD_SET(p->m_fd[1], &write_set);
223 if (select(p->m_fd[1]+1, 0, &write_set, 0, 0) != 1)
226 wrbuf_printf(*err_msg, "could not complete connect");
227 yaz_spipe_destroy(p);
230 yaz_spipe_close(&p->m_socket);
235 yaz_spipe_destroy(p);
241 wrbuf_printf(*err_msg, "pipe call failed");
242 yaz_spipe_destroy(p);
245 assert(p->m_fd[0] != YAZ_INVALID_SOCKET);
246 assert(p->m_fd[1] != YAZ_INVALID_SOCKET);
253 void yaz_spipe_destroy(yaz_spipe_t p)
255 yaz_spipe_close(&p->m_fd[0]);
256 yaz_spipe_close(&p->m_fd[1]);
257 yaz_spipe_close(&p->m_socket);
264 int yaz_spipe_get_read_fd(yaz_spipe_t p)
269 int yaz_spipe_get_write_fd(yaz_spipe_t p)
278 * c-file-style: "Stroustrup"
279 * indent-tabs-mode: nil
281 * vim: shiftwidth=4 tabstop=8 expandtab