YAZ 5.35.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 <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
71struct yaz_spipe {
72 int m_fd[2];
74};
75
76static 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
86}
87
88static 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
101yaz_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);
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:189
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.