void bufcase(int x){ bufstr("Case "); char num[10], nidx = 0; for(nidx = 0; x; ++nidx, x /= 10) num[nidx] = (x % 10) + '0'; while(nidx--) bufchar(num[nidx]); bufstr(":\n"); }
void EpollServer::serve() { #ifdef THREADED_SERVE init_thread(); #endif int sfd, s; int efd; struct epoll_event event; struct epoll_event *events; sfd = makeSvrSocket(); if (sfd == -1) abort(); s = make_socket_non_blocking(sfd); if (s == -1) abort(); reuseSock(sfd); efd = epoll_create(1); if (efd == -1) { perror("epoll_create"); abort(); } event.data.ptr = new EpollData(sfd, NULL); event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event); if (s == -1) { perror("epoll_ctl"); abort(); } /* Buffer where events are returned */ events = (epoll_event *) calloc(MAX_EVENTS, sizeof event); /* The event loop */ while (1) { int n, i; n = epoll_wait(efd, events, MAX_EVENTS, -1); for (i = 0; i < n; i++) { EpollData *edata = (EpollData*) events[i].data.ptr; if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* An error has occured on this fd, or the socket is not ready for reading (why were we notified then?) */ fprintf(stderr, "epoll error\n"); close(edata->fd()); delete edata; continue; } else if (sfd == edata->fd()) { if (_tcp == true) { /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { sockaddr *in_addr = (sockaddr *) calloc(1, sizeof(struct sockaddr)); socklen_t in_len = sizeof(struct sockaddr); int infd = accept(sfd, in_addr, &in_len); if (infd == -1) { free(in_addr); if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror("accept"); break; } } /* fprintf(stdout, "sin_family[%hu], sin_zero[%s], sin_addr.s_addr[%u], sin_port[%hu]\n", in_addr.sin_family, in_addr.sin_zero, in_addr.sin_addr.s_addr, in_addr.sin_port); */ /* char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; getnameinfo(in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, 0); if (s == 0) { printf("Accepted connection on descriptor %d " "(host=%s, _port=%s)\n", infd, hbuf, sbuf); }*/ /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ s = make_socket_non_blocking(infd); if (s == -1) { free(in_addr); abort(); } reuseSock(infd); event.data.ptr = new EpollData(infd, in_addr); event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { free(in_addr); perror("epoll_ctl"); abort(); } } continue; } else { int done = 0; while (1) { char buf[Env::BUF_SIZE]; memset(buf, 0, sizeof(buf)); //char *buf = (char*) calloc(Env::BUF_SIZE, sizeof(char)); sockaddr fromaddr; socklen_t sender_len = sizeof(struct sockaddr); ssize_t count = recvfrom(edata->fd(), buf, sizeof buf, 0, &fromaddr, &sender_len); //cout << "EpollServer.cpp: serve(): received "<< count << " bytes."<<endl; if (count == -1) { if (errno != EAGAIN) { perror("read"); done = 1; } } else if (count == 0) { done = 1; break; } else { #ifdef BIG_MSG bool ready = false; string bd = pbrb->getBdStr(sfd, buf, count, ready); if (ready) { #ifdef THREADED_SERVE EventData eventData(edata->fd(), bd.c_str(), bd.size(), fromaddr); _eventQueue.push(eventData); #else _ZProcessor->process(edata->fd(), bd.c_str(), fromaddr); #endif } #endif #ifdef SML_MSG #ifdef THREADED_SERVE EventData eventData(edata->fd(), buf, sizeof(buf), fromaddr); _eventQueue.push(eventData); #else string bufstr(buf); _ZProcessor->process(edata->fd(), bufstr.c_str(), fromaddr); #endif #endif } //memset(buf, 0, sizeof(buf)); //free(buf); } /*if (done) { close(edata->fd()); delete edata; }*/ } } else { if (_tcp == true) { /* We have data on the fd waiting to be read. Read and display it. We must read whatever data is available completely, as we are running in edge-triggered mode and won't get a notification again for the same data. */ int done = 0; while (1) { char buf[Env::BUF_SIZE]; memset(buf, 0, sizeof(buf)); //char *buf = (char*) calloc(Env::BUF_SIZE, sizeof(char)); ssize_t count = recv(edata->fd(), buf, sizeof(buf), 0); if (count == -1) { /* If errno == EAGAIN, that means we have read all data. So go back to the main loop. */ if (errno != EAGAIN) { perror("read"); done = 1; } /*else { printf( "Closed connection on descriptor %d, -1<--recv\n", edata->fd()); close(edata->fd()); delete edata; }*/ break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } else { #ifdef BIG_MSG bool ready = false; string bd = pbrb->getBdStr(sfd, buf, count, ready); if (ready) { #ifdef THREADED_SERVE EventData eventData(edata->fd(), bd.c_str(), bd.size(), *edata->sender()); _eventQueue.push(eventData); #else _ZProcessor->process(edata->fd(), bd.c_str(), *edata->sender()); #endif } #endif #ifdef SML_MSG #ifdef THREADED_SERVE EventData eventData(edata->fd(), buf, sizeof(buf), *edata->sender()); _eventQueue.push(eventData); #else string bufstr(buf); _ZProcessor->process(edata->fd(), bufstr.c_str(), *edata->sender()); #endif #endif } //memset(buf, 0, sizeof(buf)); //free(buf); } if (done) { /*printf("Closed connection on descriptor %d, done.\n", edata->fd());*/ /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ close(edata->fd()); delete edata; } } //if TCP == true } } } free(events); close(sfd); EpollData *edata = (EpollData*) event.data.ptr; delete edata; }