static ssize_t telnet_socket_read(ZBX_SOCKET socket_fd, void *buf, size_t count) { const char *__function_name = "telnet_socket_read"; ssize_t rc; int error; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); while (ZBX_TCP_ERROR == (rc = ZBX_TCP_READ(socket_fd, buf, count))) { error = zbx_sock_last_error(); /* zabbix_log() resets the error code */ zabbix_log(LOG_LEVEL_DEBUG, "%s() rc:%d errno:%d error:[%s]", __function_name, rc, error, strerror_from_system(error)); #ifdef _WINDOWS if (WSAEWOULDBLOCK == error) #else if (EAGAIN == error) #endif { /* wait and if there is still an error or no input available */ /* we assume the other side has nothing more to say */ if (1 > (rc = telnet_waitsocket(socket_fd, WAIT_READ))) goto ret; continue; } break; } /* when ZBX_TCP_READ returns 0, it means EOF - let's consider it a permanent error */ /* note that if telnet_waitsocket() is zero, it is not a permanent condition */ if (0 == rc) rc = ZBX_TCP_ERROR; ret: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, rc); return rc; }
/****************************************************************************** * * * Function: zbx_tcp_recv_ext * * * * Purpose: receive data * * * * Return value: number of bytes received - success, * * FAIL - an error occurred * * * * Author: Eugene Grigorjev * * * ******************************************************************************/ ssize_t zbx_tcp_recv_ext(zbx_sock_t *s, char **data, unsigned char flags, int timeout) { #define ZBX_BUF_LEN (ZBX_STAT_BUF_LEN * 8) ssize_t nbytes, left, total_bytes; size_t allocated, offset, read_bytes; zbx_uint64_t expected_len; ZBX_TCP_START(); if (0 != timeout) zbx_tcp_timeout_set(s, timeout); zbx_free(s->buf_dyn); total_bytes = 0; read_bytes = 0; s->buf_type = ZBX_BUF_TYPE_STAT; *data = s->buf_stat; left = ZBX_TCP_HEADER_LEN; if (ZBX_TCP_ERROR == (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, left))) goto out; if (ZBX_TCP_HEADER_LEN == nbytes && 0 == strncmp(s->buf_stat, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN)) { total_bytes += nbytes; left = sizeof(zbx_uint64_t); if (left != (nbytes = ZBX_TCP_READ(s->socket, (void *)&expected_len, left))) { total_bytes = FAIL; goto out; } expected_len = zbx_letoh_uint64(expected_len); if (ZBX_MAX_RECV_DATA_SIZE < expected_len) { zabbix_log(LOG_LEVEL_WARNING, "Message size " ZBX_FS_UI64 " from %s" " exceeds the maximum size " ZBX_FS_UI64 " bytes. Message ignored.", expected_len, get_ip_by_socket(s), (zbx_uint64_t)ZBX_MAX_RECV_DATA_SIZE); total_bytes = FAIL; goto cleanup; } flags |= ZBX_TCP_READ_UNTIL_CLOSE; } else { read_bytes = nbytes; expected_len = 16 * ZBX_MEBIBYTE; } s->buf_stat[read_bytes] = '\0'; if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE)) { if (0 == nbytes) goto cleanup; } else { if (nbytes < left) goto cleanup; } left = sizeof(s->buf_stat) - read_bytes - 1; /* check for an empty socket if exactly ZBX_TCP_HEADER_LEN bytes (without a header) were sent */ if (0 == read_bytes || '\n' != s->buf_stat[read_bytes - 1]) /* requests to passive agents end with '\n' */ { /* fill static buffer */ while (read_bytes < expected_len && 0 < left && ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat + read_bytes, left))) { read_bytes += nbytes; if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE)) { if (0 == nbytes) break; } else { if (nbytes < left) /* should we stop reading? */ { /* XML protocol? */ if (0 == strncmp(s->buf_stat, "<req>", sizeof("<req>") - 1)) { /* closing tag received in the last 10 bytes? */ s->buf_stat[read_bytes] = '\0'; if (NULL != strstr(s->buf_stat + read_bytes - (10 > read_bytes ? read_bytes : 10), "</req>")) break; } else break; } } left -= nbytes; } } s->buf_stat[read_bytes] = '\0'; if (sizeof(s->buf_stat) - 1 == read_bytes) /* static buffer is full */ { allocated = ZBX_BUF_LEN; s->buf_type = ZBX_BUF_TYPE_DYN; s->buf_dyn = zbx_malloc(s->buf_dyn, allocated); memcpy(s->buf_dyn, s->buf_stat, sizeof(s->buf_stat)); offset = read_bytes; /* fill dynamic buffer */ while (read_bytes < expected_len && ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, sizeof(s->buf_stat)))) { zbx_strncpy_alloc(&s->buf_dyn, &allocated, &offset, s->buf_stat, nbytes); read_bytes += nbytes; if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE)) { if (0 == nbytes) break; } else { if ((size_t)nbytes < sizeof(s->buf_stat) - 1) /* should we stop reading? */ { /* XML protocol? */ if (0 == strncmp(s->buf_dyn, "<req>", sizeof("<req>") - 1)) { /* closing tag received in the last 10 bytes? */ if (NULL != strstr(s->buf_dyn + read_bytes - 10, "</req>")) break; } else break; } } } *data = s->buf_dyn; } out: if (ZBX_TCP_ERROR == nbytes) { zbx_set_tcp_strerror("ZBX_TCP_READ() failed: %s", strerror_from_system(zbx_sock_last_error())); total_bytes = FAIL; } cleanup: if (0 != timeout) zbx_tcp_timeout_cleanup(s); if (FAIL != total_bytes) total_bytes += read_bytes; return total_bytes; }
/****************************************************************************** * * * Function: zbx_tcp_recv * * * * Purpose: receive data * * * * Parameters: * * * * Return value: SUCCEED - success * * FAIL - an error occurred * * * * Author: Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ int zbx_tcp_recv_ext(zbx_sock_t *s, char **data, unsigned char flags, int timeout) { #define ZBX_BUF_LEN ZBX_STAT_BUF_LEN*8 ssize_t nbytes, left; ssize_t read_bytes; int allocated, offset; int ret = SUCCEED; zbx_uint64_t expected_len; ZBX_TCP_START(); if (0 != timeout) zbx_tcp_timeout_set(s, timeout); zbx_free(s->buf_dyn); memset(s->buf_stat, 0, sizeof(s->buf_stat)); *data = s->buf_stat; read_bytes = 0; s->buf_type = ZBX_BUF_TYPE_STAT; left = ZBX_TCP_HEADER_LEN; nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, left); if( ZBX_TCP_HEADER_LEN == nbytes && 0 == strncmp(s->buf_stat, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN) ) { left = sizeof(zbx_uint64_t); nbytes = ZBX_TCP_READ(s->socket, (void *)&expected_len, left); expected_len = zbx_letoh_uint64(expected_len); /* The rest was already cleared */ memset(s->buf_stat, 0, ZBX_TCP_HEADER_LEN); flags |= ZBX_TCP_READ_UNTIL_CLOSE; } else if( ZBX_TCP_ERROR != nbytes ) { read_bytes = nbytes; expected_len = 16*1024*1024; } if( ZBX_TCP_ERROR != nbytes ) { if( flags & ZBX_TCP_READ_UNTIL_CLOSE ) { if(nbytes == 0) goto cleanup; } else { if(nbytes < left) goto cleanup; } left = sizeof(s->buf_stat) - read_bytes - 1; /* fill static buffer */ if ( s->buf_stat[ read_bytes - 1 ] != '\n' ) /* Don't try to read from an empty socket. */ { while( read_bytes < expected_len && left > 0 && ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ( s->socket, s->buf_stat + read_bytes, left))) { read_bytes += nbytes; if( flags & ZBX_TCP_READ_UNTIL_CLOSE ) { if(nbytes == 0) break; } else { if(nbytes < left) break; } left -= nbytes; } } s->buf_stat[read_bytes] = '\0'; if( (sizeof(s->buf_stat) - 1) == read_bytes) /* static buffer is full */ { allocated = ZBX_BUF_LEN; s->buf_type = ZBX_BUF_TYPE_DYN; s->buf_dyn = zbx_malloc(s->buf_dyn, allocated); memset(s->buf_dyn, 0, allocated); memcpy(s->buf_dyn, s->buf_stat, sizeof(s->buf_stat)); offset = read_bytes; /* fill dynamic buffer */ while( read_bytes < expected_len && ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, sizeof(s->buf_stat)-1)) ) { s->buf_stat[nbytes] = '\0'; zbx_snprintf_alloc(&(s->buf_dyn), &allocated, &offset, sizeof(s->buf_stat), "%s", s->buf_stat); read_bytes += nbytes; if( flags & ZBX_TCP_READ_UNTIL_CLOSE ) { if(nbytes == 0) break; } else { if(nbytes < sizeof(s->buf_stat) - 1) break; } } *data = s->buf_dyn; } } if( ZBX_TCP_ERROR == nbytes ) { zbx_set_tcp_strerror("ZBX_TCP_READ() failed [%s]", strerror_from_system(zbx_sock_last_error())); ret = FAIL; } cleanup: if (0 != timeout) zbx_tcp_timeout_cleanup(s); return ret; }