1 /* $Id: pipe.cpp,v 1.12 2007-05-09 21:23:09 adam Exp $
2 Copyright (c) 2005-2007, Index Data.
4 This file is part of Metaproxy.
6 Metaproxy is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 Metaproxy is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with Metaproxy; see the file LICENSE. If not, write to the
18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
33 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netinet/tcp.h>
42 #include <sys/socket.h>
45 #include <sys/select.h>
48 #include <boost/thread/thread.hpp>
49 #include <boost/thread/mutex.hpp>
50 #include <boost/thread/condition.hpp>
56 #include <yazpp/socket-observer.h>
61 namespace mp = metaproxy_1;
63 namespace metaproxy_1 {
64 class Pipe::Rep : public boost::noncopyable {
76 void Pipe::Rep::close(int &fd)
90 m_fd[0] = m_fd[1] = -1;
94 bool Pipe::Rep::nonblock(int s)
97 unsigned long tru = 1;
98 if (ioctlsocket(s, FIONBIO, &tru) < 0)
101 if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
104 signal (SIGPIPE, SIG_IGN);
110 Pipe::Pipe(int port_to_use) : m_p(new Rep)
114 WORD wVersionRequested = MAKEWORD(2, 0);
115 if (WSAStartup( wVersionRequested, &wsaData ))
116 throw Pipe::Error("WSAStartup failed");
118 port_to_use = 0; // we'll just use pipe on Unix
122 // create server socket
123 m_p->m_socket = socket(AF_INET, SOCK_STREAM, 0);
124 if (m_p->m_socket < 0)
125 throw Pipe::Error("could not create socket");
127 unsigned long one = 1;
128 if (setsockopt(m_p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)
129 &one, sizeof(one)) < 0)
130 throw Pipe::Error("setsockopt error");
132 // bind server socket
133 struct sockaddr_in add;
134 add.sin_family = AF_INET;
135 add.sin_port = htons(port_to_use);
136 add.sin_addr.s_addr = INADDR_ANY;
137 struct sockaddr *addr = ( struct sockaddr *) &add;
139 if (bind(m_p->m_socket, addr, sizeof(struct sockaddr_in)))
140 throw Pipe::Error("could not bind on socket");
142 if (listen(m_p->m_socket, 3) < 0)
143 throw Pipe::Error("could not listen on socket");
147 tmpadd = (unsigned) inet_addr("127.0.0.1");
149 memcpy(&add.sin_addr.s_addr, &tmpadd, sizeof(struct in_addr));
151 throw Pipe::Error("inet_addr failed");
153 m_p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0);
154 if (m_p->m_fd[1] < 0)
155 throw Pipe::Error("could not create socket");
157 m_p->nonblock(m_p->m_fd[1]);
159 if (connect(m_p->m_fd[1], addr, sizeof(*addr)) < 0)
162 if (WSAGetLastError() != WSAEWOULDBLOCK)
163 throw Pipe::Error("could not connect to socket");
165 if (errno != EINPROGRESS)
166 throw Pipe::Error("could not connect to socket");
171 struct sockaddr caddr;
173 int caddr_len = sizeof(caddr);
175 socklen_t caddr_len = sizeof(caddr);
177 m_p->m_fd[0] = accept(m_p->m_socket, &caddr, &caddr_len);
178 if (m_p->m_fd[0] < 0)
179 throw Pipe::Error("could not accept on socket");
184 FD_SET(m_p->m_fd[1], &write_set);
185 int r = select(m_p->m_fd[1]+1, 0, &write_set, 0, 0);
187 throw Pipe::Error("could not complete connect");
189 m_p->close(m_p->m_socket);
195 throw Pipe::Error("pipe failed");
198 assert(m_p->m_fd[0] >= 0);
199 assert(m_p->m_fd[1] >= 0);
207 m_p->close(m_p->m_fd[0]);
208 m_p->close(m_p->m_fd[1]);
209 m_p->close(m_p->m_socket);
215 int &Pipe::read_fd() const
220 int &Pipe::write_fd() const
228 * indent-tabs-mode: nil
229 * c-file-style: "stroustrup"
231 * vim: shiftwidth=4 tabstop=8 expandtab