/* * epoll_server() * wait on connections and read data */ static void epoll_server( const int child, uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t ppid) { int efd = -1, sfd = -1, rc = EXIT_SUCCESS; int so_reuseaddr = 1; int port = opt_epoll_port + child + (max_servers * instance); struct sigaction new_action; struct epoll_event *events = NULL; struct sockaddr *addr = NULL; socklen_t addr_len = 0; new_action.sa_handler = handle_socket_sigalrm; sigemptyset(&new_action.sa_mask); new_action.sa_flags = 0; if (sigaction(SIGALRM, &new_action, NULL) < 0) { pr_fail_err(name, "sigaction"); rc = EXIT_FAILURE; goto die; } if ((sfd = socket(opt_epoll_domain, SOCK_STREAM, 0)) < 0) { pr_fail_err(name, "socket"); rc = EXIT_FAILURE; goto die; } if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_err(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, opt_epoll_domain, port, &addr, &addr_len); if (bind(sfd, addr, addr_len) < 0) { pr_fail_err(name, "bind"); rc = EXIT_FAILURE; goto die_close; } if (epoll_set_fd_nonblock(sfd) < 0) { pr_fail_err(name, "setting socket to non-blocking"); rc = EXIT_FAILURE; goto die_close; } if (listen(sfd, SOMAXCONN) < 0) { pr_fail_err(name, "listen"); rc = EXIT_FAILURE; goto die_close; } if ((efd = epoll_create1(0)) < 0) { pr_fail_err(name, "epoll_create1"); rc = EXIT_FAILURE; goto die_close; } if (epoll_ctl_add(efd, sfd) < 0) { pr_fail_err(name, "epoll ctl add"); rc = EXIT_FAILURE; goto die_close; } if ((events = calloc(MAX_EPOLL_EVENTS, sizeof(struct epoll_event))) == NULL) { pr_fail_err(name, "epoll ctl add"); rc = EXIT_FAILURE; goto die_close; } do { int n, i; memset(events, 0, MAX_EPOLL_EVENTS * sizeof(struct epoll_event)); errno = 0; /* * Wait for 100ms for an event, allowing us to * to break out if opt_do_run has been changed */ n = epoll_wait(efd, events, MAX_EPOLL_EVENTS, 100); if (n < 0) { if (errno != EINTR) { pr_fail_err(name, "epoll_wait"); rc = EXIT_FAILURE; goto die_close; } break; } for (i = 0; i < n; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* * Error has occurred or fd is not * for reading anymore.. so reap fd */ (void)close(events[i].data.fd); } else if (sfd == events[i].data.fd) { /* * The listening socket has notification(s) * pending, so handle incoming connections */ if (epoll_notification(name, efd, sfd) < 0) break; } else { /* * The fd has data available, so read it */ epoll_recv_data(events[i].data.fd); } } } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: if (efd != -1) (void)close(efd); if (sfd != -1) (void)close(sfd); die: #ifdef AF_UNIX if (addr && (opt_epoll_domain == AF_UNIX)) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif free(events); exit(rc); }
int main (int argc, char *argv[]) { int sfd, s; int efd; struct epoll_event event; struct epoll_event *events; if (argc != 2) { fprintf (stderr, "Usage: %s [port]\n", argv[0]); exit (EXIT_FAILURE); } sfd = create_and_bind (argv[1]); if (sfd == -1) abort (); s = make_socket_non_blocking (sfd); if (s == -1) abort (); s = listen (sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort (); } efd = epoll_create1 (0); if (efd == -1) { perror ("epoll_create"); abort (); } event.data.fd = sfd; 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 = calloc (MAXEVENTS, sizeof event); /* The event loop */ while (1) { int n, i; n = epoll_wait (efd, events, MAXEVENTS, -1); for (i = 0; i < n; i++) { 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 (events[i].data.fd); continue; } else if (sfd == events[i].data.fd) { /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept (sfd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror ("accept"); break; } } s = getnameinfo (&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV); 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) abort (); event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror ("epoll_ctl"); abort (); } } continue; } else { /* 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) { ssize_t count; char buf[512]; count = read (events[i].data.fd, buf, sizeof buf); 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; } break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } /* Write the buffer to standard output */ handle_client_request(buf, count); } if (done) { printf ("Closed connection on descriptor %d\n", events[i].data.fd); /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ close (events[i].data.fd); } } } } free (events); close (sfd); return EXIT_SUCCESS; }
int fi_ibv_eq_open(struct fid_fabric *fabric, struct fi_eq_attr *attr, struct fid_eq **eq, void *context) { struct fi_ibv_eq *_eq; struct epoll_event event; int ret; _eq = calloc(1, sizeof *_eq); if (!_eq) return -ENOMEM; _eq->fab = container_of(fabric, struct fi_ibv_fabric, util_fabric.fabric_fid); fastlock_init(&_eq->lock); ret = dlistfd_head_init(&_eq->list_head); if (ret) { VERBS_INFO(FI_LOG_EQ, "Unable to initialize dlistfd\n"); goto err1; } _eq->epfd = epoll_create1(0); if (_eq->epfd < 0) { ret = -errno; goto err2; } memset(&event, 0, sizeof(event)); event.events = EPOLLIN; if (epoll_ctl(_eq->epfd, EPOLL_CTL_ADD, _eq->list_head.signal.fd[FI_READ_FD], &event)) { ret = -errno; goto err3; } switch (attr->wait_obj) { case FI_WAIT_NONE: case FI_WAIT_UNSPEC: case FI_WAIT_FD: _eq->channel = rdma_create_event_channel(); if (!_eq->channel) { ret = -errno; goto err3; } ret = fi_fd_nonblock(_eq->channel->fd); if (ret) goto err4; if (epoll_ctl(_eq->epfd, EPOLL_CTL_ADD, _eq->channel->fd, &event)) { ret = -errno; goto err4; } break; default: ret = -FI_ENOSYS; goto err1; } _eq->flags = attr->flags; _eq->eq_fid.fid.fclass = FI_CLASS_EQ; _eq->eq_fid.fid.context = context; _eq->eq_fid.fid.ops = &fi_ibv_eq_fi_ops; _eq->eq_fid.ops = &fi_ibv_eq_ops; *eq = &_eq->eq_fid; return 0; err4: if (_eq->channel) rdma_destroy_event_channel(_eq->channel); err3: close(_eq->epfd); err2: dlistfd_head_free(&_eq->list_head); err1: fastlock_destroy(&_eq->lock); free(_eq); return ret; }
int main(int argc, char **argv) { int n, nfds, res; struct itimerspec timerits; struct epoll_event events[MAX_EVENTS]; struct epoll_event timerevent; IxpClient* client; struct sb sb; signals_setup(&quit_handler); struct sb_entry sbe_sda = { .sbe_path = "/rbar/60_sda", .sbe_private = "sda", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; struct sb_entry sbe_sdb = { .sbe_path = "/rbar/61_sdb", .sbe_private = "sdb", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; struct sb_entry sbe_sdc = { .sbe_path = "/rbar/62_sdc", .sbe_private = "sdc", .sbe_init = &init_block, .sbe_update = &update_block, .sbe_foreground = 0xbbbbbb, .sbe_background = 0x444444, .sbe_border = 0x555555, }; int epollfd = epoll_create1(EPOLL_CLOEXEC); if(epollfd == -1) { perror("epoll_create"); abort(); } int timerfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK|TFD_CLOEXEC); if(timerfd == -1) { perror("timerfd_create"); abort(); } timerevent.events = EPOLLIN; timerevent.data.fd = timerfd; timerits.it_interval.tv_sec = 0; timerits.it_interval.tv_nsec = 250 * 1000 * 1000; timerits.it_value.tv_sec = timerits.it_interval.tv_sec; timerits.it_value.tv_nsec = timerits.it_interval.tv_nsec; client = ixp_nsmount("wmii"); if(client == NULL) { printf("ixp_nsmount: %s\n", ixp_errbuf()); abort(); } res = epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &timerevent); if(res == -1) { perror("epoll_ctl"); abort(); } res = timerfd_settime(timerfd, 0, &timerits, NULL); if(res == -1) { perror("timerfd_settime"); abort(); } sb_init(&sb, client); sb_add(&sb, &sbe_sda); sb_add(&sb, &sbe_sdb); sb_add(&sb, &sbe_sdc); while(1) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if(nfds == -1) { if(errno != EINTR) { perror("epoll_wait"); abort(); } } if(should_quit) { break; } for (n = 0; n < nfds; n++) { if(events[n].data.fd == timerfd) { uint64_t x; read(timerfd, &x, sizeof(x)); sb_update(&sb); } } } sb_finish(&sb); ixp_unmount(client); return 0; }
int main(int argc, char *argv[]) { int listenfd; int longindex = 0; int c; int count = 1000000; pid_t pid = getpid(); /* Epoll variables */ struct epoll_event ev; int epollfd; /* Default settings */ int addr_family = AF_INET; /* Default address family */ uint16_t listen_port = 6666; /* Support for both IPv4 and IPv6. * sockaddr_storage: Can contain both sockaddr_in and sockaddr_in6 */ struct sockaddr_storage listen_addr; memset(&listen_addr, 0, sizeof(listen_addr)); /* Parse commands line args */ while ((c = getopt_long(argc, argv, "c:l:64swv:", long_options, &longindex)) != -1) { if (c == 0) { /* optional handling "flag" options */ if (verbose) { printf("Flag option %s", long_options[longindex].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); } } if (c == 'c') count = atoi(optarg); if (c == 'l') listen_port = atoi(optarg); if (c == '4') addr_family = AF_INET; if (c == '6') addr_family = AF_INET6; if (c == 'w') write_something = 1; if (c == 'v') (optarg) ? verbose = atoi(optarg) : (verbose = 1); if (c == '?') return usage(argv); } if (verbose > 0) printf("IP%s TCP listen port %d PID:[%d]\n", (addr_family == AF_INET6) ? "v6":"v4", listen_port, pid); /* Socket setup stuff */ listenfd = Socket(addr_family, SOCK_STREAM, IPPROTO_IP); /* Enable use of SO_REUSEPORT for multi-process testing */ if (so_reuseport) { if ((setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &so_reuseport, sizeof(so_reuseport))) < 0) { printf("ERROR: No support for SO_REUSEPORT\n"); perror("- setsockopt(SO_REUSEPORT)"); exit(EXIT_FAIL_SOCKOPT); } else if (verbose) { printf(" - Enabled SO_REUSEPORT\n"); } } /* Setup listen_addr depending on IPv4 or IPv6 address */ //setup_sockaddr(addr_family, &listen_addr, "0.0.0.0", listen_port); if (addr_family == AF_INET) { struct sockaddr_in *addr4 = (struct sockaddr_in *)&listen_addr; addr4->sin_family = addr_family; addr4->sin_port = htons(listen_port); addr4->sin_addr.s_addr = htonl(INADDR_ANY); } else if (addr_family == AF_INET6) { struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&listen_addr; addr6->sin6_family= addr_family; addr6->sin6_port = htons(listen_port); } Bind(listenfd, &listen_addr); /* Notice "backlog" limited by: /proc/sys/net/core/somaxconn */ listen(listenfd, 1024); /* Epoll */ if (use_epoll) { epollfd = epoll_create1(0); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } /* Add listen socket */ ev.events = EPOLLIN; ev.data.fd = listenfd; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev) == -1) { perror(" - epoll_ctl: cannot add listen sock"); exit(EXIT_FAILURE); } epoll_connections(epollfd, &ev, listenfd, count); close(epollfd); } else { wait_for_connections(listenfd, count); } close(listenfd); return 0; }
// receive each one block from all sender void* ExpandableBlockStreamExchangeEpoll::receiver(void* arg){ ExpandableBlockStreamExchangeEpoll* Pthis=(ExpandableBlockStreamExchangeEpoll*)arg; struct epoll_event event; struct epoll_event *events; int status; /** create epoll **/ Pthis->epoll_fd_ = epoll_create1(0); if (Pthis->epoll_fd_ == -1) { Pthis->logging_->elog("epoll create error!\n"); return 0; } event.data.fd = Pthis->sock_fd; event.events = EPOLLIN | EPOLLET; status = epoll_ctl(Pthis->epoll_fd_, EPOLL_CTL_ADD, Pthis->sock_fd, &event); if (status == -1) { Pthis->logging_->elog("epoll ctl error!\n"); return 0; } events=(epoll_event*)calloc(Pthis->nlowers,sizeof(epoll_event)); int fd_cur=0; ticks start=curtick(); std::vector<int> finish_times;//in ms while(true){ usleep(1); const int event_count = epoll_wait(Pthis->epoll_fd_, events, Pthis->nlowers, -1); for (int i = 0; i < event_count; i++) { if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { if (errno == EINTR) { continue; } Pthis->logging_->elog("[%ld] epoll error,reason:%s\n", Pthis->state.exchange_id_, strerror(errno)); FileClose(events[i].data.fd); std::cout << "in " << __FILE__ << ":" << __LINE__; printf("-----for debug:close fd %d.\n", events[i].data.fd); continue; } else if (Pthis->sock_fd == events[i].data.fd) { /* We have a notification on the listening socket, which means one or more incoming connections.*/ while (true) { sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept(Pthis->sock_fd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* all the incoming connections are processed.*/ break; } else { Pthis->logging_->elog("accept error! "); break; } } status=getnameinfo(&in_addr,in_len,hbuf,sizeof(hbuf),sbuf,sizeof(sbuf),NI_NUMERICHOST|NI_NUMERICSERV); if(status==0){ Pthis->logging_->log("[%ld] Accepted connection on descriptor %d (host=%s, port=%s),id=%d\n",Pthis->state.exchange_id_, infd, hbuf, sbuf,Pthis->state.exchange_id_); Pthis->lower_ip_array.push_back(hbuf); Pthis->lower_sock_fd_to_index[infd]=Pthis->lower_ip_array.size()-1; assert(Pthis->lower_ip_array.size()<=Pthis->state.lower_id_list_.size()); } /*Make the incoming socket non-blocking and add it to the list of fds to monitor.*/ if (!Pthis->SetSocketNonBlocking(infd)) { return 0; } event.data.fd = infd; event.events = EPOLLIN | EPOLLET; status = epoll_ctl(Pthis->epoll_fd_, EPOLL_CTL_ADD, infd, &event); if (status == -1) { Pthis->logging_->elog("epoll_ctl"); return 0; } } continue; } else { /* We have data on the fd waiting to be read.*/ int done = 0; while (true) { int byte_received; int socket_fd_index=Pthis->lower_sock_fd_to_index[events[i].data.fd]; byte_received=read(events[i].data.fd, (char*)Pthis->block_for_socket_[socket_fd_index]->getBlock()+Pthis->block_for_socket_[socket_fd_index]->GetCurSize(), Pthis->block_for_socket_[socket_fd_index]->GetRestSize()); if(byte_received==-1){ if(errno==EAGAIN){ /*We have read all the data,so go back to the loop.*/ break; } Pthis->logging_->elog("read error!\n"); done = 1; } else if (byte_received == 0) { /* End of file. The remote has closed the connection.*/ done = 1; break; } /* The data is successfully read.*/ Pthis->block_for_socket_[socket_fd_index]->IncreaseActualSize(byte_received); if (Pthis->block_for_socket_[socket_fd_index]->GetRestSize() > 0) { /** the current block is not read entirely from the sender, so continue the loop to read.**/ continue; } /** a block is completely read. **/ Pthis->logging_->log("[%ld] The %d-th block is received from Lower[%s]", Pthis->state.exchange_id_, Pthis->debug_received_block[socket_fd_index], Pthis->lower_ip_array[socket_fd_index].c_str()); Pthis->debug_received_block[socket_fd_index]++; /** deserialize the data block from sender to the blockstreambase (received_block_stream_) **/ Pthis->received_block_stream_->deserialize((Block*) Pthis->block_for_socket_[socket_fd_index]); /** mark block_for_socket_[socket_fd_index] to be empty so that it can accommodate the subsequent data **/ Pthis->block_for_socket_[socket_fd_index]->reset(); /** In the current implementation, a empty block stream means End-Of-File**/ const bool eof=Pthis->received_block_stream_->Empty(); if(!eof){ /** the newly obtained data block is validate, so we insert it into the buffer and post * sem_new_block_or_eof_ so that all the threads waiting for the semaphore continue. **/ Pthis->buffer->insertBlock(Pthis->received_block_stream_); //??? why is all ,not 1 // multiple threads will still compete with lock Pthis->sem_new_block_or_eof_.post(Pthis->number_of_registered_expanded_threads_); } else { /** The newly obtained data block is the end-of-file. **/ Pthis->logging_->log("[%ld] *****This block is the last one.", Pthis->state.exchange_id_); finish_times.push_back((int)getMilliSecond(start)); /** update the exhausted senders count and post sem_new_block_or_eof_ so that all the * threads waiting for the semaphore continue. **/ Pthis->nexhausted_lowers++; Pthis->sem_new_block_or_eof_.post(Pthis->number_of_registered_expanded_threads_); if (Pthis->nexhausted_lowers == Pthis->nlowers) { /* * When all the exchange lowers are exhausted, notify the buffer * that the input data is completely received. */ Pthis->buffer->setInputComplete(); /* print the finish times */ for(unsigned i=0;i<finish_times.size();i++){ printf("%d\t",finish_times[i]); } printf("\t Var:%5.4f\n",get_stddev(finish_times)); } Pthis->logging_->log( "[%ld] <<<<<<<<<<<<<<<<nexhausted_lowers=%d>>>>>>>>>>>>>>>>exchange=(%d,%d)", Pthis->state.exchange_id_, Pthis->nexhausted_lowers, Pthis->state.exchange_id_, Pthis->partition_offset); /** tell the sender that all the block are consumed so that the sender can close the socket**/ Pthis->SendBlockAllConsumedNotification(events[i].data.fd); Pthis->logging_->log("[%ld] This notification (all the blocks in the socket buffer are consumed) is send to the lower[%s] exchange=(%d,%d).\n", Pthis->state.exchange_id_, Pthis->lower_ip_array[socket_fd_index].c_str(), Pthis->state.exchange_id_, Pthis->partition_offset); } } if (done) { Pthis->logging_->log("[%ld] Closed connection on descriptor %d[%s]\n", Pthis->state.exchange_id_, events[i].data.fd, Pthis->lower_ip_array[Pthis->lower_sock_fd_to_index[events[i].data.fd]].c_str()); /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ FileClose(events[i].data.fd); } } } } }
int main (int argc, char *argv[]) { struct epoll_event event, *events; int sfd, s; int efd; struct stat st; char *fifo = "event.fifo"; if (lstat (fifo, &st) == 0) { if ((st.st_mode & S_IFMT) == S_IFREG) { errno = EEXIST; err_sys("lstat"); exit (1); } } unlink (fifo); if (mkfifo (fifo, 0600) == -1) { err_sys("mkfifo"); exit (1); } /* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */ sfd = open (fifo, O_RDWR | O_NONBLOCK, 0); if (sfd == -1) { err_sys("open"); exit (1); } s = make_socket_non_blocking (sfd); if (s == -1) { err_sys("socket error"); exit(1); } efd = epoll_create1 (0); if (efd == -1) { err_sys("epoll_create"); exit(1); } event.data.fd = sfd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); if (s == -1) { err_sys("epoll_ctl"); exit(1); } /* Buffer where events are returned */ events = calloc (MAX_EVENTS, sizeof event); //events = (struct 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++) { 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 (events[i].data.fd); continue; } else { /* 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. */ while (1) { ssize_t count; char buf[2]; count = read (events[i].data.fd, buf, sizeof buf); if (count == -1) { /* If errno == EAGAIN, that means we have read all data. So go back to the main loop. */ if (errno != EAGAIN) { err_sys("read"); } break; } /* Write the buffer to standard output */ s = write (1, buf, count); if (s == -1) { perror ("write"); abort (); } } } } } pause(); return 0; }
int main(int argc, char *argv[]) { struct epoll_event ev; struct epoll_event *evs; if (argc != 2) { fprintf(stderr, "Usage: epoll port\n"); exit(1); } int socketfd = create_socket_and_bind_port(argv[1]); if (socketfd == -1) { exit(EXIT_FAILURE); } if (make_fd_nonblock(socketfd) == -1) { exit(EXIT_FAILURE); } if (listen_socket(socketfd, MAXLISTEN) == -1) { exit(EXIT_FAILURE); } int epollfd; if ((epollfd = epoll_create1(0)) == -1) { perror("epoll_create1"); exit(EXIT_FAILURE); } ev.events = EPOLLIN | EPOLLET; ev.data.fd = socketfd; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, socketfd, &ev) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } evs= calloc(sizeof (struct epoll_event), MAXEVENTS); if (!evs) { perror("calloc"); exit(EXIT_FAILURE); } for ( ; ;) { int nret; nret = epoll_wait(epollfd, evs, MAXEVENTS, -1); int i; for (i = 0; i < nret; ++i) { ev = evs[i]; if ((ev.events & EPOLLERR) || (ev.events & EPOLLHUP) || (!(ev.events & EPOLLIN))) { fprintf(stderr, "epoll error: %u\n", ev.events); epoll_ctl(epollfd, EPOLL_CTL_DEL, ev.data.fd, NULL); close(ev.data.fd); continue; } if (ev.data.fd == socketfd) { for (; ;) { int newfd; struct sockaddr sa; socklen_t sa_len = sizeof(struct sockaddr); newfd = accept(socketfd, &sa, &sa_len); if (newfd == -1) { if ( errno == EAGAIN || errno == EWOULDBLOCK) { break; } perror("accept"); break; } char ip[INET6_ADDRSTRLEN]; void *addr = get_in_addr(&sa); inet_ntop(sa.sa_family, addr, ip, sizeof(ip)); printf("Accept connection %s on descriptor %d\n", ip, newfd); if (make_fd_nonblock(newfd) == -1) { exit(EXIT_FAILURE); } struct epoll_event newev; newev.data.fd = newfd; newev.events = EPOLLIN | EPOLLET; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, newfd, &newev) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } } // END FOR } // END IF else { int done = 0; for ( ; ;) { ssize_t count; char buf[BUFSIZ]; count = read(ev.data.fd, buf, BUFSIZ); if (count == -1) { if (errno != EAGAIN) { perror("read"); done = 1; } break; } else if (count == 0) { done = 1; break; } int nw = write(STDOUT_FILENO, buf, count); // write buf to standard output if (nw == -1) { perror("write"); exit(EXIT_FAILURE); } } // END FOR if (done == 1) { printf("Closed connection on descriptor %d\n", ev.data.fd); del_and_close_fd_from_epoll(epollfd, ev.data.fd); continue; } } // END ELSE } } }
io_service::io_service() { int flags = 0; efd = epoll_create1(flags); }
static int server_init(Server *s, unsigned n_sockets) { int r; unsigned i; assert(s); assert(n_sockets > 0); zero(*s); s->epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (s->epoll_fd < 0) { r = log_error_errno(errno, "Failed to create epoll object: %m"); goto fail; } for (i = 0; i < n_sockets; i++) { struct epoll_event ev; Fifo *f; int fd; fd = SD_LISTEN_FDS_START+i; r = sd_is_fifo(fd, NULL); if (r < 0) { log_error_errno(r, "Failed to determine file descriptor type: %m"); goto fail; } if (!r) { log_error("Wrong file descriptor type."); r = -EINVAL; goto fail; } f = new0(Fifo, 1); if (!f) { r = -ENOMEM; log_error_errno(errno, "Failed to create fifo object: %m"); goto fail; } f->fd = -1; zero(ev); ev.events = EPOLLIN; ev.data.ptr = f; if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { r = -errno; fifo_free(f); log_error_errno(errno, "Failed to add fifo fd to epoll object: %m"); goto fail; } f->fd = fd; LIST_PREPEND(fifo, s->fifos, f); f->server = s; s->n_fifos++; } r = bus_connect_system_systemd(&s->bus); if (r < 0) { log_error_errno(r, "Failed to get D-Bus connection: %m"); r = -EIO; goto fail; } return 0; fail: server_done(s); return r; }
/* Handles a number of connections for a thread. * * data The thread data. */ static void *ThreadHandler(void *data) { int ret; socklen_t socketfd = -1; int efd; struct epoll_event event; struct epoll_event event_conn; struct epoll_event* events = NULL; ThreadData* threadData = (ThreadData*)data; #ifdef WOLFSSL_ASYNC_CRYPT WOLF_EVENT* wolfEvents[MAX_WOLF_EVENTS]; #endif /* Initialize wolfSSL and create a context object. */ if (WolfSSLCtx_Init(version, ourCert, ourKey, verifyCert, cipherList, &threadData->devId, &threadData->ctx) == -1) { exit(EXIT_FAILURE); } /* Allocate space for EPOLL events to be stored. */ events = (struct epoll_event*)malloc(EPOLL_NUM_EVENTS * sizeof(*events)); if (events == NULL) exit(EXIT_FAILURE); /* Create a socket and listen for a client. */ if (CreateSocketListen(port, numClients, &socketfd) == EXIT_FAILURE) exit(EXIT_FAILURE); /* Create an EPOLL file descriptor. */ efd = epoll_create1(0); if (efd == -1) { fprintf(stderr, "ERROR: failed to create epoll\n"); exit(EXIT_FAILURE); } /* Add the event for communications on listening socket. */ memset(&event, 0, sizeof(event)); event.events = EPOLLIN; event.data.ptr = NULL; ret = epoll_ctl(efd, EPOLL_CTL_ADD, socketfd, &event); if (ret == -1) { fprintf(stderr, "ERROR: failed to add event to epoll\n"); exit(EXIT_FAILURE); } threadData->accepting = 1; /* Keep handling clients until done. */ while (!SSLConn_Done(sslConnCtx)) { int n; int i; #ifdef WOLFSSL_ASYNC_CRYPT do { double diff, start = current_time(1); ret = wolfSSL_CTX_AsyncPoll(threadData->ctx, wolfEvents, MAX_WOLF_EVENTS, WOLF_POLL_FLAG_CHECK_HW, &n); diff = current_time(0) - start; pthread_mutex_lock(&sslConnMutex); sslConnCtx->asyncTime += diff; pthread_mutex_unlock(&sslConnMutex); for (i = 0; i < n; i++) { SSLConn* sslConn = threadData->sslConn; while (sslConn != NULL) { if (sslConn->ssl != wolfEvents[i]->context) { sslConn = sslConn->next; continue; } SSLConn_ReadWrite(sslConnCtx, threadData, sslConn); break; } } } while (n > 0); #endif SSLConn_FreeSSLConn(threadData); #ifdef WOLFSSL_ASYNC_CRYPT /* Look for events. */ n = epoll_wait(efd, events, EPOLL_NUM_EVENTS, 0); #else /* Wait a second for events. */ n = epoll_wait(efd, events, EPOLL_NUM_EVENTS, 1); #endif /* Process all returned events. */ for (i = 0; i < n; i++) { /* Error event on socket. */ if (!(events[i].events & EPOLLIN)) { if (events[i].data.ptr == NULL) { /* Not a client, therefore the listening connection. */ close(socketfd); socketfd = -1; } else { /* Client connection. */ SSLConn_Close(sslConnCtx, threadData, events[i].data.ptr); ret = epoll_ctl(efd, EPOLL_CTL_ADD, socketfd, &event); } } else if (events[i].data.ptr == NULL) { SSLConn* sslConn; /* Accept a new client on the listener. */ ret = SSLConn_Accept(threadData, threadData->ctx, socketfd, &sslConn); if (ret == EXIT_SUCCESS) { /* Set EPOLL to check for events on the new socket. */ memset(&event_conn, 0, sizeof(event_conn)); event_conn.events = EPOLLIN | EPOLLET; event_conn.data.ptr = sslConn; ret = epoll_ctl(efd, EPOLL_CTL_ADD, sslConn->sockfd, &event_conn); if (ret == -1) { fprintf(stderr, "ERROR: failed add event to epoll\n"); exit(EXIT_FAILURE); } } if (threadData->cnt == sslConnCtx->numConns) { /* Don't accept any more TCP connections. */ ret = epoll_ctl(efd, EPOLL_CTL_DEL, socketfd, &event); if (ret == -1) { fprintf(stderr, "ERROR: failed delete epoll event\n"); exit(EXIT_FAILURE); } threadData->accepting = 0; } } else { if (sslConnCtx->totalTime == 0) { pthread_mutex_lock(&sslConnMutex); if (sslConnCtx->totalTime == 0) sslConnCtx->totalTime = current_time(1); pthread_mutex_unlock(&sslConnMutex); } ret = SSLConn_ReadWrite(sslConnCtx, threadData, events[i].data.ptr); } } /* Accept more connections again up to the maximum concurrent. */ if (!threadData->accepting && threadData->cnt < sslConnCtx->numConns) { ret = epoll_ctl(efd, EPOLL_CTL_ADD, socketfd, &event); if (ret == -1) { fprintf(stderr, "ERROR: failed add event to epoll\n"); exit(EXIT_FAILURE); } threadData->accepting = 1; } } if (socketfd != -1) close(socketfd); free(events); return NULL; }
static void lwan_fd_watch_init(struct lwan *l) { l->epfd = epoll_create1(EPOLL_CLOEXEC); if (l->epfd < 0) lwan_status_critical_perror("epoll_create1"); }
static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv; int fd; #ifdef HAVE_EPOLL_CREATE1 fd = epoll_create1(EPOLL_CLOEXEC); #else fd = epoll_create(size); #endif if (fd < 0) { pollset->p = NULL; return apr_get_netos_error(); } #ifndef HAVE_EPOLL_CREATE1 { int fd_flags; if ((fd_flags = fcntl(fd, F_GETFD)) == -1) { rv = errno; close(fd); pollset->p = NULL; return rv; } fd_flags |= FD_CLOEXEC; if (fcntl(fd, F_SETFD, fd_flags) == -1) { rv = errno; close(fd); pollset->p = NULL; return rv; } } #endif pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if ((flags & APR_POLLSET_THREADSAFE) && !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { close(fd); pollset->p = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { close(fd); pollset->p = NULL; return APR_ENOTIMPL; } #endif pollset->p->epoll_fd = fd; pollset->p->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); if (!(flags & APR_POLLSET_NOCOPY)) { APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); } return APR_SUCCESS; }
PollEpoll::PollEpoll():activeEv_(kMaxEvents) { evId_ = epoll_create1(EPOLL_CLOEXEC); }
void Engine::init(const char *fname) { DLOG(INFO) << "Loading configuration"; try { config.readFile(fname); } catch (const FileIOException &fioex) { throw std::runtime_error("I/O error while reading file."); } catch (const ParseException &pex) { throw std::runtime_error("Parse configuration file error"); } //Load server configuration here int number_of_worker; Setting &sconf = config.getRoot()["general"]; if (!sconf.lookupValue("number_of_worker", number_of_worker)) { number_of_worker = 10; DLOG(ERROR) << "Fail to load number_of_worker parameter from configuration file"; } for (int i = 0; i < number_of_worker; i++) { boost::shared_ptr<Worker> w(new Worker(i)); workers.push_back(w); } int task_queue_size; if (!sconf.lookupValue("task_queue_size", task_queue_size)) { task_queue_size = 100; DLOG(ERROR) << "Use default EventQueue size: 100"; } tasks.init(task_queue_size); if (!sconf.lookupValue("max_event", max_event)) { max_event = 512; DLOG(ERROR) << "Use default max_event: 512"; } /* register services */ REGISTER_SERVICE(CoreService); /* create epoll */ epoll_fd = epoll_create1(0); if (epoll_fd == -1) { throw std::runtime_error("Error in epoll_create"); } /* init components */ for (component_map::iterator it = components.begin(); it != components.end(); it++) { DLOG(INFO) << "Component:" << it->second->get_id(); it->second->init(); } }
void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; int epollfd = epoll_create1(EPOLL_CLOEXEC); struct epoll_event event1; bzero(&event1, sizeof(event1)); event1.data.fd = sockfd; event1.events = EPOLLIN | EPOLLET; // 设为 et 模式 if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &event1)) { perror("epoll_ctl: sockfd"); } setnonblocking(sockfd); printf("file fd: %d\n", fileno(fp)); struct epoll_event event2; bzero(&event2, sizeof(event2)); event2.data.fd = fileno(fp); event2.events = EPOLLIN | EPOLLET; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fileno(fp), &event2) < 0) { perror("epoll_ctl: fp"); } printf("file fd: %d\n", fileno(fp)); setnonblocking(fileno(fp)); struct epoll_event events[events_size]; for ( ; ; ) { int eventNums = epoll_wait(epollfd, events, events_size, timeoutMs); printf("after epoll\n"); int i, ret = 0, n = 0; for (i = 0; i < eventNums; i ++) { ret = n = 0; // socket 可读, et 模式下这次事件不会重复触发, 必须循环全部读取出来 if (events[i].data.fd == sockfd) { printf("sockfd ...\n"); bzero(recvline, MAXLINE); while ((ret = read(sockfd, recvline+n, MAXLINE)) > 0) { n += ret; printf("after sockfd read, ret = %d, n = %d; ...\n", ret, n); } if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { perror("str_cli: server terminated prematurely"); } fputs(recvline, stdout); } // 终端数据可读 else if (events[i].data.fd == fileno(fp)) { printf("terminal ...\n"); if (fgets(sendline, MAXLINE, fp) == NULL) { perror("fgets error"); } n = strlen(sendline); while (n > 0) { ret = write(sockfd, sendline+ret, n); printf("after sockfd write, ret = %d, n = %d; ...\n", ret, n); if (ret < n) { if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { perror("str_cli: write error"); } break; } n -= ret; } } } } }
int main(int argc, char *argv[]) { printf("%s", "start\n"); int listen_fd; int rcode; struct epoll_event *events; if (argc != 2) { fprintf(stderr, "usage: %s [port]\n", argv[0]); exit(EXIT_FAILURE); } struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; sa.sa_flags = 0; if (sigaction(SIGPIPE, &sa, NULL)) { printf("ignore SIGPIPE\n"); } struct sockaddr_in client_addr; socklen_t client_len = 1; memset(&client_addr, 0, sizeof(struct sockaddr_in)); /* create and bind the port, and then set the socket to non blocking mode */ listen_fd = open_listenfd(atoi(argv[1])); debug("listen fd = %d", listen_fd); rcode = make_socket_non_blocking(listen_fd); if (rcode == -1) { log_err("error when making socket non blocking"); abort(); } /* create epoll event */ int efd = epoll_create1(0); if (efd == -1) { log_err("epoll_create"); abort(); } struct epoll_event event; events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * MAXEVENTS); http_request_t *request = (http_request_t *)malloc(sizeof(http_request_t)); http_request_init(request, listen_fd); event.data.ptr = (void *)request; event.events = EPOLLIN | EPOLLET; /* register the listen event */ rcode = epoll_ctl(efd, EPOLL_CTL_ADD, listen_fd, &event); if (rcode == -1) { perror("epoll_ctl"); abort(); } threadpool_t *tp = threadpool_init(NUM_OF_THREADS); /* event loop */ while (1) { int n = epoll_wait(efd, events, MAXEVENTS, -1); /* process each incoming IO event */ int i; for (i = 0; i < n; i++) { http_request_t *r = (http_request_t *)events[i].data.ptr; int fd = r->fd; debug("event fd = %d", fd); if (fd == listen_fd) { /* incoming connection event */ while (1) { int client_fd; debug("waiting for accept"); client_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // we have already processed the incoming connection debug("incoming connection processed\n"); break; } else { log_err("error occured when accepting connection\n"); break; } } rcode = make_socket_non_blocking(client_fd); if (rcode == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) // we have already processed the incoming connection break; log_err("fail to accept the connection\n"); break; } debug("new connection fd %d", client_fd); http_request_t *request = (http_request_t *)malloc(sizeof(http_request_t)); http_request_init(request, client_fd); event.data.ptr = (void *)request; event.events = EPOLLIN | EPOLLET; /* add the new event into epoll */ rcode = epoll_ctl(efd, EPOLL_CTL_ADD, client_fd, &event); if (rcode == - 1) { log_err("fail in epoll_ctl in epoll_wait"); abort(); } } debug("end accept"); } else 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 */ log_err("error events: %d", events[i].events); if (events[i].events & EPOLLERR) log_err("EPOLLERR"); if (events[i].events & EPOLLHUP) log_err("EPOLLHUP"); if (!(events[i].events & EPOLLIN)) log_err("EPOLLIN"); close(fd); continue; } else { /* incoming data read event */ /* add the event to the thread pool list */ threadpool_add(tp, handle_http, events[i].data.ptr); debug("thread count: %d", tp->thread_count); debug("thread queue size: %d", tp->queue_size); } } } threadpool_destroy(tp); return 0; }
void *runServer(void* value) { int i = 0; Settings *settings = (Settings *)value; struct sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(settings->port); int master = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (0 >= inet_pton(AF_INET, settings->ip, &sockAddr.sin_addr.s_addr)) fprintf(stderr,"ERROR: wrong IP address\n"); bind(master, (struct sockaddr *)(&sockAddr), sizeof(sockAddr)); setNonblock(master); listen(master, SOMAXCONN); int epoll = epoll_create1(0); struct epoll_event epollEvent; epollEvent.data.fd = master; epollEvent.events = EPOLLIN; epoll_ctl(epoll, EPOLL_CTL_ADD, master, &epollEvent); while(1) { struct epoll_event events[EPOLL_SIZE]; int numEvents = epoll_wait(epoll, events, EPOLL_SIZE, -1); for (i = 0; i < numEvents; ++i) { if (events[i].data.fd == master) { int slave = accept (master, 0, 0); struct epoll_event event; event.data.fd = slave; event.events = EPOLLIN; setNonblock (slave); epoll_ctl(epoll, EPOLL_CTL_ADD, slave, &event); } else { char query[BUF_LEN]; memset(query, 0, sizeof(query)); if (0 < recv(events[i].data.fd, query, BUF_LEN, MSG_NOSIGNAL)) { int start = 0; int queryLen = strlen(query); toLog("query src: ", query); while((query[start] != '/') && (start < queryLen)) start++; int finish = start; while((query[finish] != ' ') && (query[finish] != '?') && (finish < queryLen)) finish++; char queryPath[BUF_LEN]; memset(queryPath, 0, sizeof(queryPath)); strcat(queryPath, settings->path); int pathLen = strlen(queryPath); strncpy(queryPath + pathLen, query+start, finish-start); queryPath[pathLen + finish-start] = '\0'; toLog("queryPath: ", queryPath); FILE *f = fopen(queryPath, "r"); struct stat statbuf; stat(queryPath, &statbuf); if((f != NULL) && !S_ISDIR(statbuf.st_mode)) { toLog("TRY to read:", queryPath); char *buf; size_t len; fseek(f, 0, SEEK_END); len = ftell(f); int respLen = strlen(Resp_200); buf = (char *) malloc(len + respLen + 1); memset(buf, 0, sizeof(len + respLen)); strcpy(buf, Resp_200); fseek(f, 0, SEEK_SET); fread(buf + respLen, 1, len, f); fclose(f); buf[len + respLen] = '\0'; toLog("buf send: ", buf); send(events[i].data.fd, buf, strlen(buf), MSG_NOSIGNAL); } else { toLog("WRONG: ", Resp_404); send(events[i].data.fd, Resp_404, strlen(Resp_404), MSG_NOSIGNAL); } shutdown(events[i].data.fd, SHUT_RDWR); close(events[i].data.fd); } else if (errno != EAGAIN) { shutdown(events[i].data.fd, SHUT_RDWR); close(events[i].data.fd); } } } } }
int main(int argc, char **argv) { char path[64] = "/home/box/final"; char ip[16] = "127.0.0.1"; int port = 12345; int opt; int server_socket, conn_socket; struct epoll_event events[MAX_EVENTS]; struct epoll_event event; struct sockaddr_in sock_addr; int epollfd, nfds, i, robin = 0; int pid; int on = 1; int sv[2][2]; pid = fork(); if(pid != 0) return 0; pid = fork(); if(pid != 0) return 0; while ((opt = getopt(argc, argv, "h:p:d:")) != -1) { switch (opt) { case 'h': //ip.assign( optarg) ; sprintf(ip,"%s", optarg); break; case 'p': port = atoi(optarg); break; case 'd': //path.assign(optarg); sprintf(path, "%s", optarg); break; default: /* '?' */ //std::cout << "Usage: " << argv[0] << " [-h host_ip] [-p host_port] [-d directory]" << std::endl; printf("Ussage: %s [-h host_ip] [-p host_port][-d directory]",argv[0]); return -1; } } for(i = 0; i < 1 ; i++){ if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv[i]) < 0) { // printf("socketpair error"); exit(1); } switch ((pid = fork())) { case 0: close(sv[i][0]); worker(sv[i][1], path); return 0; case -1: //printf("fork error"); exit(1); default: close(sv[i][1]); /// parent(sv[i][0]); break; } } server_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); setsockopt ( server_socket, SOL_SOCKET, SO_REUSEADDR, (const char *) &on, sizeof(on)); sock_addr.sin_family = AF_INET; sock_addr.sin_port = htons(port); sock_addr.sin_addr.s_addr = inet_addr(ip); //inet_pton(AF_INET, ip, &sock_addr); bind(server_socket, (struct sockaddr *) (&sock_addr), sizeof(sock_addr)); set_nonblock(server_socket); listen(server_socket, SOMAXCONN); epollfd = epoll_create1(0); if (epollfd == -1) { goto error; } event.data.fd = server_socket; event.events = EPOLLIN; if(epoll_ctl (epollfd, EPOLL_CTL_ADD, server_socket, &event) == -1) { goto error; } while (1) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if(nfds == -1){ goto error; } for (i = 0; i < nfds; ++ i) { if (events[i].data.fd == server_socket) { conn_socket = accept(server_socket, 0, 0); if (conn_socket == -1) { goto error; } set_nonblock(conn_socket); event.data.fd = conn_socket; event.events = EPOLLIN | EPOLLET; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_socket, & event) == -1){ goto error; } } else { epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); if(robin ) robin = 0; else robin = 1; sock_fd_write(sv[robin][0], "1", 1, events[i].data.fd); } } } error: shutdown(server_socket, SHUT_RDWR); close(server_socket); return 0; }
* would be a pain to fix. */ STRV_FOREACH(address, arg_listen) { log_info("Opening address %s", *address); fd = make_socket_fd(*address, SOCK_STREAM | (arg_accept*SOCK_CLOEXEC)); if (fd < 0) { log_error("Failed to open '%s': %s", *address, strerror(-fd)); return fd; } count ++; } *epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (*epoll_fd < 0) { log_error("Failed to create epoll object: %m"); return -errno; } for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + count; fd++) { int r = add_epoll(*epoll_fd, fd); if (r < 0) return r; } return count; } static int launch(char* name, char **argv, char **env, int fds) {
int main(void) { memset(clients, 0, sizeof(Client) * MAXCLIENTS); signal(SIGCHLD, SIG_IGN); //signal(SIGPIPE, ) // FIXME struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // use my IP. "| AI_ADDRCONFIG" hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version hints.ai_family = AF_INET6; // IPv4 addresses will be like ::ffff:127.0.0.1 struct addrinfo *servinfo; getaddrinfo(NULL, PORT, &hints, &servinfo); #if DEBUG for(struct addrinfo *p = servinfo; p != NULL; p = p->ai_next) { char ipstr[INET6_ADDRSTRLEN]; inet_ntop(p->ai_family, get_in_addr(p->ai_addr), ipstr, sizeof(ipstr)); // convert the IP to a string printf(" %s\n", ipstr); } #endif struct addrinfo *servinfo2 = servinfo; //servinfo->ai_next; char ipstr[INET6_ADDRSTRLEN]; inet_ntop(servinfo2->ai_family, get_in_addr(servinfo2->ai_addr), ipstr, sizeof(ipstr)); printf("Waiting for connections on [%s]:%s\n", ipstr, PORT); int sockfd = socket(servinfo2->ai_family, servinfo2->ai_socktype, servinfo2->ai_protocol); #if 1 int yes_1 = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes_1, sizeof(yes_1)); #endif bind(sockfd, servinfo2->ai_addr, servinfo2->ai_addrlen); freeaddrinfo(servinfo); // all done with this structure setnonblocking(sockfd); listen(sockfd, 10); int efd = epoll_create1(0); struct epoll_event event; event.events = EPOLLIN; event.data.fd = sockfd; epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &event); struct epoll_event events[MAXEVENTS]; for(;;) { int nfd = epoll_wait(efd, events, MAXEVENTS, -1); for(int n = 0; n < nfd; ++n) { if(events[n].data.fd == sockfd) // listener { int idx = new_client(); struct sockaddr_storage their_addr; // connector's address information socklen_t addr_size = sizeof(their_addr); clients[idx].socket = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); setnonblocking(clients[idx].socket); // maybe try accept4(2) char ipstr[INET6_ADDRSTRLEN]; inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), ipstr, sizeof(ipstr)); printf("Got a connection from %s [%d]\n", ipstr, clients[idx].socket); const char hello_msg[] = "<rembash2>\n"; send(clients[idx].socket, hello_msg, sizeof(hello_msg) - 1, 0); struct itimerspec new_value; struct timespec now; clock_gettime(CLOCK_REALTIME, &now); new_value.it_value.tv_sec = now.tv_sec + 10; new_value.it_value.tv_nsec = now.tv_nsec; new_value.it_interval.tv_sec = 0; new_value.it_interval.tv_nsec = 0; clients[idx].timer = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC); timerfd_settime(clients[idx].timer, TFD_TIMER_ABSTIME, &new_value, NULL); EventData ed; ed.fd = clients[idx].socket; ed.idx = idx; EventUnion eu; eu.d = ed; event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; event.data.u64 = eu.u64; epoll_ctl(efd, EPOLL_CTL_ADD, ed.fd, &event); ed.fd = clients[idx].timer; eu.d = ed; event.events = EPOLLIN | EPOLLET; event.data.u64 = eu.u64; epoll_ctl(efd, EPOLL_CTL_ADD, ed.fd, &event); } else // client socket or pty or timer { char buf[BUFFERSIZE]; EventUnion eu; eu.u64 = events[n].data.u64; if(!clients[eu.d.idx].isvalid) { printf("Something bad happend on file [%d] for client [%d]\n", eu.d.fd, eu.d.idx); continue; } if (eu.d.fd == clients[eu.d.idx].timer) { printf("Time out for [%d]\n", eu.d.idx); if(clients[eu.d.idx].state == 0) { const char timer_msg[] = "TIMEOUT !\n"; send(clients[eu.d.idx].socket, timer_msg, sizeof(timer_msg) - 1, 0); printf("Client [%d] disconnected.\n", eu.d.idx); close(clients[eu.d.idx].socket); clients[eu.d.idx].isvalid = 0; } continue; } if(clients[eu.d.idx].state == 0) { // assert(eu.d.fd == clients[eu.d.idx].socket) int nbytes = recv(eu.d.fd, buf, 255, 0); // it's not 100% guaranteed to work! must use readline. if(nbytes < 1) { printf("Client [%d] disconnected.\n", eu.d.idx); close(eu.d.fd); clients[eu.d.idx].isvalid = 0; continue; } buf[nbytes - 1] = '\0'; printf("Received %s from [%d]\n", buf, eu.d.fd); if(strcmp(buf, SECRET) != 0) { const char secret_msg[] = "WRONG SECRET KEY !\n"; send(eu.d.fd, secret_msg, sizeof(secret_msg) - 1, 0); printf("Shared key check failed for [%d]\n", eu.d.idx); printf("Client [%d] disconnected.\n", eu.d.idx); close(eu.d.fd); clients[eu.d.idx].isvalid = 0; continue; } const char ok_msg[] = "<ok>\n"; send(eu.d.fd, ok_msg, sizeof(ok_msg) - 1, 0); clients[eu.d.idx].state = 1; clients[eu.d.idx].pid = forkpty(&clients[eu.d.idx].pty, NULL, NULL, NULL); if(clients[eu.d.idx].pid == 0) // child { close(sockfd); // child doesn't need the listener close(efd); // child doesn't need epoll setsid(); execl("/bin/bash", "bash", NULL); _exit(0); return 0; } else { EventData ed; ed.fd = clients[eu.d.idx].pty; ed.idx = eu.d.idx; EventUnion eu; eu.d = ed; event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLET; event.data.u64 = eu.u64; epoll_ctl(efd, EPOLL_CTL_ADD, ed.fd, &event); const char ready_msg[] = "<ready>\n"; send(clients[eu.d.idx].socket, ready_msg, sizeof(ready_msg) - 1, 0); } } // if(client->state == 0) else // if(client->state == 1) { // FIXME: EPOLLHUP or EPOLLRDHUP ?!! if((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP)) { printf("Client [%d] disconnected.\n", eu.d.idx); close(clients[eu.d.idx].socket); close(clients[eu.d.idx].pty); kill(clients[eu.d.idx].pid, SIGTERM); clients[eu.d.idx].isvalid = 0; continue; } else if(events[i].events & EPOLLIN) { int bytes_available = 0; ioctl(eu.d.fd, FIONREAD, &bytes_available); exchange_data(eu.d.fd, eu.d.idx); } else if(events[i].events & EPOLLOUT) { exchange_data(eu.d.fd == clients[eu.d.idx].socket ? clients[eu.d.idx].pty : clients[eu.d.idx].socket, eu.d.idx); } else { printf("Client [%d] ???.\n", eu.d.idx); } } } // if(events[n].data.fd == sockfd) } // for(int n = 0; n < nfd; ++n) } // for(;;) return 0; }
int main(int argc, char* const argv[]) { memset(&config, 0, sizeof(config)); const char *pidfile = "/var/run/6relayd.pid"; bool daemonize = false; int verbosity = 0; int c; while ((c = getopt(argc, argv, "ASR:D:Nsucn::l:a:rt:m:oi:p:dvh")) != -1) { switch (c) { case 'A': config.enable_router_discovery_relay = true; config.enable_dhcpv6_relay = true; config.enable_ndp_relay = true; config.send_router_solicitation = true; config.enable_route_learning = true; break; case 'S': config.enable_router_discovery_relay = true; config.enable_router_discovery_server = true; config.enable_dhcpv6_relay = true; config.enable_dhcpv6_server = true; break; case 'R': config.enable_router_discovery_relay = true; if (!strcmp(optarg, "server")) config.enable_router_discovery_server = true; else if (strcmp(optarg, "relay")) return print_usage(argv[0]); break; case 'D': config.enable_dhcpv6_relay = true; if (!strcmp(optarg, "server")) config.enable_dhcpv6_server = true; else if (strcmp(optarg, "relay")) return print_usage(argv[0]); break; case 'N': config.enable_ndp_relay = true; break; case 's': config.send_router_solicitation = true; break; case 'u': config.always_announce_default_router = true; break; case 'c': config.deprecate_ula_if_public_avail = true; break; case 'n': config.always_rewrite_dns = true; if (optarg) inet_pton(AF_INET6, optarg, &config.dnsaddr); break; case 'l': config.dhcpv6_statefile = strtok(optarg, ","); if (config.dhcpv6_statefile) config.dhcpv6_cb = strtok(NULL, ","); break; case 'a': config.dhcpv6_lease = realloc(config.dhcpv6_lease, sizeof(char*) * ++config.dhcpv6_lease_len); config.dhcpv6_lease[config.dhcpv6_lease_len - 1] = optarg; break; case 'r': config.enable_route_learning = true; break; case 't': config.static_ndp = realloc(config.static_ndp, sizeof(char*) * ++config.static_ndp_len); config.static_ndp[config.static_ndp_len - 1] = optarg; break; case 'm': config.ra_managed_mode = atoi(optarg); break; case 'o': config.ra_not_onlink = true; break; case 'i': if (!strcmp(optarg, "low")) config.ra_preference = -1; else if (!strcmp(optarg, "high")) config.ra_preference = 1; break; case 'p': pidfile = optarg; break; case 'd': daemonize = true; break; case 'v': verbosity++; break; default: return print_usage(argv[0]); } } openlog("6relayd", LOG_PERROR | LOG_PID, LOG_DAEMON); if (verbosity == 0) setlogmask(LOG_UPTO(LOG_WARNING)); else if (verbosity == 1) setlogmask(LOG_UPTO(LOG_INFO)); if (argc - optind < 1) return print_usage(argv[0]); if (getuid() != 0) { syslog(LOG_ERR, "Must be run as root. stopped."); return 2; } #if defined(__NR_epoll_create1) && defined(EPOLL_CLOEXEC) epoll = epoll_create1(EPOLL_CLOEXEC); #else epoll = epoll_create(32); epoll = fflags(epoll, O_CLOEXEC); #endif if (epoll < 0) { syslog(LOG_ERR, "Unable to open epoll: %s", strerror(errno)); return 2; } #ifdef SOCK_CLOEXEC ioctl_sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); #else ioctl_sock = socket(AF_INET6, SOCK_DGRAM, 0); ioctl_sock = fflags(ioctl_sock, O_CLOEXEC); #endif if ((rtnl_socket = relayd_open_rtnl_socket()) < 0) { syslog(LOG_ERR, "Unable to open socket: %s", strerror(errno)); return 2; } if (open_interface(&config.master, argv[optind++], false)) return 3; config.slavecount = argc - optind; config.slaves = calloc(config.slavecount, sizeof(*config.slaves)); for (size_t i = 0; i < config.slavecount; ++i) { const char *name = argv[optind + i]; bool external = (name[0] == '~'); if (external) ++name; if (open_interface(&config.slaves[i], name, external)) return 3; } if ((urandom_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) < 0) return 4; struct sigaction sa = {.sa_handler = SIG_IGN}; sigaction(SIGUSR1, &sa, NULL); if (init_router_discovery_relay(&config)) return 4; if (init_dhcpv6_relay(&config)) return 4; if (init_ndp_proxy(&config)) return 4; if (epoll_registered == 0) { syslog(LOG_WARNING, "No relays enabled or no slave " "interfaces specified. stopped."); return 5; } if (daemonize) { openlog("6relayd", LOG_PID, LOG_DAEMON); // Disable LOG_PERROR if (daemon(0, 0)) { syslog(LOG_ERR, "Failed to daemonize: %s", strerror(errno)); return 6; } FILE *fp = fopen(pidfile, "w"); if (fp) { fprintf(fp, "%i\n", getpid()); fclose(fp); } } signal(SIGTERM, set_stop); signal(SIGHUP, set_stop); signal(SIGINT, set_stop); signal(SIGCHLD, wait_child); // Main loop while (!do_stop) { struct epoll_event ev[16]; int len = epoll_wait(epoll, ev, 16, -1); for (int i = 0; i < len; ++i) { struct relayd_event *event = ev[i].data.ptr; if (event->handle_event) event->handle_event(event); else if (event->handle_dgram) relayd_receive_packets(event); } } syslog(LOG_WARNING, "Termination requested by signal."); deinit_ndp_proxy(); deinit_router_discovery_relay(); free(config.slaves); close(urandom_fd); return 0; }
int main(int argc, char *argv[]) { int sfd, s; int efd; struct epoll_event event; struct epoll_event *events; if(argc != 2) { fprintf(stderr, "Usage: %s [port]\n", argv[0]); exit(EXIT_FAILURE); } sfd = create_and_bind(argv[1]); if(sfd == -1) abort(); s = make_socket_non_blocking(sfd); if(s == -1) abort(); s = listen(sfd, SOMAXCONN); if(s == -1) { perror("listen"); abort(); } efd = epoll_create1(0); if(efd == -1) { perror("epoll_create1"); abort(); } event.data.fd = sfd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event); if(s == -1) { perror("epoll_ctl"); abort(); } events = calloc(MAXEVENTS, sizeof(event)); /* The event loop */ while(1) { int n, i; n = epoll_wait(efd, events, MAXEVENTS, -1); for(i = 0; i < n; i++) { if((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /*An error occurred, notified but no ready*/ fprintf(stderr, "epoll error\n"); close(events[i].data.fd); continue; } else if(sfd == events[i].data.fd) { /*listener port is notified, which means incoming connection*/ while(1) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof(in_addr); infd = accept(sfd, &in_addr, &in_len); if(infd == -1) { if((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /*we have processed all incoming connections*/ break; } else { perror("accept"); break; } } s = getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if(s == 0) { printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", infd, hbuf, sbuf); } /*make the socket non-blocking and add it to monitor list*/ s = make_socket_non_blocking(infd); if(s == -1) abort(); event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event); if(s == -1) { perror("epoll_ctl"); abort(); } } continue; } else { /*read is ready*/ int done = 0; while(1) { ssize_t count; char buf[512]; count = read(events[i].data.fd, buf, sizeof(buf)); if(count == -1) { if(errno != EAGAIN) { perror("read"); done = 1; } break; } else if(count == 0) { /*End of file*/ done = 1; break; } /*Write the buffer to stdout*/ s = write(1, buf, count); if(s == -1) { perror("write"); abort(); } } if(done) { printf("closed connection on descriptor %d\n", events[i].data.fd); /*close connection*/ close(events[i].data.fd); } } } } free(events); close(sfd); return EXIT_SUCCESS; }
int main(int argc, char **argv) { struct timespec mtime = { 0 }; sigset_t mask, sigmask_orig; int c, fd; int ep_timeout = 0; int ignore_timer = 0; int new_events = 0; char *eventdir, *prog, **prog_args; struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "foreground", no_argument, 0, 'f' }, { "loglevel", required_argument, 0, 'L' }, { "logfile", required_argument, 0, 'l' }, { "pidfile", required_argument, 0, 'p' }, { "timeout", required_argument, 0, 't' }, { 0, 0, 0, 0 } }; while ((c = getopt_long(argc, argv, "hVfL:l:p:", long_options, NULL)) != -1) { switch (c) { case 't': timeout = atoi(optarg); if (!timeout) timeout = DEFAULT_TIMEOUT; break; case 'p': pidfile = optarg; break; case 'l': logfile = optarg; break; case 'L': log_priority = logging_level(optarg); break; case 'f': daemonize = 0; break; case 'V': printf("%s %s\n", PROGRAM_NAME, VERSION); return EXIT_SUCCESS; default: case 'h': printf("Usage: %s [options] DIRECTORY PROGRAM [ARGS...]\n" "\nThe utility monitors the DIRECTORY and when\n" "new files appear run the PROGRAM.\n\n" "Options:\n" " -p, --pidfile=FILE pid file location;\n" " -l, --logfile=FILE log file;\n" " -L, --loglevel=LVL logging level;\n" " -t, --timeout=SEC number of seconds that need to wait" " for files before the PROGRAM launch;\n" " -f, --foreground stay in the foreground;\n" " -V, --version print program version and exit;\n" " -h, --help show this text and exit.\n" "\n", PROGRAM_NAME); return EXIT_SUCCESS; } } if (optind >= argc) error(EXIT_FAILURE, 0, "You must specify the directory"); eventdir = argv[optind++]; if (optind >= argc) error(EXIT_FAILURE, 0, "You must specify the program"); prog = canonicalize_file_name(argv[optind]); if (!prog) error(EXIT_FAILURE, errno, "Bad program"); argv[optind] = strrchr(prog, '/'); if (!argv[optind]) argv[optind] = prog; prog_args = argv + optind; if (!log_priority) log_priority = logging_level("info"); if (pidfile && check_pid(pidfile)) error(EXIT_FAILURE, 0, "%s: already running", PROGRAM_NAME); if (chdir("/") < 0) error(EXIT_FAILURE, errno, "%s: chdir(/)", PROGRAM_NAME); close(STDIN_FILENO); if ((fd = open("/dev/null", O_RDONLY)) < 0) error(EXIT_FAILURE, errno, "%s: open(/dev/null)", PROGRAM_NAME); if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO); close(fd); } if (daemonize && daemon(0, 1) < 0) error(EXIT_FAILURE, errno, "%s: daemon", PROGRAM_NAME); logging_init(); info("starting version %s", VERSION); if (pidfile && write_pid(pidfile) == 0) return EXIT_FAILURE; sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); sigdelset(&mask, SIGABRT); sigdelset(&mask, SIGSEGV); if ((fd_ep = epoll_create1(EPOLL_CLOEXEC)) < 0) fatal("epoll_create1: %m"); if ((fd_signal = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC)) < 0) fatal("signalfd: %m"); epollin_add(fd_ep, fd_signal); if ((fd_eventdir = inotify_init1(IN_NONBLOCK | IN_CLOEXEC)) < 0) fatal("inotify_init1: %m"); if (inotify_add_watch(fd_eventdir, eventdir, IN_ONLYDIR | IN_DONT_FOLLOW | IN_MOVED_TO | IN_CLOSE_WRITE) < 0) fatal("inotify_add_watch: %m"); epollin_add(fd_ep, fd_eventdir); ignore_timer = is_dir_not_empty(eventdir); if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); last.tv_sec = now.tv_sec; while (!do_exit) { struct epoll_event ev[42]; int i, fdcount; ssize_t size; if ((fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), ep_timeout)) < 0) continue; if (!ep_timeout) ep_timeout = timeout * 1000; for (i = 0; i < fdcount; i++) { if (!(ev[i].events & EPOLLIN)) { continue; } else if (ev[i].data.fd == fd_signal) { struct signalfd_siginfo fdsi; size = TEMP_FAILURE_RETRY(read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo))); if (size != sizeof(struct signalfd_siginfo)) { err("unable to read signal info"); continue; } handle_signal(fdsi.ssi_signo); } else if (ev[i].data.fd == fd_eventdir) { read_inotify_events(fd_eventdir); new_events += 1; } } if (new_events) { struct stat sb; new_events = 0; if (lstat(eventdir, &sb) < 0) fatal("lstat: %s: %m", eventdir); if (mtime.tv_sec != sb.st_mtim.tv_sec || mtime.tv_nsec != sb.st_mtim.tv_nsec) { if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); last.tv_sec = now.tv_sec; } mtime.tv_sec = sb.st_mtim.tv_sec; mtime.tv_nsec = sb.st_mtim.tv_nsec; } if (worker_pid) continue; if (!ignore_timer) { if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); if (now.tv_sec < last.tv_sec || (now.tv_sec - last.tv_sec) < timeout) continue; } ignore_timer = 0; if ((worker_pid = spawn_worker(prog, prog_args)) < 0) fatal("spawn_worker: %m"); dbg("Run worker %d", worker_pid); } epollin_remove(fd_ep, fd_signal); epollin_remove(fd_ep, fd_eventdir); free(prog); if (pidfile) remove_pid(pidfile); logging_close(); return EXIT_SUCCESS; }
void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; int ret, n, i; size_t len; int efd; struct epoll_event event; struct epoll_event events[2]; // Same with epoll_create(), except the argument size is ignored. if ((efd = epoll_create1(0)) == -1) { perror ("epoll_create"); exit(EXIT_FAILURE); } if(make_socket_non_blocking (fileno(stdin)) == -1) exit(EXIT_FAILURE); if(make_socket_non_blocking (sockfd) == -1) exit(EXIT_FAILURE); event.data.fd = fileno(stdin); // stdin event.events = EPOLLIN;// | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, fileno(stdin), &event) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } event.data.fd = sockfd; // stdin event.events = EPOLLIN;// | EPOLLET; if (epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &event) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } for (;;) { n = epoll_wait (efd, events, 2, -1); // only stdin+sockfd for (i = 0; i < n; i++) { 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 (events[i].data.fd); exit(EXIT_FAILURE); } if (sockfd == events[i].data.fd) { // socket is readable. ret = readline(sockfd, recvline, MAXLINE); if (ret == 0) { fprintf(stderr, "str_cli: server terminated prematurely\n"); exit(EXIT_FAILURE); } else if (ret < 0) { fprintf(stderr, "str_cli error\n"); exit(EXIT_FAILURE); } fputs("socket: ", stdout); if (fputs(recvline, stdout) == EOF) { fprintf(stderr, "fputs error\n"); exit(EXIT_FAILURE); } } if (fileno(stdin) == events[i].data.fd) { // input is readable. if (fgets(sendline, MAXLINE, fp) == NULL) { if (ferror(fp)) { // stream errors. fprintf(stderr, "fgets error\n"); exit(EXIT_FAILURE); } else { // end of file. return; } } fputs("stdin : ", stdout); if (fputs(sendline, stdout) == EOF) { fprintf(stderr, "fputs error\n"); exit(EXIT_FAILURE); } len = strlen(sendline); if (writen(sockfd, sendline, len) != len) { fprintf(stderr, "writen error\n"); exit(EXIT_FAILURE); } } } } }
DEFiRet; free(*ppEvtLst); *ppEvtLst = NULL; RETiRet; } /* -END--------------------------- helpers for event list ------------------------------------ */ /* Standard-Constructor */ BEGINobjConstruct(nsdpoll_ptcp) /* be sure to specify the object type also in END macro! */ #if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1) DBGPRINTF("nsdpoll_ptcp uses epoll_create1()\n"); pThis->efd = epoll_create1(EPOLL_CLOEXEC); if(pThis->efd < 0 && errno == ENOSYS) #endif { DBGPRINTF("nsdpoll_ptcp uses epoll_create()\n"); pThis->efd = epoll_create(100); /* size is ignored in newer kernels, but 100 is not bad... */ } if(pThis->efd < 0) { DBGPRINTF("epoll_create1() could not create fd\n"); ABORT_FINALIZE(RS_RET_IO_ERROR); } pthread_mutex_init(&pThis->mutEvtLst, NULL); finalize_it: ENDobjConstruct(nsdpoll_ptcp)
int main (int argc, char *argv[]) { /* initialization code */ cvect_t *dyn_vect = ccache_init(); assert(dyn_vect); int sfd, s; int efd; struct epoll_event event; struct epoll_event *events; char buf[BUFFER_SIZE]; char localbuf[BUFFER_SIZE]; if (argc != 2) { fprintf (stderr, "Usage: %s [port]\n", argv[0]); exit (EXIT_FAILURE); } sfd = create_and_bind (argv[1]); if (sfd == -1) abort (); s = make_socket_non_blocking (sfd); if (s == -1) abort (); s = listen (sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort (); } efd = epoll_create1 (0); if (efd == -1) { perror ("epoll_create"); abort (); } event.data.fd = sfd; 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 = calloc (MAXEVENTS, sizeof event); /* The event loop */ while (1) { int n, i; n = epoll_wait (efd, events, MAXEVENTS, -1); for (i = 0; i < n; i++) { 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 (events[i].data.fd); continue; } else if (sfd == events[i].data.fd) { /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept (sfd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror ("accept"); break; } } s = getnameinfo (&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV); 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) abort (); event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror ("epoll_ctl"); abort (); } } continue; } else { /* We have data on the fd waiting to be read. Read and process 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) { ssize_t count; bzero(buf,BUFFER_SIZE); //zero out the buffer every time count = read (events[i].data.fd, buf, sizeof buf); 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; } break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } /* Process the buffered request and write the results to the output */ buf[strlen(buf)-1] = '\0'; //remove trailing newline /* Make sure this request is complete - can do special handling based on creq_type then */ strcpy(localbuf, buf); ccmd_t type = get_creq_type(localbuf); strcpy(localbuf, buf); if(type == CSET) { creq_t *creq = (creq_t *) malloc(sizeof(creq_t)); creq = ccache_req_parse(buf); //now process that actual buffer /* Write Header and Footer to socket */ printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header)); if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error; if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){ if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error; } } /* CGET */ else if(type == CGET){ /* split multiple requests into single requests and process them */ char * pch; int counter = 0; pch = strtok(localbuf, " "); while(pch != NULL){ if(counter != 0){ /* formulate this new request and then skip the parsing step */ creq_t *creq = (creq_t *) malloc(sizeof(creq_t)); strcpy(creq->key, pch); creq->type = CGET; creq = ccache_get(creq); /* Write Header and Footer to socket */ //printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header)); if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error; if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){ if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error; } } pch = strtok(NULL, " "); counter++; } /* now that we're done transmitting all the CGET reqs - transmit END */ if((s = write (events[i].data.fd, "END\r\n", strlen("END\r\n"))) == -1) goto write_error; } else if(type == CDELETE || type == INVALID){ creq_t *creq = (creq_t *) malloc(sizeof(creq_t)); creq = ccache_req_parse(buf); //now process that actual buffer /* Write Header and Footer to socket */ printf("before header: %s, strlen: %i\n", buf, strlen(creq->resp.header)); if((s = write (events[i].data.fd, creq->resp.header, strlen(creq->resp.header))) == -1) goto write_error; if(creq->resp.errcode == RERROR || creq->resp.errcode == 0){ if((s = write (events[i].data.fd, creq->resp.footer, strlen(creq->resp.footer))) == -1) goto write_error; } /* cleanup from delete */ free(creq); } else{ printf("error! exiting\n"); exit(1); } } if (done) { printf ("Closed connection on descriptor %d\n", events[i].data.fd); /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ close (events[i].data.fd); } } } } free (events); close (sfd); return EXIT_SUCCESS; write_error: if (s == -1) { perror ("write"); abort (); } return -1; }
int stx_queue_create() { return epoll_create1(0); }
/** * Open a target connection * * @see glip_open() */ int gb_tcp_open(struct glip_ctx *ctx, unsigned int num_channels) { struct glip_backend_ctx *bctx = ctx->backend_ctx; int rv; const char* hostname; unsigned int port_data; unsigned int port_ctrl; if (bctx->data_sfd >= 0 || bctx->ctrl_sfd >= 0) { err(ctx, "Already connected, disconnect first!\n"); return -1; } /* get hostname and port from options */ if (glip_option_get_char(ctx, "hostname", &hostname) != 0) { dbg(ctx, "No 'hostname' option set, using default %s.\n", DEFAULT_HOSTNAME); hostname = DEFAULT_HOSTNAME; } if (glip_option_get_uint32(ctx, "port", &port_data) != 0) { dbg(ctx, "No 'port' option set, using default %u\n", DEFAULT_PORT_DATA); port_data = DEFAULT_PORT_DATA; } port_ctrl = port_data + 1; /* connect to data channel */ bctx->data_sfd = 0; rv = gl_util_connect_to_host(ctx, hostname, port_data, &bctx->data_sfd); if (rv != 0) { return -1; } rv = gl_util_fd_nonblock(ctx, bctx->data_sfd); if (rv != 0) { return -1; } /* setup polling (for blocking I/O on data channel) */ bctx->data_efd = epoll_create1(0); if (bctx->data_efd == -1) { err(ctx, "Unable to create epoll fd for the data channel: %s\n", strerror(errno)); return -1; } bctx->data_ev.data.fd = bctx->data_sfd; struct epoll_event ev; ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLPRI | EPOLLET; rv = epoll_ctl(bctx->data_efd, EPOLL_CTL_ADD, bctx->data_sfd, &ev); if (rv != 0) { return -1; } /* connect to control channel */ bctx->ctrl_sfd = 0; rv = gl_util_connect_to_host(ctx, hostname, port_ctrl, &bctx->ctrl_sfd); if (rv != 0) { return -1; } rv = gl_util_fd_nonblock(ctx, bctx->ctrl_sfd); if (rv != 0) { return -1; } return 0; }
/* // Name: main // In: argv, the arguments sent to the program. // argc, the number of arguments sent to the program. */ int main (int argc, char **argv) { char port[6]; char ssl_port[6]; if(!arguments(argv, argc, port, ssl_port)) { printf("Usage: chat_server [port] [ssl port]\n"); return 0; } char topic[MAXTOKENSIZE]; memset(topic, '\0', MAXTOKENSIZE); // Set the signal handler. signal(SIGINT, signal_handler); server_socket = -1; ssl_socket = -1; server_socket_fd; int epoll_fd; struct epoll_event event, ssl_event; BIO *sbio; SSL *ssl; // Initialize ssl context. ctx=init_ctx(); memset(&event, 0, sizeof event); memset(&ssl_event, 0, sizeof event); printf("Trying to create socket.\n"); server_socket_fd = create_socket("telnet", port); ssl_socket_fd = create_socket("telnet", ssl_port); printf("Created socket.\n"); // Check if sockets couldn't be created. if(server_socket_fd<0 || ssl_socket_fd<0) { fprintf(stderr, "Socket could not be created!\n"); return -1; } // Set the socket to be non-blocking. server_socket = unblock_socket(server_socket_fd); ssl_socket = unblock_socket(ssl_socket_fd); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not make socket non blocking.\n"); return -1; } printf("Listening...\n"); // Listen for incoming connections. server_socket = listen(server_socket_fd, NUMBER_PENDING_CONNECTIONS); ssl_socket = listen(ssl_socket_fd, NUMBER_PENDING_CONNECTIONS); if(server_socket < 0 || ssl_socket<0) { fprintf(stderr, "Could not listen to incoming connections.\n"); return -1; } epoll_fd = epoll_create1(0); event.data.fd = server_socket_fd; // Run as edge-triggered, meaning that epoll_wait will return only on // new events. event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the unsecure socket. server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_socket_fd, &event); ssl_event.data.fd=ssl_socket_fd; ssl_event.events = EPOLLIN | EPOLLET; // Create epoll control interface for the secure socket. ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ssl_socket_fd, &ssl_event); if(server_socket<0 || ssl_socket<0) { fprintf(stderr, "Could not create control interface for polling.\n"); return -1; } events = calloc(MAXEVENTS, sizeof event); // Create hash map for storing connected clients. clients = hash_empty(MAXCLIENTS); struct sockaddr client_addr; socklen_t client_len; int insocket_fd; int client_socket; char host[MAXHOST_LEN], serv[MAXSERV_LEN]; client_len = sizeof client_addr; // Main loop listening from events generated by epoll. while(1) { int n,i; // Wait for new events. n = epoll_wait(epoll_fd, events, MAXEVENTS, -1); for(i=0;i<n;i++) { if((events[i].events & EPOLLERR) || events[i].events & EPOLLHUP || (!(events[i].events & EPOLLIN))) { fprintf(stderr, "An error occured at an event.\n"); clientconn_t *c; // If the an error-event occured at a connected client. if((c = hash_get(events[i].data.fd, clients))!=NULL) { client_close(c); hash_remove(c, clients); } close(events[i].data.fd); continue; } // If an a connection is made on the unsecure socket. else if(server_socket_fd == events[i].data.fd) { while(1) { // Accept connection. insocket_fd = accept(server_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept " "input connection"); break; } else { // If the whole handshake could not be made, // keep trying to accept. break; } } // The address information. server_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(server_socket==0) { printf("Connection accepted!\n"); } // Make client socket non-blocking. server_socket = unblock_socket(insocket_fd); if(server_socket <0) { fprintf(stderr, "Could not make client socket " "non-blocking\n"); return -1; } // Create an epoll interface for the client socket. event.data.fd = insocket_fd; event.events = EPOLLIN|EPOLLET; server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &event); if(server_socket<0) { fprintf(stderr, "Could not create epoll " "interface for client\n"); return -1; } printf("Added client(%d)!\n", insocket_fd); // Store client in the hash map. c = create_client(insocket_fd, &client_addr); hash_insert(c, clients); } continue; } // If a connection is made on the secure socket. else if(ssl_socket_fd == events[i].data.fd) { printf("Someone connected through ssl!\n"); while(1) { // Accept in the same way as the unsecure socket. insocket_fd = accept(ssl_socket_fd, &client_addr, &client_len); if(insocket_fd<0) { if(!(errno == EAGAIN || errno == EWOULDBLOCK)) { fprintf(stderr, "Could not accept input " "connection\n"); break; } else { break; } } ssl_socket = getnameinfo(&client_addr, client_len, host, sizeof host, serv, sizeof serv, NI_NUMERICHOST|NI_NUMERICSERV); if(ssl_socket==0) { printf("Connection accepted!\n"); } // Make socket non-blocking ssl_socket = unblock_socket(insocket_fd); if(ssl_socket<0){ fprintf(stderr, "Could not make secure client " "socket non-blocking.\n"); return -1; } // Create epoll interface for the secure client connection ssl_event.data.fd = insocket_fd; ssl_event.events = EPOLLIN; ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, insocket_fd, &ssl_event); if(ssl_socket<0) { fprintf(stderr, "Could not create " "epoll interface for client.\n"); return -1; } printf("Added client!(%d)\n", insocket_fd); c = create_client(insocket_fd, &client_addr); // Set up ssl. c->ssl_status=STATUS_HANDSHAKE; c->ssl = SSL_new(ctx); SSL_set_fd(c->ssl, insocket_fd); SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); hash_insert(c, clients); } continue; } // If an incoming message has caused an event. else { int done = 0; while (1) { ssize_t count; char buf[MAXBUFSIZE]; memset(buf, '\0', MAXBUFSIZE); clientconn_t *c = hash_get(events[i].data.fd, clients); // If the client is trying to make an ssl handshake. if(c->ssl_status==STATUS_HANDSHAKE) { int r=1; r=SSL_accept(c->ssl); if (r<0) { if(SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_READ && SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_WRITE ){ done=1; printf("Could not accept ssl " "connection\n"); break; } } else { // Handshake is done. c->ssl_status=STATUS_ACCEPTED; } } else { // Read data from client. int count = client_read(c, buf, sizeof buf); if(count<0) { if(errno!=EAGAIN) { fprintf(stderr, "Could not read" " from socket!\n"); done=1; } break; } if(buf[MAXBUFSIZE-1] != '\0') { write(events[i].data.fd, "* BAD Buffer will " "overflow\r\n", 28); break; } else if (count==0) { done=1; break; } if (handle_input(events[i].data.fd, buf, count, clients, topic)==CLIENTCLOSED) { done=1; break; } if(server_socket<0) { fprintf(stderr, "Could get input.\n"); return -1; } } } // Client connection is done, wants to disconnect. if(done) { printf("Closed connection!\n"); clientconn_t *closeclient = hash_get(events[i].data.fd, clients); if(closeclient != NULL) { hash_remove(closeclient, clients); client_close(closeclient); } close(events[i].data.fd); } } } } free(events); close(server_socket_fd); return 0; }