Beispiel #1
0
	//send the hint to the server that the connecting is about to be closed.
	inline void close(SOCKET socket){
		sendProtocolMessage(socket, PROTOCOLCODES::CLOSEME, 1);
		closesocket(socket);
		if (readList.sockExists(socket)){
			readList.popSocket(socket);
		}
	}
Beispiel #2
0
void Msg2Msg::OnShutdown()
{
    //we have to close this stuff;
    ListableSocket* sndSocketPtr = NULL;
    while(!sndSockets.IsEmpty())//close out the socket
    {
        sndSocketPtr = sndSockets.RemoveHead();
        if(sndSocketPtr->IsOpen()) sndSocketPtr->Close();
        delete sndSocketPtr;
    }
    
    ListableSocket* rcvSocketPtr = NULL;
    while(!rcvSockets.IsEmpty())//close out the socket
    {
        rcvSocketPtr = rcvSockets.RemoveHead();
        if(rcvSocketPtr->IsOpen()) rcvSocketPtr->Close();
        delete rcvSocketPtr;
    }
    
    ListablePipe* sndPipePtr = NULL;
    while(!sndPipes.IsEmpty())//close out the pipe
    {
        sndPipePtr = sndPipes.RemoveHead();
        if(sndPipePtr->IsOpen()) sndPipePtr->Close();
        delete sndPipePtr;
    }
    
    ListablePipe* rcvPipePtr = NULL;
    while(!rcvPipes.IsEmpty())//close out the pipe
    {
        rcvPipePtr = rcvPipes.RemoveHead();
        if(rcvPipePtr->IsOpen()) rcvPipePtr->Close();
        delete rcvPipePtr;
    }
    
    ListableFile* sndFilePtr = NULL;
    while(!sndFiles.IsEmpty())//close out the file
    {
        sndFilePtr = sndFiles.RemoveHead();
        if(sndFilePtr->IsOpen()) sndFilePtr->Close();
        delete sndFilePtr;
    }
    
    if(usingstdin)
    {
        //do nothing
    }
    if(usingstdout)
    {
        //do nothing
    }
    TRACE("msg2Msg: Done.\n");
}  // end Msg2Msg::OnShutdown()
Beispiel #3
0
	//send the hint to the server that the connecting is about to be closed.
	inline void closeAll(){
		for (const auto& e : readList.sockets){
			SOCKET socket = e.first;
			sendProtocolMessage(socket, PROTOCOLCODES::CLOSEME, 1);
			closesocket(socket);
			if (readList.sockExists(socket)){
				readList.popSocket(socket);
			}
			if (readList.sockets.size() == 0){
				break;
			}
		}
	}
