| 35 | { |
| 36 | |
| 37 | IPCSocketClient::self_reference |
| 38 | IPCSocketClient::connect(std::chrono::milliseconds wait_ms, int attempts) |
| 39 | { |
| 40 | std::string text; |
| 41 | int err, tries{attempts}; |
| 42 | bool done{false}; |
| 43 | _sock = socket(AF_UNIX, SOCK_STREAM, 0); |
| 44 | |
| 45 | if (this->is_closed()) { |
| 46 | throw std::runtime_error(swoc::bwprint(text, "connect: error creating new socket. Reason: {}\n", std::strerror(errno))); |
| 47 | } |
| 48 | |
| 49 | if (safe_fcntl(_sock, F_SETFL, O_NONBLOCK) < 0) { |
| 50 | this->close(); |
| 51 | throw std::runtime_error(swoc::bwprint(text, "connect: fcntl error. Reason: {}\n", std::strerror(errno))); |
| 52 | } |
| 53 | |
| 54 | _server.sun_family = AF_UNIX; |
| 55 | std::strncpy(_server.sun_path, _path.c_str(), sizeof(_server.sun_path) - 1); |
| 56 | |
| 57 | // Very simple connect and retry. We will just try to connect to the Unix Domain |
| 58 | // Socket and if it tell us to retry we just wait for a few ms and try again for |
| 59 | // X times. |
| 60 | do { |
| 61 | --tries; |
| 62 | if (::connect(_sock, (struct sockaddr *)&_server, sizeof(struct sockaddr_un)) >= 0) { |
| 63 | done = true; |
| 64 | break; |
| 65 | } |
| 66 | |
| 67 | if (errno == EAGAIN || errno == EINPROGRESS) { |
| 68 | // Connection cannot be completed immediately |
| 69 | // EAGAIN for UDS should suffice, but just in case. |
| 70 | std::this_thread::sleep_for(wait_ms); |
| 71 | err = errno; |
| 72 | continue; |
| 73 | } else { |
| 74 | // No worth it. |
| 75 | err = errno; |
| 76 | break; |
| 77 | } |
| 78 | } while (tries != 0); |
| 79 | |
| 80 | if ((tries == 0 && !done) || !done) { |
| 81 | this->close(); |
| 82 | errno = err; |
| 83 | throw std::runtime_error(swoc::bwprint(text, "connect(attempts={}/{}): Couldn't open connection with {}. Last error: {}({})\n", |
| 84 | (attempts - tries), attempts, _path, std::strerror(errno), errno)); |
| 85 | } |
| 86 | return *this; |
| 87 | } |
| 88 | |
| 89 | std::int64_t |
| 90 | IPCSocketClient::_safe_write(int fd, const char *buffer, int len) |
nothing calls this directly
no test coverage detected