Ejemplo n.º 1
0
void epollEngine::MessageLoop()
{
	const static int maxevents = 1024;
	struct epoll_event events[1024];
	int nfds, i;
	BaseSocket * s;
	while(m_running)
	{
        	nfds = epoll_wait(epoll_fd, events, maxevents, 1000);
		for(i = 0; i < nfds; ++i)
		{
	            s = fds[events[i].data.fd];
			if(s == 0)
			{
				printf("epoll returned invalid fd %u\n", events[i].data.fd);
				continue;
			}

			if(events[i].events & EPOLLHUP || events[i].events & EPOLLERR)
			{
				s->OnError(errno);
			}
			else if(events[i].events & EPOLLIN)
			{
				s->OnRead(0);
				if(s->Writable() && !s->m_writeLock)
				{
					++s->m_writeLock;
					WantWrite(s);
				}
			}
			else if(events[i].events & EPOLLOUT)
			{
				s->OnWrite(0);
				if(!s->Writable())
				{
					/* change back to read state */
					struct epoll_event ev;
					memset(&ev, 0, sizeof(epoll_event));
					ev.data.fd = s->GetFd();
					ev.events = EPOLLIN | EPOLLET;

					epoll_ctl(epoll_fd, EPOLL_CTL_MOD, s->GetFd(), &ev);
					--s->m_writeLock;
				}
			}
		}
	}
}
Ejemplo n.º 2
0
void SelectEngine::Shutdown()
{
    m_running = false;
    m_socketLock.Acquire();
    BaseSocket * s;
    for(map<int, BaseSocket*>::iterator itr = m_sockets.begin(); itr != m_sockets.end(); )
    {
        s = itr->second;
        ++itr;
        s->Delete();
    }
    m_socketLock.Release();

    /* shutdown the socket deleter */
    sSocketDeleter.Kill();

    /* delete the socket deleter */
    delete SocketDeleter::getSingletonPtr();

    /* delete us */
    delete this;
}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
    int port = 8888;
    string ip = "127.0.0.1";
    BaseSocket toserver;

#ifdef TEST_TCP
    if (!toserver.Create()) {
        cerr << "client create error." << endl;
        return -1;
    }
    
    string host;
    int peer;
    
    if (!toserver.Connect(ip, port)) {
        cerr << "connect to server error." << endl;
        return -1;
    }
    if (!toserver.GetPeer(host, peer)) {
        cerr <<   "server get peer error." << endl;
        //return -1;
    }
    
    cout << "connected to " << host << " : " << peer << endl;
    
    cout << toserver.Send("this is the client sending msg...") << endl;
    cout << toserver.Recv() << endl;
    
    return 0;  
#endif
    
#ifdef TEST_UDP
     if (!toserver.Create(true)) {
        cerr << "client create error." << endl;
        return -1;
    }
   
    toserver.SendTo("udp test from client...", ip, port);
    cout << toserver.RecvFrom(ip, port) << endl;
    return 0;  