net_socket_private::~net_socket_private()
{
	TRACE("delete net_socket %p\n", this);

	if (parent != NULL)
		panic("socket still has a parent!");

	if (is_in_socket_list) {
		MutexLocker _(sSocketLock);
		sSocketList.Remove(this);
	}

	mutex_lock(&lock);

	// also delete all children of this socket
	while (net_socket_private* child = pending_children.RemoveHead()) {
		child->RemoveFromParent();
	}
	while (net_socket_private* child = connected_children.RemoveHead()) {
		child->RemoveFromParent();
	}

	mutex_unlock(&lock);

	put_domain_protocols(this);

	mutex_destroy(&lock);
}
static status_t
socket_std_ops(int32 op, ...)
{
	switch (op) {
		case B_MODULE_INIT:
		{
			new (&sSocketList) SocketList;
			mutex_init(&sSocketLock, "socket list");

#if ENABLE_DEBUGGER_COMMANDS
			add_debugger_command("sockets", dump_sockets, "lists all sockets");
			add_debugger_command("socket", dump_socket, "dumps a socket");
#endif
			return B_OK;
		}
		case B_MODULE_UNINIT:
			ASSERT(sSocketList.IsEmpty());
			mutex_destroy(&sSocketLock);

#if ENABLE_DEBUGGER_COMMANDS
			remove_debugger_command("socket", dump_socket);
			remove_debugger_command("sockets", dump_sockets);
#endif
			return B_OK;

		default:
			return B_ERROR;
	}
}
Beispiel #6
0
	//start listening for connections and processing messages.
	inline void synchListen(){
		_DB std::cout << "Entering synchListen()\n";
		listen(serverSocket, SOMAXCONN);

		SOCKET accepted = -1;
		bool listening = true;

		auto lamb = [&](bool& listening){
			while (listening && runListenLoop){
				socklen_t size = sizeof(serverAddress);
				accepted = accept(serverSocket, (sockaddr *)&serverAddress, &size);
				if (accepted == SOCKET_ERROR){
					//error
				}
				else{
					std::lock_guard<std::recursive_mutex> lock(mutex);
					readList.pushSocket(accepted, serverAddress);
					_DB std::cout << "Adding SOCKET `" << accepted << "` to connected to `" << readList.getAddressString(accepted) << "`." << std::endl;
				}


			}
		};

		auto f = std::async(std::launch::async, lamb, std::ref(listening));
		_DB std::cout << "Fired the socket aceptor!\n";
		bool run = true;
		runListenLoop = true;
		while (run && runListenLoop){
			auto list = readList.getReadable();
			while (list.size() > 0){
				std::lock_guard<std::recursive_mutex> lock(mutex);
				_DB std::cout << "_________________________________________\n";
				//std::lock_guard<std::mutex> lock(mutex);

				ProtMsg msg = getProtocolMessage(list.front());
				int ret = handleProtocol(msg, list.front(), run);
				_DB std::cout << "handling protocol messages.\n";
				if (ret == PROTOCOLCODES::CLOSEME){
					readList.popSocket(list.front());
				}
				list.pop_front();
			}
		}
		_DB std::cout << "Exiting sychlisten loop.\n";
	}
Beispiel #7
0
	//send data to a socket at a specific address.
	inline void sendData(const std::string& address, char * src, uint32_t size){
		SOCKET socket = 0;
		for (const auto& e : readList.sockets){
			if (readList.getAddressString(e.first) == address){
				socket = e.first;
				Socket::sendData(socket, src, size);
			}
		}
	}
