bool Socket::SetNonblocking() { int ret; if (fd < 0) { Log_Trace("SetNonblocking on invalid file descriptor"); return false; } ret = fcntl(fd, F_GETFL, 0); if (ret < 0) { Log_Errno(); return false; } ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK); if (ret < 0) { Log_Errno(); return false; } return true; }
bool Socket::Bind(int port) { int ret; struct sockaddr_in sa; int sockopt; sockopt = 1; ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); if (ret < 0) { Log_Errno(); Close(); return false; } memset(&sa, 0, sizeof(sa)); sa.sin_port = htons((uint16_t)port); sa.sin_addr.s_addr = htonl(INADDR_ANY); ret = bind(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)); if (ret < 0) { Log_Errno(); Close(); return false; } return true; }
int64_t FS_FileSeek(FD fd, uint64_t offset, int whence_) { off_t ret; int whence; whence = -1; switch (whence_) { case FS_SEEK_SET: whence = SEEK_SET; break; case FS_SEEK_CUR: whence = SEEK_CUR; break; case FS_SEEK_END: whence = SEEK_END; break; default: return -1; } ret = lseek(fd, offset, whence); if (ret < 0) Log_Errno("%d", fd); return ret; }
bool Socket::Create(Proto proto_) { int stype; if (fd >= 0) { Log_Trace("Called Create() on existing socket"); return false; } if (proto_ == UDP) stype = SOCK_DGRAM; else stype = SOCK_STREAM; fd = socket(AF_INET, stype, 0); if (fd < 0) { Log_Errno(); return false; } proto = proto_; listening = false; // SetReceiveBufferSize(64*KiB); return true; }
bool AddKq(int ident, short filter, IOOperation* ioop) { int nev; struct kevent ev; struct timespec timeout = { 0, 0 }; if (kq < 0) { Log_Trace("kq < 0"); return false; } EV_SET(&ev, ident, filter, EV_ADD | EV_ONESHOT, 0, 0, ioop); // add our interest in the event nev = kevent(kq, &ev, 1, NULL, 0, &timeout); if (nev < 0) { Log_Errno(); return false; } if (ioop) ioop->active = true; return true; }
void ProcessUDPRead(struct kevent* ev) { int salen, nread; UDPRead* udpread; udpread = (UDPRead*) ev->udata; salen = ENDPOINT_SOCKADDR_SIZE; nread = recvfrom(udpread->fd, udpread->data.buffer, udpread->data.size, 0, (sockaddr*) udpread->endpoint.GetSockAddr(), (socklen_t*)&salen); if (nread < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) IOProcessor::Add(udpread); // try again else Log_Errno(); } else { udpread->data.length = nread; Call(udpread->onComplete); } if (ev->flags & EV_EOF) Call(udpread->onClose); }
void Signal::Wait() { DWORD ret; bool stuck; SetWaiting(true); stuck = false; while (true) { DWORD timeout = 10000; //ret = WaitForSingleObject((HANDLE) impl.event, INFINITE); ret = WaitForSingleObject((HANDLE) impl.event, timeout); if (ret == WAIT_FAILED) Log_Errno(); if (ret != WAIT_OBJECT_0 && ret != WAIT_TIMEOUT) Log_Debug("WaitForSingleObject: ret %d", ret); if (ret == WAIT_TIMEOUT) { if (stuck == false) { //Log_Debug("Waiting for long: %p in %U", this, ThreadPool::GetThreadID()); stuck = true; } continue; } break; } SetWaiting(false); }
ssize_t FS_FileReadOffs(FD fd, void* buf, size_t count, uint64_t offset) { ssize_t ret; ret = pread(fd, buf, count, offset); if (ret < 0) Log_Errno("%d", fd); return ret; }
void FS_CloseDir(FS_Dir dir) { int ret; if ((DIR*) dir == NULL) return; ret = closedir((DIR*) dir); if (ret < 0) Log_Errno(); }
ssize_t FS_FileWriteOffs(FD fd, const void* buf, size_t count, uint64_t offset) { ssize_t ret; dirtyFiles[fd] = true; ret = pwrite(fd, buf, count, offset); if (ret < 0) Log_Errno("%d", fd); return ret; }
bool IOProcessor::Init(int maxfd_) { rlimit rl; if (kq != 0) return true; terminated = false; kq = kqueue(); if (kq < 0) { Log_Errno(); return false; } SetupSignals(); rl.rlim_cur = maxfd_; rl.rlim_max = maxfd_; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { Log_Errno(); } // setup async pipe if (pipe(asyncOpPipe) < 0) { Log_Errno(); return false; } fcntl(asyncOpPipe[0], F_SETFD, FD_CLOEXEC); fcntl(asyncOpPipe[0], F_SETFD, O_NONBLOCK); fcntl(asyncOpPipe[1], F_SETFD, FD_CLOEXEC); if (!AddKq(asyncOpPipe[0], EVFILT_READ, NULL)) return false; return true; }
bool Socket::Accept(Socket *newSocket) { newSocket->fd = accept(fd, NULL, NULL); if (newSocket->fd < 0) { Log_Errno(); Close(); return false; } return true; }
int FS_FileTruncate(FD fd, uint64_t length) { int ret; dirtyFiles[fd] = true; ret = ftruncate(fd, length); if (ret < 0) Log_Errno("%d", fd); return ret; }
bool FS_CreateDir(const char* filename) { int ret; ret = mkdir(filename, S_IRUSR | S_IWUSR | S_IXUSR); if (ret < 0) { Log_Errno("%s", filename); return false; } return true; }
void Signal::Wait() { DWORD ret; SetWaiting(true); ret = WaitForSingleObject((HANDLE) impl.event, INFINITE); if (ret == WAIT_FAILED) Log_Errno(); if (ret != WAIT_OBJECT_0) Log_Debug("WaitForSingleObject: ret %d", ret); SetWaiting(false); }
bool FS_DeleteDir(const char* filename) { int ret; ret = rmdir(filename); if (ret < 0) { Log_Errno("%s", filename); return false; } return true; }
ssize_t FS_FileWrite(FD fd, const void* buf, size_t count) { ssize_t ret; dirtyFiles[fd] = true; ret = write(fd, buf, count); if (ret < 0) Log_Errno("%d", fd); return ret; }
FS_Dir FS_OpenDir(const char* filename) { DIR* dir; dir = opendir(filename); if (dir == NULL) { Log_Errno("%s", filename); return FS_INVALID_DIR; } return (FS_Dir) dir; }
void FS_FileClose(FD fd) { int ret; globalMutex.Lock(); fileHandles.Remove(fd); dirtyFiles[fd] = false; globalMutex.Unlock(); ret = close(fd); if (ret < 0) Log_Errno("%d", fd); }
bool FS_Rename(const char* src, const char* dst) { int ret; ret = rename(src, dst); if (ret < 0) { Log_Errno("src: %s, dst: %s", src, dst); return false; } return true; }
int64_t FS_FileSize(const char* path) { int64_t ret; struct stat buf; ret = stat(path, &buf); if (ret < 0) { Log_Errno("%s", path); return ret; } return buf.st_size; }
int64_t FS_FileSize(FD fd) { int64_t ret; struct stat buf; ret = fstat(fd, &buf); if (ret < 0) { Log_Errno("%d", fd); return ret; } return buf.st_size; }
void Socket::Close() { int ret; if (fd != -1) { ret = close(fd); if (ret < 0) Log_Errno(); fd = -1; } }
void ProcessTCPWrite(struct kevent* ev) { int writelen, nwrite; TCPWrite* tcpwrite; tcpwrite = (TCPWrite*) ev->udata; if (ev->flags & EV_EOF) { Call(tcpwrite->onClose); return; } if (tcpwrite->data.length == 0) { if (ev->flags & EV_EOF) Call(tcpwrite->onClose); else Call(tcpwrite->onComplete); return; } writelen = tcpwrite->data.length - tcpwrite->transferred; writelen = MIN(ev->data, writelen); if (writelen > 0) { nwrite = write(tcpwrite->fd, tcpwrite->data.buffer + tcpwrite->transferred, writelen); if (nwrite < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) IOProcessor::Add(tcpwrite); else if (!(ev->flags & EV_EOF)) Log_Errno(); } else { tcpwrite->transferred += nwrite; if (tcpwrite->transferred == tcpwrite->data.length) Call(tcpwrite->onComplete); else IOProcessor::Add(tcpwrite); } } }
bool IOProcessor::Complete(Callable* callable) { Log_Trace(); int nwrite; nwrite = write(asyncOpPipe[1], &callable, sizeof(Callable*)); if (nwrite < 0) Log_Errno(); if (nwrite >= 0) return true; return false; }
bool Socket::SendTo(void *data, int count, const Endpoint &endpoint) { int ret; const struct sockaddr* sa = (const struct sockaddr*) ((Endpoint&) endpoint).GetSockAddr(); ret = sendto(fd, data, count, 0, sa, ENDPOINT_SOCKADDR_SIZE); if (ret < 0) { Log_Errno(); return false; } return true; }
void ProcessTCPRead(struct kevent* ev) { int readlen, nread; TCPRead* tcpread; tcpread = (TCPRead*) ev->udata; if (tcpread->listening) { Call(tcpread->onComplete); } else { if (tcpread->requested == IO_READ_ANY) readlen = tcpread->data.size - tcpread->data.length; else readlen = tcpread->requested - tcpread->data.length; readlen = MIN(ev->data, readlen); if (readlen > 0) { nread = read(tcpread->fd, tcpread->data.buffer + tcpread->data.length, readlen); if (nread < 0) { if (errno == EWOULDBLOCK || errno == EAGAIN) IOProcessor::Add(tcpread); else if (!(ev->flags & EV_EOF)) Log_Errno(); } else { tcpread->data.length += nread; if (tcpread->requested == IO_READ_ANY || (int) tcpread->data.length == tcpread->requested) Call(tcpread->onComplete); else IOProcessor::Add(tcpread); } } if (ev->flags & EV_EOF) Call(tcpread->onClose); } }
bool Socket::GetEndpoint(Endpoint &endpoint) { int ret; struct sockaddr* sa = (struct sockaddr*) endpoint.GetSockAddr(); socklen_t len = ENDPOINT_SOCKADDR_SIZE; ret = getpeername(fd, sa, &len); if (ret < 0) { Log_Errno(); Close(); return false; } return true; }
bool Socket::Connect(Endpoint &endpoint) { int ret; struct sockaddr* sa = (struct sockaddr*) endpoint.GetSockAddr(); ret = connect(fd, sa, ENDPOINT_SOCKADDR_SIZE); if (ret < 0) { if (errno != EINPROGRESS) { Log_Errno(); return false; } } return true; }
bool IOProcessor::Remove(IOOperation* ioop) { short filter; int nev; struct kevent ev; struct timespec timeout = { 0, 0 }; if (!ioop->active) return true; if (ioop->pending) { ioop->active = false; return true; } if (kq < 0) { Log_Trace("kq < 0"); return false; } if (ioop->type == TCP_READ || ioop->type == UDP_READ) filter = EVFILT_READ; else filter = EVFILT_WRITE; EV_SET(&ev, ioop->fd, filter, EV_DELETE, 0, 0, 0); // delete event nev = kevent(kq, &ev, 1, NULL, 0, &timeout); if (nev < 0) { Log_Errno(); // HACK: ioop->active = false; return false; } ioop->active = false; return true; }