1 /* $Id: pipe.cpp,v 1.11 2007-02-26 13:19:23 adam Exp $
2 Copyright (c) 2005-2007, Index Data.
4 See the LICENSE file for details
17 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <netinet/tcp.h>
26 #include <sys/socket.h>
29 #include <sys/select.h>
32 #include <boost/thread/thread.hpp>
33 #include <boost/thread/mutex.hpp>
34 #include <boost/thread/condition.hpp>
40 #include <yazpp/socket-observer.h>
45 namespace mp = metaproxy_1;
47 namespace metaproxy_1 {
48 class Pipe::Rep : public boost::noncopyable {
60 void Pipe::Rep::close(int &fd)
74 m_fd[0] = m_fd[1] = -1;
78 bool Pipe::Rep::nonblock(int s)
81 unsigned long tru = 1;
82 if (ioctlsocket(s, FIONBIO, &tru) < 0)
85 if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
88 signal (SIGPIPE, SIG_IGN);
94 Pipe::Pipe(int port_to_use) : m_p(new Rep)
98 WORD wVersionRequested = MAKEWORD(2, 0);
99 if (WSAStartup( wVersionRequested, &wsaData ))
100 throw Pipe::Error("WSAStartup failed");
102 port_to_use = 0; // we'll just use pipe on Unix
106 // create server socket
107 m_p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
108 if (m_p->m_socket < 0)
109 throw Pipe::Error("could not create socket");
111 unsigned long one = 1;
112 if (setsockopt(m_p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)
113 &one, sizeof(one)) < 0)
114 throw Pipe::Error("setsockopt error");
116 // bind server socket
117 struct sockaddr_in add;
118 add.sin_family = AF_INET;
119 add.sin_port = htons(port_to_use);
120 add.sin_addr.s_addr = INADDR_ANY;
121 struct sockaddr *addr = ( struct sockaddr *) &add;
123 if (bind(m_p->m_socket, addr, sizeof(struct sockaddr_in)))
124 throw Pipe::Error("could not bind on socket");
126 if (listen(m_p->m_socket, 3) < 0)
127 throw Pipe::Error("could not listen on socket");
131 tmpadd = (unsigned) inet_addr("127.0.0.1");
133 memcpy(&add.sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
135 throw Pipe::Error("inet_addr failed");
137 m_p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
138 if (m_p->m_fd[1] < 0)
139 throw Pipe::Error("could not create socket");
141 m_p->nonblock(m_p->m_fd[1]);
143 if (connect(m_p->m_fd[1], addr, sizeof(*addr)) < 0)
146 if (WSAGetLastError() != WSAEWOULDBLOCK)
147 throw Pipe::Error("could not connect to socket");
149 if (errno != EINPROGRESS)
150 throw Pipe::Error("could not connect to socket");
155 struct sockaddr caddr;
157 int caddr_len = sizeof(caddr);
159 socklen_t caddr_len = sizeof(caddr);
161 m_p->m_fd[0] = accept(m_p->m_socket, &caddr, &caddr_len);
162 if (m_p->m_fd[0] < 0)
163 throw Pipe::Error("could not accept on socket");
168 FD_SET(m_p->m_fd[1], &write_set);
169 int r = select(m_p->m_fd[1]+1, 0, &write_set, 0, 0);
171 throw Pipe::Error("could not complete connect");
173 m_p->close(m_p->m_socket);
179 throw Pipe::Error("pipe failed");
182 assert(m_p->m_fd[0] >= 0);
183 assert(m_p->m_fd[1] >= 0);
191 m_p->close(m_p->m_fd[0]);
192 m_p->close(m_p->m_fd[1]);
193 m_p->close(m_p->m_socket);
199 int &Pipe::read_fd() const
204 int &Pipe::write_fd() const
212 * indent-tabs-mode: nil
213 * c-file-style: "stroustrup"
215 * vim: shiftwidth=4 tabstop=8 expandtab