Beispiel #8
0
bool
Msg2Msg::AddNewRcvSocket(const char* socketAddrStr)
{
    char charAddr[255];
    memset(charAddr,0,255);
    ProtoAddress rcv_addr;
    int rcv_port; 
    //parse socketAddrStr
    const char* index = strchr(socketAddrStr,'/');
    if(index!=NULL)
    {
        strncpy(charAddr,socketAddrStr,index-socketAddrStr);
        if(!(rcv_addr.ResolveFromString(charAddr)))
        {
            DMSG(0,"Msg2Msg::AddNewRcvSocket() Error setting address to %s\n",charAddr);
            return false;
        }
        rcv_port = atoi(index+1);
    }
    else
    {
        rcv_port = atoi(socketAddrStr);
    }
    ListableSocket *newSocketPtr = new ListableSocket(ProtoPipe::UDP);
    if(!newSocketPtr)
    {
        DMSG(0,"Msg2MsgAddNewRcvSocket error allocing new socket\n");
        return false;
    }
    newSocketPtr->SetNotifier(&GetSocketNotifier());
    newSocketPtr->SetListener(this,&Msg2Msg::OnSocketListenEvent);//bunny the this will need to be changed
    if(!(newSocketPtr->Open(rcv_port,ProtoAddress::IPv4)))
    {
        DMSG(0,"Msg2MsgAddNewRcvSocket Error Opening the socket rcv port %d\n",rcv_port);
        delete newSocketPtr;
        return false;
    }
    if(rcv_addr.IsMulticast()) //do multicast stuff
    {
        if(!newSocketPtr->JoinGroup(rcv_addr))
        {
            DMSG(0,"Msg2MsgAddNewRcvSocket Error joining the multicast group %s\n",rcv_addr.GetHostString());
            newSocketPtr->Close();
            delete newSocketPtr;
            return false;
        }
    }
    rcvSockets.Append(*newSocketPtr);
    return true;
}
void
net_socket_private::RemoveFromParent()
{
	ASSERT(!is_in_socket_list && parent != NULL);

	parent = NULL;

	mutex_lock(&sSocketLock);
	sSocketList.Add(this);
	mutex_unlock(&sSocketLock);

	is_in_socket_list = true;

	ReleaseReference();
}
status_t
socket_get_next_stat(uint32* _cookie, int family, struct net_stat* stat)
{
	MutexLocker locker(sSocketLock);

	net_socket_private* socket = NULL;
	SocketList::Iterator iterator = sSocketList.GetIterator();
	uint32 cookie = *_cookie;
	uint32 count = 0;

	while (true) {
		socket = iterator.Next();
		if (socket == NULL)
			return B_ENTRY_NOT_FOUND;

		// TODO: also traverse the pending connections
		if (count == cookie)
			break;

		if (family == -1 || family == socket->family)
			count++;
	}

	*_cookie = count + 1;

	stat->family = socket->family;
	stat->type = socket->type;
	stat->protocol = socket->protocol;
	stat->owner = socket->owner;
	stat->state[0] = '\0';
	memcpy(&stat->address, &socket->address, sizeof(struct sockaddr_storage));
	memcpy(&stat->peer, &socket->peer, sizeof(struct sockaddr_storage));
	stat->receive_queue_size = 0;
	stat->send_queue_size = 0;

	// fill in protocol specific data (if supported by the protocol)
	size_t length = sizeof(net_stat);
	socket->first_info->control(socket->first_protocol, socket->protocol,
		NET_STAT_SOCKET, stat, &length);

	return B_OK;
}
static int
dump_sockets(int argc, char** argv)
{
	kprintf("address        kind  owner protocol   module_info parent\n");

	SocketList::Iterator iterator = sSocketList.GetIterator();
	while (net_socket_private* socket = iterator.Next()) {
		print_socket_line(socket, "");

		SocketList::Iterator childIterator
			= socket->pending_children.GetIterator();
		while (net_socket_private* child = childIterator.Next()) {
			print_socket_line(child, " ");
		}

		childIterator = socket->connected_children.GetIterator();
		while (net_socket_private* child = childIterator.Next()) {
			print_socket_line(child, " ");
		}
	}

	return 0;
}
status_t
socket_open(int family, int type, int protocol, net_socket** _socket)
{
	net_socket_private* socket;
	status_t status = create_socket(family, type, protocol, &socket);
	if (status != B_OK)
		return status;

	status = socket->first_info->open(socket->first_protocol);
	if (status != B_OK) {
		delete socket;
		return status;
	}

	socket->owner = team_get_current_team_id();
	socket->is_in_socket_list = true;

	mutex_lock(&sSocketLock);
	sSocketList.Add(socket);
	mutex_unlock(&sSocketLock);

	*_socket = socket;
	return B_OK;
}
Beispiel #13
0
bool
Msg2Msg::AddNewSndSocket(const char* socketAddrStr)
{
    char charAddr[255];
    memset(charAddr,0,255);
    ProtoAddress dst_addr;
    int dst_port;
    int src_port;//bunny setting this to dst port for now this should be controled seperatly
    //parse the string
    const char* index = strchr(socketAddrStr,'/');
    if(index!=NULL)
    {
        strncpy(charAddr,socketAddrStr,index-socketAddrStr);
        if(!dst_addr.ResolveFromString(charAddr))
        {
            DMSG(0,"Msg2Msg::AddNewSndSocket: Error setting address to %s\n",socketAddrStr);
            return false;
        }
        dst_port = atoi(index+1);
        src_port = dst_port;
        dst_addr.SetPort(dst_port);
    }
    else
    {
        DMSG(0,"Msg2Msg::AddNewSndSocket: Error missing \"/\" for send socket command\n");
        return false;
    }
    ListableSocket *newSocketPtr = new ListableSocket(ProtoSocket::UDP);
    if(!newSocketPtr)
    {
        DMSG(0,"Msg2MsgAddNewSndSocket error allocing new socket\n");
        return false;
    }
    if(!(newSocketPtr->Bind(src_port)))
    {
        DMSG(0,"Msg2MsgAddNewSndSocket: Error binding to src_port %d\n",src_port);
        delete newSocketPtr;
        return false;
    }
    if(!(newSocketPtr->Open(src_port,ProtoAddress::IPv4,false)))
    {
        DMSG(0,"msg2MsgAddNewSndSocket: Error opening socket on port %d\n",src_port);
        delete newSocketPtr;
        return false;
    }
    if(dst_addr.IsMulticast())
    {
        if(!newSocketPtr->JoinGroup(dst_addr))
        {
            DMSG(0,"Msg2MsgAddNewSndSocket: Error joinging multicast Group %s\n",dst_addr.GetHostString());
            newSocketPtr->Close();
            delete newSocketPtr;
            return false;
        }
    }
    if(!(newSocketPtr->Connect(dst_addr)))
    {
        DMSG(0,"Msg2MsgAddNewSndSocket: Error connecting to %s\n",dst_addr.GetHostString());
        newSocketPtr->Close();
        delete newSocketPtr;
        return false;
    }
    sndSockets.Append(*newSocketPtr);
    return true;
}
Beispiel #14
0
	//get a strign that reprisents the address of a port
	inline std::string getAddressString(SOCKET sock){
		std::lock_guard<std::recursive_mutex> lock(mutex);
		return readList.getAddressString(sock);
	}
