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