bool server_tick(server_t server, int timeout_ms) { int i; int numready; bool raft_ready = false; #ifdef USE_EPOLL struct epoll_event events[MAX_EVENTS]; numready = epoll_wait(server->epollfd, events, MAX_EVENTS, timeout_ms); if (numready < 0) { shout("failed to epoll: %s\n", strerror(errno)); return false; } for (i = 0; i < numready; i++) { stream_t stream = (stream_t)events[i].data.ptr; if (stream == NULL) { server_accept(server); } else if (stream == &server->raft_stream) { raft_ready = true; } else { if (events[i].events & EPOLLERR) { stream->good = false; } else if (events[i].events & EPOLLIN) { server_stream_handle(server, stream); } } } #else fd_set readfds = server->all; struct timeval timeout = ms2tv(timeout_ms); numready = select(server->maxfd + 1, &readfds, NULL, NULL, &timeout); if (numready == -1) { shout("failed to select: %s\n", strerror(errno)); return false; } if (FD_ISSET(server->listener, &readfds)) { numready--; server_accept(server); } if ((server->raft_stream.good) && FD_ISSET(server->raft_stream.fd, &readfds)) { numready--; raft_ready = true; } stream_t s; for (s = server_used_chain; (s != NULL) && (numready > 0); s = s->next) { if (FD_ISSET(s->fd, &readfds)) { server_stream_handle(server, s); numready--; } } #endif server_close_bad_streams(server); server_flush(server); return raft_ready; }
static bool tick(int timeout_ms) { int numready; bool raft_ready = false; fd_set readfds = server.all; struct timeval timeout = ms2tv(timeout_ms); numready = select(server.maxfd + 1, &readfds, NULL, NULL, &timeout); if (numready == -1) { fprintf(stderr, "failed to select: %s\n", strerror(errno)); return false; } if (FD_ISSET(server.listener, &readfds)) { numready--; accept_client(); } if (FD_ISSET(server.raftsock, &readfds)) { numready--; raft_ready = true; } Client *c = server.clients; while (numready > 0) { Assert(c - server.clients < MAX_CLIENTS); if ((c->sock >= 0) && (FD_ISSET(c->sock, &readfds))) { attend(c); numready--; } c++; } drop_bads(); return raft_ready; }
// muust be exec only once! ErrorCode PipeServer::runProc() { int listenSocket = -1; struct sockaddr_un localAddress; if ((listenSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); return ErrorCode::FAILURE; } localAddress.sun_family = AF_UNIX; strcpy(localAddress.sun_path, pipename); unlink(localAddress.sun_path); unsigned int len = strlen(localAddress.sun_path) + sizeof(localAddress.sun_family); if (bind(listenSocket, (struct sockaddr *)&localAddress, len) == -1) { perror("bind"); close(listenSocket); return ErrorCode::FAILURE; } /* * The backlog argument defines the maximum length to which the queue of pending connections * for sockfd may grow. If a connection request arrives when the queue is full, * the client may receive an error with an indication of ECONNREFUSED or, if the underlying * protocol supports retransmission, the request may be ignored so that * a later reattempt at connection succeeds. */ if (listen(listenSocket, CPPL_PIPESERV_UNIX_MAXCONNQUEUE) == -1) { perror("listen"); close(listenSocket); return ErrorCode::FAILURE; } socklen_t t; int acceptSocket; struct sockaddr_un remoteAddress; // int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); int tmperrno; // Set timeout on accept struct timeval tv; ms2tv(mTimCON, &tv); setsockopt(listenSocket, SOL_SOCKET, SO_RCVTIMEO, (const void *) &tv, sizeof(struct timeval)); while(1) // TODO: Termination through IPC or SIGTERM or by closing socket { t = sizeof(sockaddr_un); errno = 0; acceptSocket = accept(listenSocket, (struct sockaddr *)&remoteAddress, &t); tmperrno = errno; if (isTerminated()) { close(listenSocket); printf("PipeServer terminating ....\n"); manager.terminateAndJoin(); return ErrorCode::TERMINATED; } int joined = manager.joinIfFinished(); if (joined) printf("joined %d and remains %d\n", joined, manager.threadCount()); if (tmperrno == EAGAIN) { continue; } // TODO: if timeout continue; if (acceptSocket == -1) { perror("accept"); close(listenSocket); // TODO: we should here terminate and join all threads here return ErrorCode::FAILURE; } manager.startThread<PipeChannel>([=](){return m_proc(acceptSocket, mTimRX, mTimTX);}); } return ErrorCode::SUCCESS; }
TcpErrorCode sock_read_stream(SNET_SOCKTYPE sock, San2::Utils::CThread *thr, char *data, unsigned int dataSize, unsigned int *bytesRead, unsigned int mTimRX) { if (sock == -1) return TcpErrorCode::FAILURE; fd_set fds; // struct sockaddr_un remoteAddress; int selRval; struct timeval tv; while (1) { FD_ZERO(&fds); FD_SET(sock, &fds); ms2tv(mTimRX, &tv); errno = 0; selRval = select(sock+1, &fds, NULL, NULL, &tv); #ifdef LINUX if (errno == EINTR) { // MUST not AFFECT errno if (thr->isTerminated()) return TcpErrorCode::TERMINATED; continue; } if (thr->isTerminated()) return TcpErrorCode::TERMINATED; if (selRval < 0) return TcpErrorCode::FAILURE; #endif if (selRval == 0) continue; // timeout, terminated check already performed #ifdef WINDOWS if (thr->isTerminated()) return TcpErrorCode::TERMINATED; if (selRval == SOCKET_ERROR) { DWORD wsaerr = WSAGetLastError(); if (wsaerr == WSAEINTR || wsaerr == WSAETIMEDOUT) continue; // INTERRUPT continue FILE_LOG(logDEBUG4) << "FAIL: sock_read_stream(): select(): " << wsaerr; return TcpErrorCode::FAILURE; } #endif break; // success } *bytesRead = recv(sock, data, dataSize, 0); #ifdef LINUX if (*bytesRead == 0) return TcpErrorCode::PEER_DISCONNECT; if (*bytesRead < 0) return TcpErrorCode::FAILURE; #endif #ifdef WINDOWS if (*bytesRead == SOCKET_ERROR) { DWORD wsaerr = GetLastError(); if (wsaerr == WSAESHUTDOWN || wsaerr == WSAECONNRESET) return TcpErrorCode::PEER_DISCONNECT; FILE_LOG(logDEBUG4) << "FAIL: sock_read_stream(): recv():2: " << wsaerr; return TcpErrorCode::FAILURE; } #endif return TcpErrorCode::SUCCESS; }
TcpErrorCode sock_sendall_stream(SNET_SOCKTYPE sock, const char *buf, int *len, unsigned int timeoutMsec, San2::Utils::CThread *thr) { if (sock == -1) return TcpErrorCode::FAILURE; fd_set fds; struct timeval tv; int selRval; int total = 0; // how many bytes we've sent int bytesleft = *len; // how many we have left to send int n = 0; // =0 kvuli warningu while(total < *len) { //printf("total: %d len: %d\n", total, *len); FD_ZERO(&fds); FD_SET(sock, &fds); ms2tv(timeoutMsec, &tv); errno = 0; selRval = select(sock+1, NULL, &fds, NULL, &tv); #ifdef LINUX if (errno == EINTR) { if (thr->isTerminated()) return TcpErrorCode::TERMINATED; continue; // INTERRUPT continue } if (thr->isTerminated()) return TcpErrorCode::TERMINATED; if (selRval == 0) continue; // timeout, terminated check already performed if (selRval < 0) return TcpErrorCode::FAILURE; errno = 0; n = send(sock, buf+total, bytesleft, 0); if (errno == EPIPE || errno == ECONNRESET) return TcpErrorCode::PEER_DISCONNECT; #endif #ifdef WINDOWS if (thr->isTerminated()) return TcpErrorCode::TERMINATED; if (selRval == SOCKET_ERROR) { DWORD gla = GetLastError(); if (gla == WSAEINTR || gla == WSAETIMEDOUT) continue; // INTERRUPT continue // printf(.....); return TcpErrorCode::FAILURE; } n = send(sock, buf+total, bytesleft, 0); if (n == SOCKET_ERROR) { DWORD gla = GetLastError(); if (gla == WSAESHUTDOWN || gla == WSAECONNRESET) return TcpErrorCode::PEER_DISCONNECT; n = -1; // indicate error } #endif if (n == -1) break; total += n; bytesleft -= n; } *len = total; // return number actually sent here return n==-1? (TcpErrorCode::FAILURE):(TcpErrorCode::SUCCESS); }