Beispiel #15
0
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout)
{
#if defined(POCO_HAVE_FD_EPOLL)

	int epollSize = readList.size() + writeList.size() + exceptList.size();
	if (epollSize == 0) return 0;

	int epollfd = -1;
	{
		struct epoll_event eventsIn[epollSize];
		memset(eventsIn, 0, sizeof(eventsIn));
		struct epoll_event* eventLast = eventsIn;
		for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it)
		{
			poco_socket_t sockfd = it->sockfd();
			if (sockfd != POCO_INVALID_SOCKET)
			{
				struct epoll_event* e = eventsIn;
				for (; e != eventLast; ++e)
				{
					if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
						break;
				}
				if (e == eventLast)
				{
					e->data.ptr = &(*it);
					++eventLast;
				}
				e->events |= EPOLLIN;
			}
		}

		for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it)
		{
			poco_socket_t sockfd = it->sockfd();
			if (sockfd != POCO_INVALID_SOCKET)
			{
				struct epoll_event* e = eventsIn;
				for (; e != eventLast; ++e)
				{
					if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
						break;
				}
				if (e == eventLast)
				{
					e->data.ptr = &(*it);
					++eventLast;
				}
				e->events |= EPOLLOUT;
			}
		}

		for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it)
		{
			poco_socket_t sockfd = it->sockfd();
			if (sockfd != POCO_INVALID_SOCKET)
			{
				struct epoll_event* e = eventsIn;
				for (; e != eventLast; ++e)
				{
					if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
						break;
				}
				if (e == eventLast)
				{
					e->data.ptr = &(*it);
					++eventLast;
				}
				e->events |= EPOLLERR;
			}
		}

		epollSize = eventLast - eventsIn;
		epollfd = epoll_create(epollSize);
		if (epollfd < 0)
		{
			char buf[1024];
			strerror_r(errno, buf, sizeof(buf));
			SocketImpl::error(std::string("Can't create epoll queue: ") + buf);
		}

		for (struct epoll_event* e = eventsIn; e != eventLast; ++e)
		{
			poco_socket_t sockfd = reinterpret_cast<Socket*>(e->data.ptr)->sockfd();
			if (sockfd != POCO_INVALID_SOCKET)
			{
				if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0)
				{
					char buf[1024];
					strerror_r(errno, buf, sizeof(buf));
					::close(epollfd);
					SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf);
				}
			}
		}
	}

	struct epoll_event eventsOut[epollSize];
	memset(eventsOut, 0, sizeof(eventsOut));

	Poco::Timespan remainingTime(timeout);
	int rc;
	do
	{
		Poco::Timestamp start;
		rc = epoll_wait(epollfd, eventsOut, epollSize, remainingTime.totalMilliseconds());
		if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
		{
 			Poco::Timestamp end;
			Poco::Timespan waited = end - start;
			if (waited < remainingTime)
				remainingTime -= waited;
			else
				remainingTime = 0;
		}
	}
	while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);

	::close(epollfd);
	if (rc < 0) SocketImpl::error();

 	SocketList readyReadList;
	SocketList readyWriteList;
	SocketList readyExceptList;
	for (int n = 0; n < rc; ++n)
	{
		if (eventsOut[n].events & EPOLLERR)
			readyExceptList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
		if (eventsOut[n].events & EPOLLIN)
			readyReadList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
		if (eventsOut[n].events & EPOLLOUT)
			readyWriteList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
	}
	std::swap(readList, readyReadList);
	std::swap(writeList, readyWriteList);
	std::swap(exceptList, readyExceptList);
	return readList.size() + writeList.size() + exceptList.size();

