YAZ  5.23.1
spipe.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14 
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <yaz/xmalloc.h>
20 #include <yaz/nmem.h>
21 #include <yaz/log.h>
22 #include <yaz/spipe.h>
23 
24 #if HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 
28 #ifdef WIN32
29 #include <winsock2.h>
30 #define YAZ_INVALID_SOCKET INVALID_SOCKET
31 #else
32 #define YAZ_INVALID_SOCKET -1
33 #include <fcntl.h>
34 #endif
35 
36 #if HAVE_NETINET_IN_H
37 #include <netinet/in.h>
38 #endif
39 #if HAVE_NETDB_H
40 #include <netdb.h>
41 #endif
42 #if HAVE_ARPA_INET_H
43 #include <arpa/inet.h>
44 #endif
45 #if HAVE_NETINET_TCP_H
46 #include <netinet/tcp.h>
47 #endif
48 #if HAVE_SYS_SOCKET_H
49 #include <sys/socket.h>
50 #endif
51 
52 #if HAVE_NETINET_IN_H
53 #include <netinet/in.h>
54 #endif
55 #if HAVE_NETDB_H
56 #include <netdb.h>
57 #endif
58 #if HAVE_ARPA_INET_H
59 #include <arpa/inet.h>
60 #endif
61 #if HAVE_NETINET_TCP_H
62 #include <netinet/tcp.h>
63 #endif
64 
65 #ifndef YAZ_SOCKLEN_T
66 #define YAZ_SOCKLEN_T int
67 #endif
68 
69 struct yaz_spipe {
70  int m_fd[2];
71  int m_socket;
72 };
73 
74 static void yaz_spipe_close(int *fd)
75 {
76 #ifdef WIN32
77  if (*fd != YAZ_INVALID_SOCKET)
78  closesocket(*fd);
79 #else
80  if (*fd != YAZ_INVALID_SOCKET)
81  close(*fd);
82 #endif
83  *fd = YAZ_INVALID_SOCKET;
84 }
85 
86 static int nonblock(int s)
87 {
88 #ifdef WIN32
89  unsigned long tru = 1;
90  if (ioctlsocket(s, FIONBIO, &tru))
91  return -1;
92 #else
93  if (fcntl(s, F_SETFL, O_NONBLOCK))
94  return -1;
95 #endif
96  return 0;
97 }
98 
99 yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg)
100 {
101  yaz_spipe_t p = xmalloc(sizeof(*p));
102 
103 #ifdef WIN32
104  {
105  WSADATA wsaData;
106  WORD wVersionRequested = MAKEWORD(2, 0);
107  if (WSAStartup( wVersionRequested, &wsaData))
108  {
109  if (err_msg)
110  wrbuf_printf(*err_msg, "WSAStartup failed");
111  xfree(p);
112  return 0;
113  }
114  }
115 #endif
116  p->m_fd[0] = p->m_fd[1] = YAZ_INVALID_SOCKET;
118 
119  if (port_to_use)
120  {
121  struct sockaddr_in add;
122  struct sockaddr *addr = 0;
123  unsigned int tmpadd;
124  struct sockaddr caddr;
125  YAZ_SOCKLEN_T caddr_len = sizeof(caddr);
126  fd_set write_set;
127 
128  /* create server socket */
129  p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
130  if (p->m_socket == YAZ_INVALID_SOCKET)
131  {
132  if (err_msg)
133  wrbuf_printf(*err_msg, "socket call failed");
135  return 0;
136  }
137 #ifndef WIN32
138  {
139  unsigned long one = 1;
140  if (setsockopt(p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)
141  &one, sizeof(one)))
142  {
143  if (err_msg)
144  wrbuf_printf(*err_msg, "setsockopt call failed");
146  return 0;
147  }
148  }
149 #endif
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;
155 
156  if (bind(p->m_socket, addr, sizeof(struct sockaddr_in)))
157  {
158  if (err_msg)
159  wrbuf_printf(*err_msg, "could not bind to socket");
161  return 0;
162  }
163 
164  if (listen(p->m_socket, 3) < 0)
165  {
166  if (err_msg)
167  wrbuf_printf(*err_msg, "could not listen on socket");
169  return 0;
170  }
171 
172  /* client socket */
173  tmpadd = (unsigned) inet_addr("127.0.0.1");
174  if (!tmpadd)
175  {
176  if (err_msg)
177  wrbuf_printf(*err_msg, "inet_addr failed");
179  return 0;
180  }
181 
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)
185  {
186  if (err_msg)
187  wrbuf_printf(*err_msg, "socket call failed (2)");
189  return 0;
190  }
191  nonblock(p->m_fd[1]);
192 
193  if (connect(p->m_fd[1], addr, sizeof(*addr)))
194  {
195  if (
196 #ifdef WIN32
197  WSAGetLastError() != WSAEWOULDBLOCK
198 #else
199  errno != EINPROGRESS
200 #endif
201  )
202  {
203  if (err_msg)
204  wrbuf_printf(*err_msg, "connect call failed");
206  return 0;
207  }
208  }
209 
210  /* server accept */
211  p->m_fd[0] = accept(p->m_socket, &caddr, &caddr_len);
212  if (p->m_fd[0] == YAZ_INVALID_SOCKET)
213  {
214  if (err_msg)
215  wrbuf_printf(*err_msg, "accept failed");
217  return 0;
218  }
219 
220  /* complete connect */
221  FD_ZERO(&write_set);
222  FD_SET(p->m_fd[1], &write_set);
223  if (select(p->m_fd[1]+1, 0, &write_set, 0, 0) != 1)
224  {
225  if (err_msg)
226  wrbuf_printf(*err_msg, "could not complete connect");
228  return 0;
229  }
231  }
232  else
233  {
234 #ifdef WIN32
236  return 0;
237 #else
238  if (pipe(p->m_fd))
239  {
240  if (err_msg)
241  wrbuf_printf(*err_msg, "pipe call failed");
243  return 0;
244  }
245  assert(p->m_fd[0] != YAZ_INVALID_SOCKET);
246  assert(p->m_fd[1] != YAZ_INVALID_SOCKET);
247 #endif
248  }
249 
250  return p;
251 }
252 
254 {
255  yaz_spipe_close(&p->m_fd[0]);
256  yaz_spipe_close(&p->m_fd[1]);
258  xfree(p);
259 #ifdef WIN32
260  WSACleanup();
261 #endif
262 }
263 
265 {
266  return p->m_fd[0];
267 }
268 
270 {
271  return p->m_fd[1];
272 }
273 
274 
275 /*
276  * Local variables:
277  * c-basic-offset: 4
278  * c-file-style: "Stroustrup"
279  * indent-tabs-mode: nil
280  * End:
281  * vim: shiftwidth=4 tabstop=8 expandtab
282  */
283 
int yaz_spipe_get_read_fd(yaz_spipe_t p)
returns reading socket
Definition: spipe.c:264
#define YAZ_INVALID_SOCKET
Definition: spipe.c:32
int m_socket
Definition: spipe.c:71
Header for errno utilities.
int m_fd[2]
Definition: spipe.c:70
int yaz_spipe_get_write_fd(yaz_spipe_t p)
returns writing socket
Definition: spipe.c:269
string buffer
Definition: wrbuf.h:42
socket-pipe header
void yaz_spipe_destroy(yaz_spipe_t p)
destroys socket pipe
Definition: spipe.c:253
#define YAZ_SOCKLEN_T
Definition: spipe.c:66
static int nonblock(int s)
Definition: spipe.c:86
#define xfree(x)
utility macro which calls xfree_f
Definition: xmalloc.h:53
static void yaz_spipe_close(int *fd)
Definition: spipe.c:74
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition: wrbuf.c:178
yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg)
create socket pipe
Definition: spipe.c:99
#define xmalloc(x)
utility macro which calls malloc_f
Definition: xmalloc.h:49
Header for memory handling functions.
Header for Nibble Memory functions.
Logging utility.