int m600_read_card(unsigned int count, m600_cardfn_t on_card, void* ctx) { static const m600_request_t req = M600_REQ_READ_CARD; m600_reply_t rep; size_t size; int error; for (; count; --count) { error = serial_write(&handle, &req, sizeof(req), &size); if (error == -1 || size != sizeof(req)) return -1; if (wait_for_read() == -1) return -1; error = serial_readn(&handle, (void*)&rep, sizeof(rep)); if (error == -1) return -1; if (on_card(rep.card_data, rep.alarms, ctx) == -1) break; } return 0; }
Socket *IPv4Socket::accept(bool nonblocking) { //fudeb("Socket::accept(s:%d)", sock_); LOG_DEBUG((use_rs_ ? "RDMA" : "TCP")); int asock = 0; while (!stop_) { if (nonblocking_) { wait_for_read(); } asock = rs_accept(sock_, 0, 0); if (asock >= 0) break; LOG_WARN("accept encountered " << strerror(errno)); if (asock < 0 && errno != EAGAIN && errno != EINTR #ifndef _WIN32 && errno != ECONNABORTED && errno != EPROTO #endif ) { throw IOException("accept", "", getErrorNumber()); } } if (stop_) { return 0; } uint16_t remote_port = 0; char str[INET_ADDRSTRLEN]; struct sockaddr_in clientaddr; socklen_t addrlen = sizeof(clientaddr); int res = rs_getpeername(asock, (struct sockaddr *) &clientaddr, &addrlen); if (res < 0) { throw IOException("Socket::accept() Failed to find peer IP/port", "", res); } char * buf = inet_ntoa(clientaddr.sin_addr); if (buf != 0) { str[0] = 0; #pragma warning( push ) #pragma warning( disable: 4996) // we use strncpy in a safe way strncpy(str, buf, INET_ADDRSTRLEN); #pragma warning( pop ) LOG_DEBUG("IPv4 Client address is " << str); LOG_DEBUG("Client port is " << ntohs(clientaddr.sin_port)); } else { throw IOException( "Socket::accept() Failure to resolve remote peer for accepted connection"); } remote_port = ntohs(clientaddr.sin_port); Socket *asock2 = new IPv4Socket(this, asock, sock_type_, str, remote_port); if (nonblocking) { asock2->setNonBlocking(); } // TODO make sendbuffersize // asock2->setSendbufferssize(32 * 1024); return asock2; }
int m600_read_alarms(m600_alarms_t* alarms) { static const m600_request_t req = M600_REQ_READ_ALARMS; m600_reply_t rep; size_t size; int error; error = serial_write(&handle, &req, sizeof(req), &size); if (error == -1 || size != sizeof(req)) return -1; if (wait_for_read() == -1) return -1; error = serial_readn(&handle, (void*)&rep, sizeof(rep)); if (error == -1) return -1; *alarms = rep.alarms; return 0; }
size_t network::stream_read( network::socket_t const &sockfd, void *buffer, size_t buffer_size, size_t buffer_offset, bool *out_disconnected, int *out_error /* = NULL */) { char *buf = (char*) buffer + buffer_offset; int nba = (int) (buffer_size - buffer_offset); int res = -1; LLSOCKET_SET_ERROR_RESULT(0); if (buffer == NULL || buffer_size == 0 || out_disconnected == NULL || buffer_offset >= buffer_size) { // invalid parameter. return immediately. if (out_disconnected != NULL) *out_disconnected = false; return 0; } // ideally this loop only executes once, but if the OS buffers fill up // we may need to re-try the receive operation multiple times. size_t retry_count = 0; bool try_recv = true; while (try_recv) { if (retry_count >= LLSOCKET_MAX_RETRIES) { // this socket has exceeded its retry count. disconnect it. network::stream_shutdown(sockfd, NULL, NULL); *out_disconnected = true; return 0; } // assume the receive operation will succeed: try_recv = false; // read as much data as possible from the socket: res = recv(sockfd, buf, nba, 0); if (!network::socket_error(res)) { if (res != 0) { *out_disconnected = false; return (size_t) res; } else { // the socket was shutdown gracefully. network::stream_shutdown(sockfd, NULL, NULL); *out_disconnected = true; return 0; } } #if defined(_WIN32) || defined(_WIN64) // an error occurred. try to determine whether we are still connected. int err = WSAGetLastError(); switch (err) { case WSAEWOULDBLOCK: { // no data is available to read on the socket. // this is not actually an error. *out_disconnected = false; } return 0; case WSAENOBUFS: // ENOBUFS { // insufficient resources available in the system to // perform the operation. we'll wait (in select()) for // a bit to see if the socket becomes readable again; // otherwise, the socket is shutdown. if (wait_for_read(sockfd, LLSOCKET_WAIT_TIMEOUT_USEC)) { // the socket is available again. retry. try_recv = true; retry_count++; continue; // back to the loop start } else { // the wait timed out. disconnect the socket. network::stream_shutdown(sockfd, NULL, NULL); LLSOCKET_SET_ERROR_RESULT(err); *out_disconnected = true; } } return 0; case WSANOTINITIALISED: case WSAENETDOWN: case WSAENOTCONN: case WSAENETRESET: case WSAENOTSOCK: case WSAESHUTDOWN: case WSAECONNABORTED: case WSAETIMEDOUT: case WSAECONNRESET: { // we were either never connected, or the connection has // somehow been terminated in a non-graceful way. network::stream_shutdown(sockfd, NULL, NULL); LLSOCKET_SET_ERROR_RESULT(err); *out_disconnected = true; } return 0; default: { // an error occurred; try again. try_recv = true; retry_count++; } break; } #else // an error occurred. try to determine whether we are still connected. int err = errno; switch (err) { case EWOULDBLOCK: { // no data is available to read on the socket. // this is not actually an error. *out_disconnected = false; } return 0; case ENOBUFS: { // insufficient resources available in the system to // perform the operation. we'll wait (in select()) for // a bit to see if the socket becomes readable again; // otherwise, the socket is shutdown. if (wait_for_read(sockfd, LLSOCKET_WAIT_TIMEOUT_USEC)) { // the socket is available again. retry. try_recv = true; retry_count++; continue; // back to the loop start } else { // the wait timed out. disconnect the socket. network::stream_shutdown(sockfd, NULL, NULL); LLSOCKET_SET_ERROR_RESULT(err); *out_disconnected = true; } } return 0; case EBADF: case ECONNRESET: case ENOTCONN: case ENOTSOCK: case ETIMEDOUT: { // we were either never connected, or the connection has // somehow been terminated in a non-graceful way. network::stream_shutdown(sockfd, NULL, NULL); LLSOCKET_SET_ERROR_RESULT(err); *out_disconnected = true; } return 0; default: { // an error occurred; try again. try_recv = true; retry_count++; } break; } #endif } // no data was received. return 0; }