#elif defined(POCO_HAVE_FD_POLL)

	nfds_t nfd = readList.size() + writeList.size() + exceptList.size();
	if (0 == nfd) return 0;

	SharedPollArray pPollArr = new pollfd[nfd];

	int idx = 0;
	for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it)
	{
		pPollArr[idx].fd = int(it->sockfd());
		pPollArr[idx++].events |= POLLIN;
	}

	SocketList::iterator begR = readList.begin();
	SocketList::iterator endR = readList.end();
	for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it)
	{
		SocketList::iterator pos = std::find(begR, endR, *it);
		if (pos != endR) 
		{
			pPollArr[pos-begR].events |= POLLOUT;
			--nfd;
		}
		else
		{
			pPollArr[idx].fd = int(it->sockfd());
			pPollArr[idx++].events |= POLLOUT;
		}
	}

	SocketList::iterator begW = writeList.begin();
	SocketList::iterator endW = writeList.end();
	for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it)
	{
		SocketList::iterator pos = std::find(begR, endR, *it);
		if (pos != endR) --nfd;
		else
		{
			SocketList::iterator pos = std::find(begW, endW, *it);
			if (pos != endW) --nfd;
			else pPollArr[idx++].fd = int(it->sockfd());
		}
	}

	Poco::Timespan remainingTime(timeout);
	int rc;
	do
	{
		Poco::Timestamp start;
		rc = ::poll(pPollArr, nfd, timeout.totalMilliseconds());
		if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
		{
			Poco::Timestamp end;
			Poco::Timespan waited = end - start;
			if (waited < remainingTime) remainingTime -= waited;
			else remainingTime = 0;
		}
	}
	while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
	if (rc < 0) SocketImpl::error();

	SocketList readyReadList;
	SocketList readyWriteList;
	SocketList readyExceptList;

	SocketList::iterator begE = exceptList.begin();
	SocketList::iterator endE = exceptList.end();
	for (int idx = 0; idx < nfd; ++idx)
	{
		SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd));
		if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt);
		slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd));
		if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt);
		slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd));
		if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt);
	}
	std::swap(readList, readyReadList);
	std::swap(writeList, readyWriteList);
	std::swap(exceptList, readyExceptList);
	return readList.size() + writeList.size() + exceptList.size();

