AsyncStatus asyncConnector_run(AsyncConnector* ac) { switch (ac->state) { case CONNECT_ERROR: errno = ac->error; return ASYNC_ERROR; case CONNECT_CONNECTING: loopIo_dontWantWrite(ac->io); /* We need to read the socket error to determine if * the connection was really succesful or not. This * is optional, because in case of error a future * socket_recv() or socket_send() will fail anyway, but this * allows us to get a better error value as soon as * possible. */ ac->error = socket_get_error(ac->io->fd); if (ac->error == 0) { ac->state = CONNECT_COMPLETED; return ASYNC_COMPLETE; } ac->state = CONNECT_ERROR; errno = ac->error; return ASYNC_ERROR; default: return ASYNC_COMPLETE; } }
GError* gridd_client_step(struct client_s *client) { struct pollfd pfd = {-1, 0, 0}; if (!_client_to_pollfd(client, &pfd)) { return NULL; } int rc = metautils_syscall_poll(&pfd, 1, 1000); if (rc == 0) { GTimeVal now; g_get_current_time(&now); gridd_client_expire(client, &now); return NULL; } if (rc < 0) return NEWERROR(errno, "poll errno=%d %s", errno, strerror(errno)); if (pfd.revents & POLLERR) { GError *err = socket_get_error(pfd.fd); g_prefix_error(&err, "%s: ", gridd_client_url(client)); gridd_client_fail(client, err); g_clear_error(&err); } else gridd_client_react(client); return NULL; }
GError* gridd_client_step(struct gridd_client_s *client) { int rc; struct pollfd pfd = {-1, 0, 0}; if (!_client_to_pollfd(client, &pfd)) return NULL; retry: rc = metautils_syscall_poll(&pfd, 1, 1000); if (rc == 0) { gridd_client_expire(client, oio_ext_monotonic_time ()); return NULL; } if (rc < 0) { if (errno == EINTR) goto retry; return NEWERROR(errno, "poll errno=%d %s", errno, strerror(errno)); } if (pfd.revents & POLLERR) { GError *err = socket_get_error(pfd.fd); g_prefix_error(&err, "%s: ", gridd_client_url(client)); gridd_client_fail(client, err); g_clear_error(&err); } else if (pfd.revents & (POLLIN|POLLOUT)) { gridd_client_react(client); } return NULL; }
static void tcp_wait_for_connect(void *opaque) { FdMigrationState *s = opaque; int ret; dprintf("connect completed\n"); ret = socket_get_error(s->fd); if (ret < 0) { dprintf("error connecting %d\n", val); migrate_fd_error(s); return; } qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); migrate_fd_connect(s); }
int Socket::read(char* buffer, int nbytes) { int err; int r; int chunk_size = 1024; if (NULL == buffer) { RX_ERROR("Trying to read into NULL buffer."); return -1; } if (0 == nbytes) { RX_ERROR("Buffer size is 0. No way we can read into that."); return -2; } if (0 != isConnected()) { return -3; } r = recv(handle, buffer, nbytes, 0); if (r < 0) { err = socket_get_error(); if (0 == socket_is_recoverable_error(err)) { return 0; } RX_ERROR("Could not read data from socket: %s", strerror(errno)); close(); return -4; } if (0 == r) { close(); return -5; } // if (NULL != listener) { // listener->onSocketRead(buffer, r); // } return r; }
int Socket::close() { /* Already closed? */ if (0 != isConnected()) { return 0; } /* Close */ if (-1 != handle) { errno = EINTR; #if defined(_WIN32) int result = -1; int err = 0; do { result = ::closesocket(handle); handle = -1; /* event when closesocket returns < 0, we unset the handle so we can reuse it. */ if (0 != result) { err = socket_get_error(); switch(err) { case WSANOTINITIALISED: { RX_ERROR("Socket not initialized."); return 0; } case WSAENETDOWN: { RX_ERROR("Network is down. Socket closed"); return 0; } case WSAENOTSOCK: { RX_ERROR("The `sock` member is not a real socket. This is not supposed to happen but occurs when connect() fails."); return 0; } case WSAEINPROGRESS: { RX_VERBOSE("We're in the process of closing the socket; continuing."); return 0; } case WSAEINTR: { RX_VERBOSE("Call was interrupted."); return 0; } case WSAEWOULDBLOCK: { RX_ERROR("WSAWOULDBLOCK"); return 0; } default: { RX_ERROR("Unhandled error in close(), error: %d", err); return 0; } } } } while (0 != result); #else while (::close(handle) != 0 && EINTR == errno) { } #endif handle = -1; } return 0; }
int Socket::send(const char* data, int nbytes) { int err = 0; int done = 0; if (NULL == data) { RX_ERROR("Trying to send NULL data."); return -1; } if (0 == nbytes) { RX_ERROR("Trying to send 0 bytes."); return -2; } if (0 != isConnected()) { RX_ERROR("Cannot send because we're not connected."); return -3; } while (nbytes > 0 && 0 == isConnected()) { #if defined(_WIN32) done = ::send(handle, (const char*) data, nbytes, 0); #else done = ::send(handle, (const void*) data, nbytes, 0); #endif if (done != nbytes) { /* @todo implement the situation where we couldn't send all bytes. */ RX_ERROR("Failed to send all bytes, this is a situation we need to handle correctly. We sent: %d, but should: %lu.", done, nbytes); err = socket_get_error(); if (0 == socket_is_recoverable_error(err)) { RX_ERROR("The error is recoverable."); return -4; } else { close(); return -5; } } if (done < 0) { err = socket_get_error(); if (0 == socket_is_recoverable_error(err)) { return 0; } RX_ERROR("Error while sending data over socket: %s", strerror(errno)); if (0 != close()) { RX_ERROR("Failed to cleanly close the socket after being disconnected."); } if (NULL != listener) { listener->onSocketDisconnected(); } return -3; } nbytes -= done; } return 0; }
GError * gridd_clients_step(struct client_s **clients) { struct client_s ** _lookup_client(int fd, struct client_s **ppc) { struct client_s *c; for (; (c = *ppc) ;ppc++) { if (gridd_client_fd(c) == fd) return ppc; } return ppc; } guint i, j; int rc; struct client_s *last, **plast; GTimeVal now; guint nbclients; EXTRA_ASSERT(clients != NULL); nbclients = g_strv_length((gchar**)clients); EXTRA_ASSERT(nbclients > 0); struct pollfd pfd[nbclients]; for (j=0,plast=clients; NULL != (last = *plast) ;plast++) { if (_client_to_pollfd(last, pfd+j)) j++; } if (!j) return NULL; /* Wait for an event to happen */ if (!(rc = poll(pfd, j, 100))) { g_get_current_time(&now); _clients_expire(clients, &now); return NULL; } if (rc < 0) return NEWERROR(errno, "poll error (%s)", strerror(errno)); /* Then manage each event */ for (plast=clients,i=0; i<j ;i++) { if (!pfd[i].revents) continue; /* Find the client for this pollfd */ plast = _lookup_client(pfd[i].fd, plast); EXTRA_ASSERT(plast != NULL); last = *plast; /* Manage the poll() event */ if (pfd[i].revents & POLLERR) { GError *err = socket_get_error(pfd[i].fd); g_prefix_error(&err, "%s: ", gridd_client_url(last)); gridd_client_fail(last, err); g_clear_error(&err); } else gridd_client_react(last); } /* Now check for expired clients */ g_get_current_time(&now); _clients_expire(clients, &now); return NULL; }