void ofxVideoRecorder::close() { if(!bIsInitialized) return; //set pipes to non_blocking so we dont get stuck at the final writes setNonblocking(audioPipeFd); setNonblocking(videoPipeFd); while(frames.size() > 0 && audioFrames.size() > 0) { // if there are frames in the queue or the thread is writing, signal them until the work is done. videoThread.signal(); audioThread.signal(); } //at this point all data that ffmpeg wants should have been consumed // one of the threads may still be trying to write a frame, // but once close() gets called they will exit the non_blocking write loop // and hopefully close successfully bIsInitialized = false; if (bRecordVideo) { videoThread.close(); } if (bRecordAudio) { audioThread.close(); } retirePipeNumber(pipeNumber); ffmpegThread.waitForThread(); // TODO: kill ffmpeg process if its taking too long to close for whatever reason. }
int EpollSocket::handle_accept_event(int &epollfd, epoll_event &event, EpollSocketWatcher &socket_handler) { int sockfd = event.data.fd; std::string client_ip; int conn_sock = accept_socket(sockfd, client_ip); if (conn_sock == -1) { return -1; } setNonblocking(conn_sock); LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock); EpollContext *epoll_context = new EpollContext(); epoll_context->fd = conn_sock; epoll_context->client_ip = client_ip; socket_handler.on_accept(*epoll_context); struct epoll_event conn_sock_ev; conn_sock_ev.events = EPOLLIN | EPOLLET; conn_sock_ev.data.ptr = epoll_context; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } return 0; }
int CEpollSocket::handle_accept_event(int epollfd, epoll_event &event, CEpollSocketWatcher &socket_handler) { int sockfd = event.data.fd; std::string client_ip; int conn_sock = accept_socket(sockfd, client_ip); if (conn_sock == -1) { return -1; } setNonblocking(conn_sock); LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock); CEpollContext *epoll_context = new CEpollContext(); epoll_context->fd = conn_sock; epoll_context->client_ip = client_ip; socket_handler.on_accept(*epoll_context); struct epoll_event conn_sock_ev; conn_sock_ev.events = EPOLLIN; conn_sock_ev.data.ptr = epoll_context; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) { LOG_ERROR("epoll_ctl: conn_sock:%s", strerror(errno)); return -1; } return 0; }
/* Try to open a connection to LCDd if support is enabled ** If it succeeeds configure our screen ** If it fails, print a message, disable support and continue */ void init_lcd (void) { if (!use_lcdd_menu) return; use_lcdd_menu = false; lcd_fd = socket(AF_INET, SOCK_STREAM, 0); if (lcd_fd > 0) { lcd_addr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *)); lcd_addr->sin_family = AF_INET; if (inet_pton(AF_INET, "127.0.0.1", (void *)(&(lcd_addr->sin_addr.s_addr))) >0) { lcd_addr->sin_port = htons(13666); if (connect(lcd_fd, (struct sockaddr *)lcd_addr, sizeof(struct sockaddr)) >= 0) { int flag = 1; if (setsockopt(lcd_fd, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag) ) == 0) { use_lcdd_menu = true; send_lcd("hello\n",6); while(!read_lcd()); /* wait for display info */ send_lcd("client_set name {squeeze}\n",26); send_lcd("screen_add main\n",16); send_lcd("screen_set main name {main}\n",28); send_lcd("screen_set main heartbeat off\n",30); send_lcd("widget_add main one string\n",27); send_lcd("widget_add main two string\n",27); if ( lcdd_compat ) send_lcd("screen_set main -priority 256\n",30); else send_lcd("screen_set main -priority info\n",31); setNonblocking(lcd_fd); } } } } /* If connect failed */ if (!use_lcdd_menu) { use_lcdd_menu = true; close_lcd(); fprintf(stderr,"Connect to LCDd failed!\n"); } }
int bluetooth_open(const char *addr, uint8_t channel, struct gn_statemachine *state) { bdaddr_t bdaddr; struct sockaddr_rc raddr; int fd; if (str2ba((char *)addr, &bdaddr)) { fprintf(stderr, _("Invalid bluetooth address \"%s\"\n"), addr); return -1; } if ((fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) { perror(_("Can't create socket")); return -1; } memset(&raddr, 0, sizeof(raddr)); raddr.rc_family = AF_BLUETOOTH; bacpy(&raddr.rc_bdaddr, &bdaddr); dprintf("Channel: %d\n", channel); if (channel < 1) { if (!strcmp(state->config.model, "gnapplet") || !strcmp(state->config.model, "symbian")) channel = get_serial_channel(&bdaddr, 1); else channel = get_serial_channel(&bdaddr, 0); } dprintf("Channel: %d\n", channel); /* If none channel found, fail. */ if (channel < 1) { fprintf(stderr, _("Cannot find any appropriate rfcomm channel and none was specified in the config.\n")); close(fd); return -1; } dprintf("Using channel: %d\n", channel); raddr.rc_channel = channel; if (connect(fd, (struct sockaddr *)&raddr, sizeof(raddr)) < 0) { perror(_("Can't connect")); close(fd); return -1; } /* Ignore errors. If the socket was not set in the async way, * we can live with that. */ setNonblocking(fd); return fd; }
/* Try to open a connection to lircd if suppor is enabled ** if it fails, disable support, print a message and continue */ void init_lirc(void) { if (using_lirc) { using_lirc = false; if ((lirc_fd = lirc_init("squeezeslave",1)) > 0) { if (lirc_readconfig(lircrc, &lircconfig, NULL)==0) { using_lirc = true; setNonblocking(lcd_fd); } else { using_lirc = true; close_lirc(); } } if (!using_lirc ) fprintf(stderr, "Failed to init LIRC\n"); } }
static int serverSocket(int af) { int fd, rc; if(af == 4) { fd = socket(PF_INET, SOCK_STREAM, 0); } else if(af == 6) { #ifdef HAVE_IPv6 fd = socket(PF_INET6, SOCK_STREAM, 0); #else fd = -1; errno = EAFNOSUPPORT; #endif } else { abort(); } if(fd >= 0) { if(proxyOutgoingAddress != NULL) { serverSocket_outgoingIP(fd); } rc = setNonblocking(fd, 1); if(rc < 0) { int errno_save = errno; CLOSE(fd); errno = errno_save; return -1; } #ifdef HAVE_IPV6_PREFER_TEMPADDR if (af == 6 && useTemporarySourceAddress != 1) { int value; value = (useTemporarySourceAddress == 2) ? 1 : 0; rc = setsockopt(fd, IPPROTO_IPV6, IPV6_PREFER_TEMPADDR, &value, sizeof(value)); if (rc < 0) { /* no error, warning only */ do_log_error(L_WARN, errno, "Couldn't set IPV6CTL_USETEMPADDR"); } } #endif } return fd; }
void think() { fd_set readSet; struct timeval tv={1,0}; unsigned int i; vector<int> toRemove; int maxfd = server; FD_ZERO(&readSet); FD_SET(server,&readSet); set<int>::iterator it; for (it=sockets.begin();it!=sockets.end();it++) { FD_SET(maxfd = *it, &readSet); } int sel = select(maxfd+1, &readSet,0,0,&tv); if (sel <= 0) { struct timespec ts={0,100000000}; nanosleep(&ts,0); } if (FD_ISSET(server,&readSet)) { int s = accept(server, 0, 0); if (s != -1 && sockets.size() < FD_SETSIZE) { setNonblocking(s); sockets.insert(s); } } for (it=sockets.begin();it!=sockets.end();it++) { if (FD_ISSET(*it, &readSet)) { int ret = recv(*it, buffer, BUFSIZE, 0); if (ret <= 0) toRemove.push_back(*it); } } for (i=0;i<toRemove.size(); i++) { shutdown(toRemove[i],1); close(toRemove[i]); sockets.erase(toRemove[i]); } }
static s32 helper_setup_socket( u16 port) { s32 sock; int ret; //u32 clientlen; struct sockaddr_in server; struct sockaddr_in client; //clientlen = sizeof(client); sock = net_socket (AF_INET, SOCK_STREAM, IPPROTO_IP); if (sock == INVALID_SOCKET) { printf( "setup():INVALID_SOCKET\n"); return -1; } memset (&server, 0, sizeof (server)); memset (&client, 0, sizeof (client)); server.sin_family = AF_INET; server.sin_port = htons (port); server.sin_addr.s_addr = INADDR_ANY; ret = net_bind (sock, (struct sockaddr *) &server, sizeof (server)); if ( ret ) { printf( "net_bind():INVALID_SOCKET\n"); net_close( sock); return -1; } if ( (ret = net_listen( sock, 1)) ) { printf( "net_listen():INVALID_SOCKET\n"); net_close( sock); return -1; } #if 0 ret = setNonblocking(sock); printf( "setNonblocking(%d) returns=%d.\n", sock, ret); #endif return sock; }
int _accept(int fd) { int new_fd = -1; while (true) { struct sockaddr_in sock; socklen_t sockLen = sizeof(sock); new_fd = ::accept(fd, (struct sockaddr*)&sock, &sockLen); if (new_fd == -1) { if (errno == EINTR) continue; else return -1; } break; } if (setNonblocking(new_fd) == false) { LOG(ERROR) << "set socket nonblocking error\n"; ::close(new_fd); return -1; } int send_buffer_size = SOCKET_BUFFER_SIZE; setsockopt(new_fd, SOL_SOCKET, SO_SNDBUF, (void*)&send_buffer_size, sizeof(send_buffer_size)); int flags = 1; int ret = setsockopt(new_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); ret = setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); if (ret != 0) LOG(ERROR) << "setsockopt tcp_nodelay error\n"; struct linger ling = {0, 0}; setsockopt(new_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling)); if (ret != 0) LOG(ERROR) << "setsockopt tcp_linger error\n"; return new_fd; }
int main(int argc, char* argv[]) { server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (server == -1) error("cannot create socket."); setNonblocking(server); struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = argc > 1 ? htons(atoi(argv[argc-1])) : htons(22222); saddr.sin_addr.s_addr = 0; if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) error("cannot bind."); if (listen(server,1) == -1) error("cannot listen."); // cerr << "Starting server..." << endl; while (true) { think(); } }
void Socket::createSocket(const SocketAddress& sa) const { SOCKET& socket = impl->fd; if (socket != INVALID_SOCKET) Socket::close(); SOCKET s = ::socket (getAddrInfo(sa).ai_family, getAddrInfo(sa).ai_socktype, 0); if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError()); socket = s; try { if (nonblocking) setNonblocking(); if (nodelay) setTcpNoDelay(); } catch (std::exception&) { ::closesocket(s); socket = INVALID_SOCKET; throw; } }
int main(int argc, char *argv[]) { int listenfd; struct sockaddr_in server_addr; int opt = 1; //套接字选项 int result; listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd == -1){ perror("socket error"); exit(1); } setNonblocking(listenfd); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //接受任意IP server_addr.sin_port = htons(PORT); //设置socket状态 //SOL_SOCKET:存取socket层, SO_REUSEADDR:允许在bind()过程中本地址可重复使用 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //绑定套接字 result = bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if(result == -1){ perror("socket bind error"); exit(1); } result = listen(listenfd, LISTENQ); if(result == -1){ perror("socket listen error"); exit(1); } do_epoll(listenfd); return 0; }
int runRedirector(pid_t *pid_return, int *read_fd_return, int *write_fd_return) { int rc, rc2, status; pid_t pid; int filedes1[2], filedes2[2]; sigset_t ss, old_mask; assert(redirector); if(redirector_buffer == NULL) { redirector_buffer = malloc(REDIRECTOR_BUFFER_SIZE); if(redirector_buffer == NULL) return -errno; } rc = pipe(filedes1); if(rc < 0) { rc = -errno; goto fail1; } rc = pipe(filedes2); if(rc < 0) { rc = -errno; goto fail2; } fflush(stdout); fflush(stderr); flushLog(); interestingSignals(&ss); do { rc = sigprocmask(SIG_BLOCK, &ss, &old_mask); } while (rc < 0 && errno == EINTR); if(rc < 0) { rc = -errno; goto fail3; } pid = fork(); if(pid < 0) { rc = -errno; goto fail4; } if(pid > 0) { do { rc = sigprocmask(SIG_SETMASK, &old_mask, NULL); } while(rc < 0 && errno == EINTR); if(rc < 0) { rc = -errno; goto fail4; } rc = setNonblocking(filedes1[1], 1); if(rc >= 0) rc = setNonblocking(filedes2[0], 1); if(rc < 0) { rc = -errno; goto fail4; } /* This is completely unnecesary -- if the redirector cannot be started, redirectorStreamHandler1 will get EPIPE straight away --, but it improves error messages somewhat. */ rc = waitpid(pid, &status, WNOHANG); if(rc > 0) { logExitStatus(status); rc = -EREDIRECTOR; goto fail4; } else if(rc < 0) { rc = -errno; goto fail4; } *read_fd_return = filedes2[0]; *write_fd_return = filedes1[1]; *pid_return = pid; /* This comes at the end so that the fail* labels can work */ close(filedes1[0]); close(filedes2[1]); } else { close(filedes1[1]); close(filedes2[0]); uninitEvents(); do { rc = sigprocmask(SIG_SETMASK, &old_mask, NULL); } while (rc < 0 && errno == EINTR); if(rc < 0) exit(142); if(filedes1[0] != 0) dup2(filedes1[0], 0); if(filedes2[1] != 1) dup2(filedes2[1], 1); execlp(redirector->string, redirector->string, NULL); exit(142); /* NOTREACHED */ } return 1; fail4: do { rc2 = sigprocmask(SIG_SETMASK, &old_mask, NULL); } while(rc2 < 0 && errno == EINTR); fail3: close(filedes2[0]); close(filedes2[1]); fail2: close(filedes1[0]); close(filedes1[1]); fail1: free(redirector_buffer); redirector_buffer = NULL; return rc; }
int main(int argc, char **argv) { int port = 22000; std::string host = "127.0.0.1"; if (argc >= 3) { host = argv[1]; port = atoi(argv[2]); } LOG("LISTEN " << host << ":" << port); int events_fd = kqueue(); if (events_fd < 0) { err(1, "\t%s:%d", __FILE__, __LINE__); } fdMap[events_fd] = FDType::events; struct sockaddr_in servaddr; bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(port); inet_pton(AF_INET, host.c_str(), &(servaddr.sin_addr)); int listen_fd = ::socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { err(1, "\t%s:%d", __FILE__, __LINE__); } fdMap[listen_fd] = FDType::listen; int enable = 1; if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { err(1, "setsockopt(SO_REUSEADDR) failed %s:%d", __FILE__, __LINE__); } if (::bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { err(1, "Error bind \t%s:%d", __FILE__, __LINE__); } if (::listen(listen_fd, 10) < 0) { err(1, "\t%s:%d", __FILE__, __LINE__); } setNonblocking(listen_fd); kqAdd(listen_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0); struct kevent events[MAX_EVENTS]; while (1) { int events_size = ::kevent(events_fd, events_to_monitor, events_to_monitor_size, events, MAX_EVENTS, 0); events_to_monitor_size = 0; for (int i = 0; i < events_size; ++i) { struct kevent &event = events[i]; LOG(event); int fd = (int) event.ident; auto fdMapIt = fdMap.find(fd); if (fdMapIt == fdMap.end()) { warn("Error accepting \t%s:%d", __FILE__, __LINE__); continue; } switch (fdMapIt->second) { case FDType::listen : { struct sockaddr_in client_addr; socklen_t ca_len = sizeof(client_addr); int client_fd = accept(fd, (struct sockaddr *) &client_addr, &ca_len); LOG("accept(" << fd << ") return " << client_fd); if (client_fd < 0) { warn("Error accepting \t%s:%d", __FILE__, __LINE__); continue; } LOG("Client connected: " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port)); fdMap[client_fd] = FDType::client; setNonblocking(client_fd); kqAdd(client_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0); kqAdd(client_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE, 0); break; } case FDType::client : { if (event.filter == EVFILT_READ) { if (event.flags & EV_EOF) { LOG("close(" << fd << ")"); close(fd); break; } char buffer[BUFFER_SIZE]; int received = ::recv(fd, buffer, BUFFER_SIZE, 0); if (received < 0) { warn("Error reading from socket \t%s:%d", __FILE__, __LINE__); break; } if (received == 0) { LOG("close(" << fd << ")"); close(fd); break; } else { buffer[received] = 0; LOG("Reading " << received << " bytes: '" << buffer << "'"); } if (::send(fd, buffer, received, 0) != received) { warn("Could not write to stream \t%s:%d", __FILE__, __LINE__); continue; } } break; } } } } close(events_fd); }
static int count_connects(int ipadr, int portnum, int want) { int i; int maxfd; int nopen; struct pollfd pfds[65536]; int nok; int nrej; time_t end; #ifdef VERBOSE printf("Starting connections until we can't start any more; will print what stops us to stderr.\n"); #endif for (i = 0; i < want; i++) { struct sockaddr_in srv_addr; int err; fds[i] = socket(AF_INET, SOCK_STREAM, 0); if (fds[i] < 0) { #ifdef VERBOSE perror("socket"); #endif break; } setNonblocking(fds[i]); /* else connect will wait until resources avail */ memset((char *) &srv_addr, 0, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = ipadr; srv_addr.sin_port = htons(portnum); /* daytime service */ err = connect(fds[i], (struct sockaddr *) &srv_addr, sizeof(srv_addr)); if ((err != 0) && (errno != EINPROGRESS)) { #ifdef VERBOSE perror("connect"); #endif break; } pfds[i].fd = fds[i]; pfds[i].events = POLLOUT; } maxfd = i; #ifdef VERBOSE printf("%d connections in progress...\n", maxfd); #endif /* Now sit until they all connect or fail, or until five seconds * pass, whichever comes first. */ end = time(0) + 6; for (nrej=nok=0, nopen=maxfd; nopen; ) { int nready; if ((end - time(0)) < 0) break; nready = poll(pfds, maxfd, 1000); if (nready < 0) { perror("poll"); exit(1); } for (i=0; i<maxfd; i++) { if ((pfds[i].fd == -1) || !pfds[i].revents) continue; /* question: if a connect fails, will it show up first * as a POLLERR, POLLHUP, or POLLOUT? */ if (pfds[i].revents & (POLLHUP|POLLERR)) { /* connect failed? */ close(pfds[i].fd); nrej++; } else if (pfds[i].revents & POLLOUT) { /* check to see if connect succeeded */ int connecterr = -1; socklen_t len = sizeof(connecterr); if (getsockopt(pfds[i].fd, SOL_SOCKET, SO_ERROR, (char *)&connecterr, &len) < 0) { perror("getsockopt"); exit(1); } if (!connecterr) { nok++; /* keep socket open */ } else if (connecterr == ECONNREFUSED) { close(pfds[i].fd); nrej++; } } else { printf("bad poll result: pfds[%d].fd %d, .revents %x\n", i, pfds[i].fd, pfds[i].revents); exit(1); } pfds[i].fd = -1; nopen--; } } /* Close 'em (might close a few extra, but that's ok) */ for (i = 0; i < maxfd; i++) close(fds[i]); #ifdef VERBOSE printf("%d connections accepted, %d rejected, %d pending\n", nok, nrej, nopen); #endif return nok + nrej + nopen; }
void run() { struct sockaddr_in server_addr; bzero(&server_addr,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); int server_socket = socket(PF_INET, SOCK_STREAM, 0); if( server_socket < 0) { printf("Create Socket Failed!"); exit(1); } int opt = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,&opt, sizeof(opt)); setNonblocking(server_socket); if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) { printf("Server Bind Port : %d Failed!", SERVER_PORT); exit(1); } if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE) ) { printf("Server Listen Failed!"); exit(1); } int efd = epoll_create(MAXEVENTS); if (efd == -1) { perror ("epoll_create"); return; } struct epoll_event server_event; server_event.data.ptr = new Connection(server_socket); server_event.events = EPOLLIN; printf("epoll_ctl [%d]\n", epoll_ctl(efd, EPOLL_CTL_ADD, server_socket, &server_event)); struct epoll_event events[MAXEVENTS]; while (1) { fflush(stdout); int n = epoll_wait (efd, events, MAXEVENTS, -1); // printf("epoll_wait [%d] events\n", n); for (int i = 0; i < n; i++) { Connection* conn = (Connection*)(events[i].data.ptr); if (conn == NULL) { printf("invalid conn[%p]", conn); continue; } if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)) { printf("epoll error\n"); printf("epoll_del [%d]\n", epoll_ctl(efd, EPOLL_CTL_DEL, conn->GetFd(), NULL)); close(conn->GetFd()); delete conn; continue; } if (conn->GetFd() == server_socket) { struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); int new_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length); if (new_socket < 0) { printf("Server Accept Failed!\n"); break; } setNonblocking(new_socket); Connection* conn = new Connection(new_socket); struct epoll_event* event = new struct epoll_event; event->data.ptr = conn; event->events = EPOLLIN|EPOLLET; // event->events = EPOLLIN; int ret = epoll_ctl(efd, EPOLL_CTL_ADD, conn->GetFd(), event); if (ret != 0) { printf("epoll_add read [%d] %d %s\n", ret, errno, strerror(errno)); } } else { RETCODE retCode = conn->Handle(events[i].events); if (retCode == DELETE) { int ret = epoll_ctl(efd, EPOLL_CTL_DEL, conn->GetFd(), NULL); if (ret != 0) { printf("epoll_del [%d]\n\n\n", epoll_ctl(efd, EPOLL_CTL_DEL, conn->GetFd(), NULL)); } printf("\n\n\n"); close(conn->GetFd()); delete conn; } else if (retCode == ADDOUT) { struct epoll_event* event = new struct epoll_event; event->data.ptr = conn; event->events = EPOLLOUT|EPOLLET; // event->events = EPOLLOUT; int ret = epoll_ctl(efd, EPOLL_CTL_MOD, conn->GetFd(), event); if (ret != 0) { printf("epoll_add write [%d] %d %s\n", ret, errno, strerror(errno)); } } } } } // while accept() close(server_socket); }
int EpollSocket::start_epoll(int port, EpollSocketWatcher &socket_handler, int backlog) { int sockfd = this->listen_on(port, backlog); struct epoll_event ev; int epollfd = epoll_create(10); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = sockfd; if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) { perror("epoll_ctl: listen_sock"); exit(EXIT_FAILURE); } epoll_event events[10]; while(1) { int fds_num = epoll_wait(epollfd, events, 10, -1); if(fds_num == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (int i = 0; i < fds_num; i++) { if(events[i].data.fd == sockfd) { int conn_sock = accept_socket(sockfd); setNonblocking(conn_sock); LOG_DEBUG("get accept socket which listen fd:%d, conn_sock_fd:%d", sockfd, conn_sock); EpollContext *epoll_context = new EpollContext(); epoll_context->fd = conn_sock; socket_handler.on_accept(*epoll_context); epoll_event conn_sock_ev; conn_sock_ev.events = EPOLLIN | EPOLLET; conn_sock_ev.data.ptr = epoll_context; if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &conn_sock_ev) == -1) { perror("epoll_ctl: conn_sock"); exit(EXIT_FAILURE); } } else if(events[i].events & EPOLLIN ){ // readable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; int buffer_size = 1024; char read_buffer[buffer_size]; memset(read_buffer, 0, buffer_size); int read_size = 0; while((read_size = recv(fd, read_buffer, buffer_size, 0)) > 0) { LOG_DEBUG("read success which read size:%d", read_size); int ret = socket_handler.on_readable(*epoll_context, read_buffer, buffer_size, read_size); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } memset(read_buffer, 0, buffer_size); // reset buffer for next read } if(read_size == 0 /* connect close*/ || (read_size == -1 && errno != EAGAIN) /* io error*/) { LOG_DEBUG("read_size not normal which size:%d", read_size); close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLOUT | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else if(events[i].events & EPOLLOUT) { // writeable EpollContext *epoll_context = (EpollContext *) events[i].data.ptr; int fd = epoll_context->fd; LOG_DEBUG("start write data"); int ret = socket_handler.on_writeable(*epoll_context); if(ret != 0) { close_and_release(epollfd, events[i], socket_handler); continue; } events[i].events = EPOLLIN | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &events[i]); } else { LOG_INFO("unkonw events :%d", events[i].events); continue; } } } }
struct process* accept_sock ( int listen_sock ) { int s; // 在ET模式下必须循环accept到返回-1为止 while ( 1 ) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if ( current_total_processes >= MAX_PORCESS ) { // 请求已满,accept之后直接挂断 infd = accept ( listen_sock, &in_addr, &in_len ); if ( infd == -1 ) { if ( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { /* We have processed all incoming connections. */ break; } else { perror ( "accept" ); break; } } close ( infd ); return; } in_len = sizeof in_addr; infd = accept ( listen_sock, &in_addr, &in_len ); if ( infd == -1 ) { if ( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { /* We have processed all incoming connections. */ break; } else { perror ( "accept" ); break; } } getnameinfo ( &in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV ); /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ s = setNonblocking ( infd ); if ( s == -1 ) abort (); int on = 1; setsockopt ( infd, SOL_TCP, TCP_CORK, &on, sizeof ( on ) ); //添加监视sock的读取状态 event.data.fd = infd; event.events = EPOLLIN | EPOLLET; s = epoll_ctl ( efd, EPOLL_CTL_ADD, infd, &event ); if ( s == -1 ) { perror ( "epoll_ctl" ); abort (); } struct process* process = find_empty_process_for_sock ( infd ); current_total_processes++; reset_process ( process ); process->sock = infd; process->fd = NO_FILE; process->status = STATUS_READ_REQUEST_HEADER; } }
FdEventHandlerPtr create_listener(char *address, int port, int (*handler) (int, FdEventHandlerPtr, AcceptRequestPtr), void *data) { int fd, rc; int one = 1; int done; struct sockaddr_in addr; int inet6 = 0; if (inet6 && address) { struct in_addr buf; rc = inet_aton(address, &buf); if (rc == 1) inet6 = 0; } fd = -1; errno = EAFNOSUPPORT; if (fd < 0 && (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)) { inet6 = 0; fd = socket(PF_INET, SOCK_STREAM, 0); } if (fd < 0) { done = (*handler) (-errno, NULL, NULL); assert(done); return NULL; } rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); if (rc < 0) do_log_error(L_WARN, errno, "Couldn't set SO_REUSEADDR"); if (inet6) { rc = -1; errno = EAFNOSUPPORT; } else { memset(&addr, 0, sizeof(addr)); rc = inet_aton(address, &addr.sin_addr); if (rc != 1) { done = (*handler) (rc == 0 ? -ESYNTAX : -errno, NULL, NULL); assert(done); return NULL; } addr.sin_family = AF_INET; addr.sin_port = htons(port); rc = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); } if (rc < 0) { do_log_error(L_ERROR, errno, "Couldn't bind"); CLOSE(fd); done = (*handler) (-errno, NULL, NULL); assert(done); return NULL; } rc = setNonblocking(fd, 1); if (rc < 0) { do_log_error(L_ERROR, errno, "Couldn't set non blocking mode"); CLOSE(fd); done = (*handler) (-errno, NULL, NULL); assert(done); return NULL; } rc = listen(fd, 32); if (rc < 0) { do_log_error(L_ERROR, errno, "Couldn't listen"); CLOSE(fd); done = (*handler) (-errno, NULL, NULL); assert(done); return NULL; } /* do_log(L_INFO, "Established listening socket on port %d.\n", port); */ return schedule_accept(fd, handler, data); }
int main ( int argc, char *argv[] ) { int s; struct epoll_event *events; signal ( SIGABRT, &sighandler ); signal ( SIGTERM, &sighandler ); signal ( SIGINT, &sighandler ); if ( argc != 3 ) { fprintf ( stderr, "Usage: %s [port] [doc root]\n", argv[0] ); exit ( EXIT_FAILURE ); } init_processes(); listen_sock = create_and_bind ( argv[1] ); doc_root = argv[2]; if ( listen_sock == -1 ) abort (); s = setNonblocking ( listen_sock ); if ( s == -1 ) abort (); s = listen ( listen_sock, SOMAXCONN ); if ( s == -1 ) { perror ( "listen" ); abort (); } efd = epoll_create1 ( 0 ); if ( efd == -1 ) { perror ( "epoll_create" ); abort (); } event.data.fd = listen_sock; event.events = EPOLLIN | EPOLLET; s = epoll_ctl ( efd, EPOLL_CTL_ADD, listen_sock, &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 ); if ( n == -1 ) { perror ( "epoll_wait" ); } for ( i = 0; i < n; i++ ) { if ( ( events[i].events & EPOLLERR ) || ( events[i].events & EPOLLHUP ) ) { /* 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; } handle_request ( events[i].data.fd ); } } free ( events ); close ( listen_sock ); return EXIT_SUCCESS; }
void call_udpl_epoll(struct sockaddr_in servaddr, unsigned expected_size, unsigned *latency, size_t sender_buf_size) { int sockfd; char buf[BUF_SIZE]; struct timespec start; struct timespec end; int n, i; size_t sent_size=0; size_t max_send_size=0; struct epoll_event ev, events[MAX_EVENTS]; int nfds, epollfd; struct timespec wait_for_server={.tv_sec=0, .tv_nsec=INTERVAL}; assert(sender_buf_size <= BUF_SIZE); nanosleep(&wait_for_server, NULL); sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (setNonblocking(sockfd) != 0) perror("setNonblocking"); epollfd = epoll_create(16); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = sockfd; // need not care about blocking if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) { perror("epoll_ctl: sockfd"); exit(EXIT_FAILURE); } max_send_size = MIN(MAX_UDP_SIZE, MIN(expected_size, sender_buf_size)); clock_gettime(CLOCK_MONOTONIC, &start); // send something first n = sendton(sockfd, buf, max_send_size, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (n < 0) perror("client sendto"); while (sent_size < expected_size) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } for (i = 0; i < nfds; ++i) { if (events[i].events & EPOLLIN) { // readable n = Readn(events[i].data.fd, buf, BUF_SIZE); sent_size += n; // only the echoed size is effective if (DEBUG) printf("%u / %u<<<<%u / %u echo rate\n", n, MIN(max_send_size, expected_size - sent_size), sent_size, expected_size); if (sendton(sockfd, buf, MIN(max_send_size, expected_size - sent_size), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) perror("client sendto"); } } } clock_gettime(CLOCK_MONOTONIC, &end); *latency = ((end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec) / 2; close(sockfd); } void call_udpt_epoll(struct sockaddr_in servaddr, unsigned expected_size, unsigned *latency, size_t sender_buf_size, size_t *received) { int sockfd; char buf[BUF_SIZE]; struct timespec start; struct timespec end; int n, i, ret; size_t sent_size=0; size_t max_send_size, send_size; struct epoll_event ev, events[MAX_EVENTS]; int nfds, epollfd; struct timespec wait_for_server={.tv_sec=0, .tv_nsec=INTERVAL}; assert(sender_buf_size <= BUF_SIZE); nanosleep(&wait_for_server, NULL); sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (setNonblocking(sockfd) != 0) perror("setNonblocking"); epollfd = epoll_create(16); if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = sockfd; // need not care about blocking if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) { perror("epoll_ctl: sockfd"); exit(EXIT_FAILURE); } max_send_size = MIN(MAX_UDP_SIZE, MIN(expected_size, sender_buf_size)); *received = 0; clock_gettime(CLOCK_MONOTONIC, &start); // when performing throughput, sender needs not to care about receiver while (sent_size < expected_size) { send_size = MIN(max_send_size, expected_size - sent_size); Sendton(sockfd, buf, send_size, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (DEBUG) printf("%u>>>>%u / %u sendto\n", send_size, sent_size, expected_size); sent_size += send_size; } if (DEBUG) printf("client finished throughput sent %u\n", sent_size); // the second while is used to receive multiple reply while (1) { nfds = epoll_wait(epollfd, events, MAX_EVENTS, EPOLL_MILLI_TIMEOUT); if (nfds == -1) { perror("epoll_pwait"); exit(EXIT_FAILURE); } else if (nfds == 0) break; for (i = 0; i < nfds; ++i) { if (events[i].events & EPOLLIN) { // readable while (1) { // since server will respond to every sent packet, there may be multiple responds ret = read(events[i].data.fd, &n, sizeof(int)); if (ret < 0) { if (!((errno == EAGAIN) || (errno == EWOULDBLOCK))) perror("read error other than nonblock read"); break; } else if (ret == 0) // end of file break; else { // single "ack" response contributes a small amount of time clock_gettime(CLOCK_MONOTONIC, &end); *received += n; if (DEBUG) printf("<<<<%u echoed\n", n); } } if (DEBUG) printf("%i / %u ack Received\n", *received, expected_size); } } } *latency = (end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec; close(sockfd); } #ifdef CLIENT_MAIN int main(int argc, char**argv) { struct sockaddr_in servaddr; unsigned chunk_size[] = {4, 16, 64, 256, 1024, 4*1024, 16*1024, 64*1024, 256*1024, 512*1024, 32*1024, 48*1024, 96*1024, 128*1024}; //unsigned chunk_size[] = {4, 16, 64, 256, 1024, 4*1024, 16*1024, 32*1024, 64*1024, 96*1024, 128*1024}; unsigned latency, total_time; size_t received; int i; int repeat=1; size_t sender_buf_size=1024; if (argc >= 5) sender_buf_size = atoi(argv[4]); if (argc >= 4) repeat = atoi(argv[3]); if (argc < 3) { printf("usage: [udp|tcp] <IP address> <repeat times> <sender_buf_size=1024>\n"); exit(1); } bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr=inet_addr(argv[2]); servaddr.sin_port=htons(PORT); while (repeat) { if (strcmp(argv[1], "udp") == 0) { printf("SIZE\tUDP latency us\tUDP througput MB/s\tLOST\tLOSS rate%%\n"); for (i=0; i<sizeof(chunk_size) / sizeof(chunk_size[0]); i++) { call_udp(servaddr, 1, chunk_size[i], &latency, NULL); call_udp(servaddr, 0, chunk_size[i], &total_time, &received); printf("%8u\t%8u\t%8.2f\t%8u\t%8.2f\n", chunk_size[i], latency / 1000, chunk_size[i] * 1000000000.0 / total_time / 1024 / 1024, chunk_size[i] - received, (chunk_size[i] - received) * 100.0 / chunk_size[i]); } } else if (strcmp(argv[1], "udpl") == 0) { printf("SIZE\tUDP latency us\tsender_buf_size: %i\n", sender_buf_size); for (i=0; i<sizeof(chunk_size) / sizeof(chunk_size[0]); i++) { call_udpl_epoll(servaddr, chunk_size[i], &latency, sender_buf_size); printf("%8u\t%8u\n", chunk_size[i], latency / 1000); } } else if (strcmp(argv[1], "udpt") == 0) { printf("SIZE\tUDP throughput MB/s\tLOST\tLOSS Rate%%\tsender_buf_size: %i\n", sender_buf_size); for (i=0; i<sizeof(chunk_size) / sizeof(chunk_size[0]); i++) { call_udpt_epoll(servaddr, chunk_size[i], &latency, sender_buf_size, &received); printf("%8u\t%8.2f\t%8u\t%8.2f\n", chunk_size[i], chunk_size[i] * 1000000000.0 / latency / 1024 / 1024, chunk_size[i] - received, (chunk_size[i] - received) * 100.0 / chunk_size[i]); } } else if (strcmp(argv[1], "tcp") == 0) { printf("SIZE\tTCP latency us\tTCP througput MB/s\tLOST\tLOSS rate\n"); for (i=0; i<sizeof(chunk_size) / sizeof(chunk_size[0]); i++) { call_tcp(servaddr, 1, chunk_size[i], &latency, NULL); call_tcp(servaddr, 0, chunk_size[i], &total_time, &received); printf("%8u\t%8u\t%8.2f\t%8u\t%8.2f\n", chunk_size[i], latency / 1000, chunk_size[i] * 1000000000.0 / total_time / 1024 / 1024, chunk_size[i] - received, (chunk_size[i] - received) * 100.0 / chunk_size[i]); } } repeat--; } }
int writeStringToFile(int i_fd, const char* ccp_text) { struct pollfd poll_fd[1]; int i_text_length = 0; int i_poll_result = 0; int i_num_polls = 1; ssize_t written_bytes = 0; ssize_t total_written_bytes = 0; if(ccp_text == NULL) { return EXIT_FAILURE; } if (setNonblocking(i_fd)) { debug(HTTP_RESPONSE, "Setting output stream non-blocking failed.\n"); return EXIT_FAILURE; } i_text_length = strlen(ccp_text); poll_fd[0].fd = i_fd; poll_fd[0].events = POLLOUT; poll_fd[0].revents = 0; while(total_written_bytes < i_text_length) { i_poll_result = poll(poll_fd, i_num_polls, si_cgi_timeout_); if(i_poll_result < 0) { debug(HTTP_RESPONSE, "Polling on output stream failed."); return EXIT_FAILURE; } if(i_poll_result == 0) { debug(HTTP_RESPONSE, "Output stream timed out."); return EXIT_FAILURE; } if((poll_fd[0].revents & (POLLERR)) || ((!poll_fd[0].revents) & (POLLHUP))) { debug(HTTP_RESPONSE, "A problem occurred on the output stream."); return EXIT_FAILURE; } written_bytes = write(poll_fd[0].fd, ccp_text + (total_written_bytes), i_text_length - total_written_bytes); total_written_bytes += written_bytes; if (written_bytes < 0) { if(errno != EAGAIN) { debug(HTTP_RESPONSE, "Error while writing on output stream.\n"); return EXIT_FAILURE; } } } return EXIT_SUCCESS; }
/** * struct sockaddr_in serv: * * Descriptions **/ void call_tcp(struct sockaddr_in servaddr, bool require_echo, unsigned expected_size, unsigned *latency, size_t *received) { int sockfd; char buf[BUF_SIZE]; struct timespec start; struct timespec end; int optval=1; sockfd=socket(AF_INET,SOCK_STREAM,0); if (setsockopt(sockfd, IPPROTO_IP, TCP_NODELAY, &optval, sizeof(optval)) != 0) perror("setsockopt TCP_NODELAY"); if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) perror("connect"); struct timespec wait_for_server={.tv_sec=0, .tv_nsec=INTERVAL}; nanosleep(&wait_for_server, NULL); Writen(sockfd, &expected_size, sizeof(unsigned)); Writen(sockfd, &require_echo, sizeof(bool)); // could ignore the header time clock_gettime(CLOCK_MONOTONIC, &start); Writen(sockfd, buf, expected_size); if (DEBUG) printf("buf sent\n"); if (require_echo) { // measuring latency Readn(sockfd, buf, expected_size); clock_gettime(CLOCK_MONOTONIC, &end); *latency = ((end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec) / 2; } else { // measuring througput Readn(sockfd, received, sizeof(received)); clock_gettime(CLOCK_MONOTONIC, &end); *latency = ((end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec); } close(sockfd); } void call_udp(struct sockaddr_in servaddr, bool require_echo, unsigned expected_size, unsigned *latency, size_t *received) { int sockfd; char buf[BUF_SIZE]; struct timespec start; struct timespec end; struct SimpleProtocol data; data.require_echo = require_echo; data.expected_size = expected_size; sockfd=socket(AF_INET, SOCK_DGRAM, 0); Sendton(sockfd, &data, sizeof(data), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); clock_gettime(CLOCK_MONOTONIC, &start); Sendton(sockfd, buf, expected_size, 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (DEBUG) printf("request sent: expected_size=%u, require_echo=%i, Reading...\n", data.expected_size, data.require_echo); if (data.require_echo) { // measuring latency // prevent client from blocking on receiving less data than expected setNonblocking(sockfd); Readn(sockfd, buf, expected_size); clock_gettime(CLOCK_MONOTONIC, &end); *latency = ((end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec) / 2; } else { // measuring througput Readn(sockfd, received, sizeof(int)); clock_gettime(CLOCK_MONOTONIC, &end); *latency = ((end.tv_sec - start.tv_sec) * 1000000000 + end.tv_nsec - start.tv_nsec); if (DEBUG) printf("SUMMARY: %i of %u sent\n", *received, expected_size); } close(sockfd); }
/** tiniweb main routine * @param argc number of commandline arguments * @param argv arguments itself * @return tiniweb return value */ int main(int argc, char** argv) { int c = 0; int i_option_index = 0; bool b_static = FALSE; char* cp_mapped_path = NULL; char* cp_path_to_htdigest_file = NULL; char* cp_search_path_root = NULL; bool b_digest_file_available = FALSE; bool b_authenticated = FALSE; // command line parsing: like done in example from // http://www.gnu.org/s/libc/manual/html_node/Getopt-Long-Option-Example.html while (1) { static struct option long_options[] = { { "web-dir", required_argument, 0, 0 }, { "cgi-dir", required_argument, 0, 1 }, { "cgi-timeout", required_argument, 0, 2 }, { "secret", required_argument, 0, 3}, { "verbose", no_argument, 0, 4 }, { 0, 0, 0, 0 } }; i_option_index = 0; c = getopt_long(argc, argv, "", long_options, &i_option_index); if (c == -1) break; switch (c) { case 0: scp_web_dir_ = secPrint2String("%s", optarg); debugVerbose(MAIN, "option web-dir used with argument: %s \n", scp_web_dir_); break; case 1: scp_cgi_dir_ = secPrint2String("%s",optarg); debugVerbose(MAIN, "option cgi-dir used with argument: %s \n", scp_cgi_dir_); break; case 2: debugVerbose(MAIN, "option cgi-timeout used with argument: %s \n", optarg); si_cgi_timeout_ = (int) strtol(optarg, NULL, 10); si_cgi_timeout_ *= 1000; break; case 3: scp_secret_ = secPrint2String("%s", optarg); debugVerbose(MAIN, "option secret used with argument: %s \n", scp_secret_); break; case 4: b_flag_verbose_ = TRUE; debugVerbose(MAIN, "switching to verbose mode \n"); break; default: debug(MAIN, "encountert unknown argument \n"); secExit(STATUS_CANCEL); break; } } if(!scp_cgi_dir_ || !scp_web_dir_ || !scp_secret_){ debug(MAIN, "Mandatory parameter missing\n"); debug(MAIN, "usage: ./tiniweb (--verbose) --web-dir <path> --cgi-dir <path> --secret <secret> (--cgi-timeout <msec>)\n"); secExit(STATUS_CANCEL); } if (performPathChecking(&scp_cgi_dir_, &scp_web_dir_) == FALSE) { debug(MAIN, "ERROR, Paths not valid!\n"); secExit(STATUS_CANCEL); } if(si_cgi_timeout_ < CGI_TIME_OUT_MIN) { debug(MAIN, "cgi-timeout is too short, using default value (%d)\n", CGI_TIME_OUT_MIN); si_cgi_timeout_ = CGI_TIME_OUT_MIN; } else if(si_cgi_timeout_ > CGI_TIME_OUT_MAX) { debug(MAIN, "cgi-timeout is too long, using default value (%d)\n", CGI_TIME_OUT_MAX); si_cgi_timeout_ = CGI_TIME_OUT_MAX; } debug(MAIN, "Argument parsing finished\n"); debugVerbose(MAIN, "WEB_DIR = %s \n", scp_web_dir_); debugVerbose(MAIN, "CGI_DIR = %s \n", scp_cgi_dir_); debugVerbose(MAIN, "SECRET = %s \n", scp_secret_); debugVerbose(MAIN, "CGI_TIMEOUT = %d \n", si_cgi_timeout_); debugVerbose(MAIN, "Switching stdin to non_blocking mode\n"); if(setNonblocking(STDIN_FILENO)) { debug(MAIN, "Switching stdin to non_blocking mode failed!\n"); secAbort(); } char* cp_header = retrieveHeader(STDIN_FILENO, STDIN_TIMEOUT); if(cp_header == NULL) { debug(MAIN,"STDIN has to talk to use! We don't like DoS\n"); secExit(STATUS_CANCEL); } http_norm *hnp_info = normalizeHttp(cp_header, FALSE); debugVerbose(MAIN, "Normalize finished \n"); parse(hnp_info); debugVerbose(MAIN, "Parsing finished \n"); if (mapRequestPath(&cp_mapped_path, &b_static) == FALSE) { secExit(STATUS_NOT_FOUND); } if (checkRequestPath(cp_mapped_path) == FALSE) { secExit(STATUS_NOT_FOUND); } cp_search_path_root = b_static ? scp_web_dir_ : scp_cgi_dir_; if (searchForHTDigestFile(cp_mapped_path, cp_search_path_root, &b_digest_file_available, &cp_path_to_htdigest_file) == EXIT_FAILURE) { // We found two .htdigest Files in the path! File is protected! secExit(STATUS_FORBIDDEN); } if (b_digest_file_available) { b_authenticated = authenticate(cp_path_to_htdigest_file); } if(b_authenticated == TRUE || b_digest_file_available == FALSE) { if(b_static == TRUE) { processStaticFile(cp_mapped_path); } else { setupEnvVarList(scp_web_dir_, cp_mapped_path, hnp_info, b_authenticated); processCGIScript(cp_mapped_path); } } secExit(STATUS_OK); return EXIT_SUCCESS; }
static void do_epoll(int listenfd) { int epollfd, sockfd; //ev用于注册事件,数组用于存储要处理的事件 struct epoll_event ev, events[LISTENQ]; struct sockaddr_in clien_addr; int fd_numb; int i, rw_size; char buf[MAXSIZE]; int clilen; pthread_t pid; //创建一个描述符 epollfd = epoll_create(LISTENQ); //添加监听描述符事件 //EPOLLIN:表示对应的文件描述符可读; EPOLLIN:设置ET工作模式 ev.events = EPOLLIN | EPOLLET; ev.data.fd = listenfd; //EPOLL_CTL_ADD:注册listenfd到epollfd中 epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev); while(1) { //获取已经准备好的描述符事件 //第3个参数不能大于epoll_create的参数, -1:超时时间, -1表示永久阻塞 fd_numb = epoll_wait(epollfd, events, LISTENQ, -1); //printf("收到连接请求数:%d\n", fd_numb); //处理事件 for(i=0; i<fd_numb; i++) { //检测到用户连接 if(events[i].data.fd == listenfd){ clilen = sizeof(clien_addr); sockfd = accept(listenfd, (struct sockaddr *)&clien_addr, &clilen ); if(sockfd == -1){ perror("accept error"); exit(1); } //printf("accept a new client: %s:%d\n", inet_ntoa(clien_addr.sin_addr), ntohs(clien_addr.sin_port)/* clien_addr.sin_port*/ ); setNonblocking(sockfd); //继续添加事件 ev.data.fd = sockfd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev); } else if(events[i].events & EPOLLIN){ //printf("创建了处理线程\n"); pthread_create(&pid , NULL, (void *)handleThread, (void *)&sockfd); } /* else if(events[i].events & EPOLLIN){ rw_size = epoll_read(sockfd, buf, MAXSIZE); //事件读改为写, EPOLL_CTL_MOD:修改已经注册的监听事件 ev.data.fd = sockfd; handleThread,ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, sockfd, &ev); } else if(events[i].events & EPOLLOUT){ //rw_size = write(sockfd, buf, rw_size); epoll_write(sockfd, buf); //事件写改读 ev.data.fd = events[i].data.fd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &ev); }*/ } } close(epollfd); free(events); }
FdEventHandlerPtr create_listener(char *address, int port, int (*handler)(int, FdEventHandlerPtr, AcceptRequestPtr), void *data) { int fd, rc; int one = 1; int done; struct sockaddr_in addr; #ifdef HAVE_IPv6 int inet6 = 1; struct sockaddr_in6 addr6; #else int inet6 = 0; #endif if(inet6 && address) { struct in_addr buf; rc = inet_aton(address, &buf); if(rc == 1) inet6 = 0; } fd = -1; errno = EAFNOSUPPORT; #ifdef HAVE_IPv6 if(inet6) { fd = socket(PF_INET6, SOCK_STREAM, 0); } #endif if(fd < 0 && (errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT)) { inet6 = 0; fd = socket(PF_INET, SOCK_STREAM, 0); } if(fd < 0) { done = (*handler)(-errno, NULL, NULL); assert(done); return NULL; } rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)); if(rc < 0) do_log_error(L_WARN, errno, "Couldn't set SO_REUSEADDR"); if(inet6) { #ifdef HAVE_IPv6 rc = setV6only(fd, 0); if(rc < 0) /* Reportedly OpenBSD returns an error for that. So only log it as a debugging message. */ do_log_error(D_CLIENT_CONN, errno, "Couldn't reset IPV6_V6ONLY"); memset(&addr6, 0, sizeof(addr6)); rc = inet_pton(AF_INET6, address, &addr6.sin6_addr); if(rc != 1) { done = (*handler)(rc == 0 ? -ESYNTAX : -errno, NULL, NULL); assert(done); return NULL; } addr6.sin6_family = AF_INET6; addr6.sin6_port = htons(port); rc = bind(fd, (struct sockaddr*)&addr6, sizeof(addr6)); #else rc = -1; errno = EAFNOSUPPORT; #endif } else { memset(&addr, 0, sizeof(addr)); rc = inet_aton(address, &addr.sin_addr); if(rc != 1) { done = (*handler)(rc == 0 ? -ESYNTAX : -errno, NULL, NULL); assert(done); close(fd); return NULL; } addr.sin_family = AF_INET; addr.sin_port = htons(port); rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); } if(rc < 0) { do_log_error(L_ERROR, errno, "Couldn't bind"); CLOSE(fd); done = (*handler)(-errno, NULL, NULL); assert(done); return NULL; } rc = setNonblocking(fd, 1); if(rc < 0) { do_log_error(L_ERROR, errno, "Couldn't set non blocking mode"); CLOSE(fd); done = (*handler)(-errno, NULL, NULL); assert(done); return NULL; } rc = listen(fd, 1024); if(rc < 0) { do_log_error(L_ERROR, errno, "Couldn't listen"); CLOSE(fd); done = (*handler)(-errno, NULL, NULL); assert(done); return NULL; } do_log(L_INFO, "Established listening socket on port %d.\n", port); return schedule_accept(fd, handler, data); }
int main(int argc , char **argv) { int i, listenfd, connfd, sockfd, epfd, nfds; ssize_t n, ret; char buf[MAX_LINE]; socklen_t clilen; struct sockaddr_in servaddr , cliaddr; /*声明epoll_event结构体变量,ev用于注册事件,数组用于回传要处理的事件*/ struct epoll_event ev, events[20]; /*(1) 得到监听描述符*/ listenfd = socket(AF_INET , SOCK_STREAM , 0); setNonblocking(listenfd); /*生成用于处理accept的epoll专用文件描述符*/ epfd = epoll_create(CONNECT_SIZE); /*设置监听描述符*/ ev.data.fd = listenfd; /*设置处理事件类型*/ ev.events = EPOLLIN | EPOLLET; /*注册事件*/ epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev); /*(2) 绑定套接字*/ bzero(&servaddr , sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); bind(listenfd , (struct sockaddr *)&servaddr , sizeof(servaddr)); /*(3) 监听*/ listen(listenfd , LISTENQ); /*(4) 进入服务器接收请求死循环*/ while(1) { /*等待事件发生*/ nfds = epoll_wait(epfd , events , CONNECT_SIZE , -1); if(nfds <= 0) continue; printf("nfds = %d\n" , nfds); /*处理发生的事件*/ for(i=0 ; i<nfds ; ++i) { /*检测到用户链接*/ if(events[i].data.fd == listenfd) { /*接收客户端的请求*/ clilen = sizeof(cliaddr); if((connfd = accept(listenfd , (struct sockaddr *)&cliaddr , &clilen)) < 0) { perror("accept error.\n"); exit(1); }//if printf("accpet a new client: %s:%d\n", inet_ntoa(cliaddr.sin_addr) , cliaddr.sin_port); /*设置为非阻塞*/ setNonblocking(connfd); ev.data.fd = connfd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd , EPOLL_CTL_ADD , connfd , &ev); }//if /*如果是已链接用户,并且收到数据,进行读入*/ else if(events[i].events & EPOLLIN){ if((sockfd = events[i].data.fd) < 0) continue; bzero(buf , MAX_LINE); printf("reading the socket~~~\n"); if((n = read(sockfd , buf , MAX_LINE)) <= 0) { close(sockfd); events[i].data.fd = -1; }//if else{ buf[n] = '\0'; printf("clint[%d] send message: %s\n", i , buf); /*设置用于注册写操作文件描述符和事件*/ ev.data.fd = sockfd; ev.events = EPOLLOUT| EPOLLET; epoll_ctl(epfd , EPOLL_CTL_MOD , sockfd , &ev); }//else }//else else if(events[i].events & EPOLLOUT) { if((sockfd = events[i].data.fd) < 0) continue; if((ret = write(sockfd , buf , n)) != n) { printf("error writing to the sockfd!\n"); break; }//if /*设置用于读的文件描述符和事件*/ ev.data.fd = sockfd; ev.events = EPOLLIN | EPOLLET; /*修改*/ epoll_ctl(epfd , EPOLL_CTL_MOD , sockfd , &ev); }//else }//for }//while free(events); close(epfd); exit(0); }