#else

	fd_set fdRead;
	fd_set fdWrite;
	fd_set fdExcept;
	int nfd = 0;
	FD_ZERO(&fdRead);
	for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (int(fd) > nfd)
				nfd = int(fd);
			FD_SET(fd, &fdRead);
		}
	}
	FD_ZERO(&fdWrite);
	for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (int(fd) > nfd)
				nfd = int(fd);
			FD_SET(fd, &fdWrite);
		}
	}
	FD_ZERO(&fdExcept);
	for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (int(fd) > nfd)
				nfd = int(fd);
			FD_SET(fd, &fdExcept);
		}
	}
	if (nfd == 0) return 0;
	Poco::Timespan remainingTime(timeout);
	int rc;
	do
	{
		struct timeval tv;
		tv.tv_sec  = (long) remainingTime.totalSeconds();
		tv.tv_usec = (long) remainingTime.useconds();
		Poco::Timestamp start;
		rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv);
		if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
		{
			Poco::Timestamp end;
			Poco::Timespan waited = end - start;
			if (waited < remainingTime)
				remainingTime -= waited;
			else
				remainingTime = 0;
		}
	}
	while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
	if (rc < 0) SocketImpl::error();
	
	SocketList readyReadList;
	for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (FD_ISSET(fd, &fdRead))
				readyReadList.push_back(*it);
		}
	}
	std::swap(readList, readyReadList);
	SocketList readyWriteList;
	for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (FD_ISSET(fd, &fdWrite))
				readyWriteList.push_back(*it);
		}
	}
	std::swap(writeList, readyWriteList);
	SocketList readyExceptList;
	for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
	{
		poco_socket_t fd = it->sockfd();
		if (fd != POCO_INVALID_SOCKET)
		{
			if (FD_ISSET(fd, &fdExcept))
				readyExceptList.push_back(*it);
		}
	}
	std::swap(exceptList, readyExceptList);	
	return rc; 

#endif // POCO_HAVE_FD_EPOLL
}
Beispiel #16
0
void close_all(SocketList& list)
{
    SocketListLock lock(list);
    list.close_all();
}
Beispiel #17
0
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout)
{
	fd_set fdRead;
	fd_set fdWrite;
	fd_set fdExcept;
	int nfd = 0;
	FD_ZERO(&fdRead);
	for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
	{
		if (int(it->sockfd()) > nfd)
			nfd = int(it->sockfd());
		FD_SET(it->sockfd(), &fdRead);
	}
	FD_ZERO(&fdWrite);
	for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
	{
		if (int(it->sockfd()) > nfd)
			nfd = int(it->sockfd());
		FD_SET(it->sockfd(), &fdWrite);
	}
	FD_ZERO(&fdExcept);
	for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
	{
		if (int(it->sockfd()) > nfd)
			nfd = int(it->sockfd());
		FD_SET(it->sockfd(), &fdExcept);
	}
	Poco::Timespan remainingTime(timeout);
	int rc;
	do
	{
		struct timeval tv;
		tv.tv_sec  = (long) remainingTime.totalSeconds();
		tv.tv_usec = (long) remainingTime.useconds();
		Poco::Timestamp start;
		rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv);
		if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
		{
			Poco::Timestamp end;
			Poco::Timespan waited = end - start;
			if (waited < remainingTime)
				remainingTime -= waited;
			else
				remainingTime = 0;
		}
	}
	while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
	if (rc < 0) SocketImpl::error();
	
	SocketList readyReadList;
	for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
	{
		if (FD_ISSET(it->sockfd(), &fdRead))
			readyReadList.push_back(*it);
	}
	std::swap(readList, readyReadList);
	SocketList readyWriteList;
	for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
	{
		if (FD_ISSET(it->sockfd(), &fdWrite))
			readyWriteList.push_back(*it);
	}
	std::swap(writeList, readyWriteList);
	SocketList readyExceptList;
	for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
	{
		if (FD_ISSET(it->sockfd(), &fdExcept))
			readyExceptList.push_back(*it);
	}
	std::swap(exceptList, readyExceptList);	
	return rc; 
}