#endif
}
Ejemplo n.º 4
0
void kqueueEngine::MessageLoop()
{
	const static int maxevents = MAX_DESCRIPTORS;
	timespec timeout;
	timeout.tv_sec = 1;
	timeout.tv_nsec = 0;
	struct kevent events[MAX_DESCRIPTORS];
	struct kevent ev;
	int nfds, i;
	BaseSocket * s;
	while(m_running)
	{
		nfds = kevent(kq, 0, 0, events, maxevents, &timeout);
		for(i = 0; i < nfds; ++i)
		{
	        s = fds[events[i].ident];
			if(s == 0)
			{
				printf("kqueue returned invalid fd %u\n", events[i].ident);
				continue;
			}

			if(events[i].flags & EV_EOF || events[i].flags & EV_ERROR)
			{
				s->OnError(events[i].fflags);
				continue;
			}

			if(events[i].filter == EVFILT_READ)
			{
				s->OnRead(0);
                if(s->Writable() && !s->m_writeLock)
				{
					++s->m_writeLock;
					WantWrite(s);
				}
			}
			else if(events[i].filter == EVFILT_WRITE)
			{
				s->OnWrite(0);
				if(!s->Writable())
				{
					--s->m_writeLock;
					EV_SET(&ev, s->GetFd(), EVFILT_READ, EV_ADD, 0, 0, NULL);
					if(kevent(kq, &ev, 1, NULL, 0, NULL) < 0)
						printf("!! could not modify kevent (to read) for fd %u\n", s->GetFd());
				}
				else
				{
					EV_SET(&ev, s->GetFd(), EVFILT_WRITE, EV_ADD | EV_ONESHOT, 0, 0, NULL);
                    if(kevent(kq, &ev, 1, NULL, 0, NULL) < 0)
	                    printf("!! could not modify kevent (to write) for fd %u\n", s->GetFd());
				}

			}
			else
			{
				printf("Unknwon filter: %u Fflags: %u, fd: %u, flags: %u\n", events[i].filter, events[i].fflags, events[i].ident, events[i].flags);
			}
		}
	}
}
Ejemplo n.º 5
0
void pollEngine::MessageLoop()
{
	const static int maxevents = 1024;
	int nfds, i;
	BaseSocket * s;
	timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec = 50000;

	while(m_running)
	{
        nfds = poll(poll_events, highest_fd + 1, 50);
		if(!m_running)
			return;

		if(nfds > 0)
		{
			for(i = 0; i <= highest_fd; ++i)
			{
                if(poll_events[i].fd > 0)
				{
					s = fds[i];
					if(s == 0)
					{
						printf("poll returned invalid fd %u\n", i);
						poll_events[i].fd = -1;
						poll_events[i].events = 0;
						poll_events[i].revents = 0;
						continue;
					}

					if(poll_events[i].revents & POLLERR || poll_events[i].revents & POLLHUP)
					{
						s->Disconnect();
						continue;
					}

					if(poll_events[i].revents & POLLIN)
					{
						s->OnRead(0);

						/* are we writable now? */
						if(s->Writable() && !s->m_writeLock)
						{
							++s->m_writeLock;
							poll_events[i].events = POLLOUT;
						}
					}
					
					if(poll_events[i].revents & POLLOUT)
					{
						s->OnWrite(0);

						/* are we readable now? */
						if(!s->Writable())
						{
							--s->m_writeLock;
							poll_events[i].events = POLLIN;
						}
					}
				}
			}
		}
	}
}
Ejemplo n.º 6
0
// tunnel data from fdfrom to fdto (unfiltered)
// return false if throughput larger than target throughput
bool FDTunnel::tunnel(BaseSocket &sockfrom, BaseSocket &sockto, bool twoway, off_t targetthroughput, bool ignore)
{
    if (targetthroughput == 0)    {
#ifdef DGDEBUG
        std::cout << "No data expected, tunnelling aborted." << std::endl;
#endif
        return true;
    }

#ifdef DGDEBUG
    if (targetthroughput < 0)
        std::cout << "Tunnelling without known content-length" << std::endl;
    else
        std::cout << "Tunnelling with content length " << targetthroughput << std::endl;
#endif
    if ((sockfrom.bufflen - sockfrom.buffstart) > 0)    {
#ifdef DGDEBUG
        std::cout << "Data in fdfrom's buffer; sending " << (sockfrom.bufflen - sockfrom.buffstart) << " bytes" << std::endl;
#endif
        if (!sockto.writeToSocket(sockfrom.buffer + sockfrom.buffstart, sockfrom.bufflen - sockfrom.buffstart, 0, 120, false))
            throw std::runtime_error(std::string("Can't write to socket: ") + strerror(errno));

        throughput += sockfrom.bufflen - sockfrom.buffstart;
        sockfrom.bufflen = 0;
        sockfrom.buffstart = 0;
    }

    int maxfd, rc, fdfrom, fdto;

    fdfrom = sockfrom.getFD();
    fdto = sockto.getFD();

    maxfd = fdfrom > fdto ? fdfrom : fdto;  // find the maximum file
    // descriptor.  As Linux normally allows each process
    // to have up to 1024 file descriptors, maxfd
    // prevents the kernel having to look through all
    // 1024 fds each fdSet could contain

    char buff[32768];  // buffer for the input
    timeval timeout;  // timeval struct
    timeout.tv_sec = 120;  // modify the struct so its a 120 sec timeout
    timeout.tv_usec = 0;

    fd_set fdSet;  // file descriptor set

    FD_ZERO(&fdSet);  // clear the set
    FD_SET(fdto, &fdSet);  // add fdto to the set
    FD_SET(fdfrom, &fdSet);  // add fdfrom to the set

    timeval t;  // we need a 2nd copy used later
    fd_set inset;  // we need a 2nd copy used later
    fd_set outset;  // we need a 3rd copy used later

    bool done = false;  // so we get past the first while

    while (!done && (targetthroughput > -1 ? throughput < targetthroughput : true))    {
        done = true;  // if we don't make a sucessful read and write this
        // flag will stay true and so the while() will exit

        inset = fdSet;  // as select() can modify the sets we need to take
        t = timeout;  // a copy each time round and use that

        if (ignore && !twoway) FD_CLR(fdto, &inset);

        if (selectEINTR(maxfd + 1, &inset, NULL, NULL, &t) < 1)            {
            break;  // an error occured or it timed out so end while()
        }

        if (FD_ISSET(fdfrom, &inset))  	// fdfrom is ready to be read from
        {
            if (targetthroughput > -1)
                // we have a target throughput - only read in the exact amount of data we've been told to
                // plus 2 bytes to "solve" an IE post bug with multipart/form-data forms:
                // adds an extra CRLF on certain requests, that it doesn't count in reported content-length
                rc = sockfrom.readFromSocket(buff, (((int)sizeof(buff) < ((targetthroughput - throughput)/*+2*/)) ? sizeof(buff) : (targetthroughput - throughput)/* + 2*/), 0, 0, false);
            else
                rc = sockfrom.readFromSocket(buff, sizeof(buff), 0, 0, false);

            // read as much as is available
            if (rc < 0)            {
                break;  // an error occured so end the while()
            }
            else if (!rc)            {
                done = true;  // none received so pipe is closed so flag it
            }
            else  	// some data read
            {
                throughput += rc;  // increment our counter used to log
                outset = fdSet;  // take a copy to work with
                FD_CLR(fdfrom, &outset);  // remove fdfrom from the set
                // as we are only interested in writing to fdto

                t = timeout;  // take a copy to work with

                if (selectEINTR(fdto + 1, NULL, &outset, NULL, &t) < 1)                {
                    break;  // an error occured or timed out so end while()
                }

                if (FD_ISSET(fdto, &outset))  	// fdto ready to write to
                {
                    if (!sockto.writeToSocket(buff, rc, 0, 0, false))  	// write data
                    {
                        break;  // was an error writing
                    }
                    done = false;  // flag to say data still to be handled
                }                else                {
                    break;  // should never get here
                }
            }
        }
        if (FD_ISSET(fdto, &inset))  	// fdto is ready to be read from
        {
            if (!twoway)            {
                // since HTTP works on a simple request/response basis, with no explicit
                // communications from the client until the response has been completed
                // (just TCP cruft, which is of no interest to us here), tunnels only
                // need to be one way. As soon as the client tries to send data, break
                // the tunnel, as it will be a new request, possibly to an entirely
                // different webserver. This is important for proper filtering when
                // persistent connection support gets implemented. PRA 2005-11-14
#ifdef DGDEBUG
                std::cout << "fdto is sending data; closing tunnel. (This must be a persistent connection.)" << std::endl;
#endif
                break;
            }

            // read as much as is available
            rc = sockto.readFromSocket(buff, sizeof(buff), 0, 0, false);

            if (rc < 0)            {
                break;  // an error occured so end the while()
            }
            else if (!rc)            {
                done = true;  // none received so pipe is closed so flag it
                break;
            }
            else  	// some data read
            {
                outset = fdSet;  // take a copy to work with
                FD_CLR(fdto, &outset);  // remove fdto from the set
                // as we are only interested in writing to fdfrom

                t = timeout;  // take a copy to work with

                if (selectEINTR(fdfrom + 1, NULL, &outset, NULL, &t) < 1)                {
                    break;  // an error occured or timed out so end while()
                }

                if (FD_ISSET(fdfrom, &outset))  	// fdfrom ready to write to
                {
                    if (!sockfrom.writeToSocket(buff, rc, 0, 0, false))  	// write data
                    {
                        break;  // was an error writing
                    }
                    done = false;  // flag to say data still to be handled
                }                else                {
                    break;  // should never get here
                }
            }
        }
    }
#ifdef DGDEBUG
    if ((throughput >= targetthroughput) && (targetthroughput > -1))
        std::cout << "All expected data tunnelled. (expected " << targetthroughput << "; tunnelled " << throughput << ")" << std::endl;
    else
        std::cout <<"Tunnel closed."<< std::endl;
#endif
    return (targetthroughput > -1) ? (throughput <= targetthroughput) : true;
}