1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2010 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>
52 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 #include <netinet/tcp.h>
62 static void yaz_spipe_close(int *fd)
65 if (*fd != YAZ_INVALID_SOCKET)
68 if (*fd != YAZ_INVALID_SOCKET)
71 *fd = YAZ_INVALID_SOCKET;
74 static int nonblock(int s)
77 unsigned long tru = 1;
78 if (ioctlsocket(s, FIONBIO, &tru))
81 if (fcntl(s, F_SETFL, O_NONBLOCK))
87 yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg)
89 yaz_spipe_t p = xmalloc(sizeof(*p));
94 WORD wVersionRequested = MAKEWORD(2, 0);
95 if (WSAStartup( wVersionRequested, &wsaData))
98 wrbuf_printf(*err_msg, "WSAStartup failed");
104 p->m_fd[0] = p->m_fd[1] = YAZ_INVALID_SOCKET;
105 p->m_socket = YAZ_INVALID_SOCKET;
109 struct sockaddr_in add;
110 struct sockaddr *addr = 0;
112 struct sockaddr caddr;
114 int caddr_len = sizeof(caddr);
116 socklen_t caddr_len = sizeof(caddr);
120 // create server socket
121 p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
122 if (p->m_socket == YAZ_INVALID_SOCKET)
125 wrbuf_printf(*err_msg, "socket call failed");
126 yaz_spipe_destroy(p);
131 unsigned long one = 1;
132 if (setsockopt(p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)
136 wrbuf_printf(*err_msg, "setsockopt call failed");
137 yaz_spipe_destroy(p);
142 // bind server socket
143 add.sin_family = AF_INET;
144 add.sin_port = htons(port_to_use);
145 add.sin_addr.s_addr = INADDR_ANY;
146 addr = ( struct sockaddr *) &add;
148 if (bind(p->m_socket, addr, sizeof(struct sockaddr_in)))
151 wrbuf_printf(*err_msg, "could not bind to socket");
152 yaz_spipe_destroy(p);
156 if (listen(p->m_socket, 3) < 0)
159 wrbuf_printf(*err_msg, "could not listen on socket");
160 yaz_spipe_destroy(p);
165 tmpadd = (unsigned) inet_addr("127.0.0.1");
169 wrbuf_printf(*err_msg, "inet_addr failed");
170 yaz_spipe_destroy(p);
174 memcpy(&add.sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
175 p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
176 if (p->m_fd[1] == YAZ_INVALID_SOCKET)
179 wrbuf_printf(*err_msg, "socket call failed (2)");
180 yaz_spipe_destroy(p);
183 nonblock(p->m_fd[1]);
185 if (connect(p->m_fd[1], addr, sizeof(*addr)))
189 WSAGetLastError() != WSAEWOULDBLOCK
196 wrbuf_printf(*err_msg, "connect call failed");
197 yaz_spipe_destroy(p);
203 p->m_fd[0] = accept(p->m_socket, &caddr, &caddr_len);
204 if (p->m_fd[0] == YAZ_INVALID_SOCKET)
207 wrbuf_printf(*err_msg, "accept failed");
208 yaz_spipe_destroy(p);
212 /* complete connect */
214 FD_SET(p->m_fd[1], &write_set);
215 if (select(p->m_fd[1]+1, 0, &write_set, 0, 0) != 1)
218 wrbuf_printf(*err_msg, "could not complete connect");
219 yaz_spipe_destroy(p);
222 yaz_spipe_close(&p->m_socket);
227 yaz_spipe_destroy(p);
233 wrbuf_printf(*err_msg, "pipe call failed");
234 yaz_spipe_destroy(p);
237 assert(p->m_fd[0] != YAZ_INVALID_SOCKET);
238 assert(p->m_fd[1] != YAZ_INVALID_SOCKET);
245 void yaz_spipe_destroy(yaz_spipe_t p)
247 yaz_spipe_close(&p->m_fd[0]);
248 yaz_spipe_close(&p->m_fd[1]);
249 yaz_spipe_close(&p->m_socket);
256 int yaz_spipe_get_read_fd(yaz_spipe_t p)
261 int yaz_spipe_get_write_fd(yaz_spipe_t p)
270 * c-file-style: "Stroustrup"
271 * indent-tabs-mode: nil
273 * vim: shiftwidth=4 tabstop=8 expandtab