summaryrefslogtreecommitdiffstats
path: root/exporting
diff options
context:
space:
mode:
Diffstat (limited to 'exporting')
-rw-r--r--exporting/README.md2
-rw-r--r--exporting/WALKTHROUGH.md17
-rw-r--r--exporting/clean_connectors.c5
-rw-r--r--exporting/exporting_engine.c2
-rw-r--r--exporting/exporting_engine.h3
-rw-r--r--exporting/graphite/graphite.c5
-rw-r--r--exporting/json/json.c5
-rw-r--r--exporting/opentsdb/opentsdb.c10
-rw-r--r--exporting/prometheus/prometheus.c85
-rw-r--r--exporting/prometheus/remote_write/remote_write.c5
-rw-r--r--exporting/prometheus/remote_write/remote_write_request.cc16
-rw-r--r--exporting/send_data.c105
12 files changed, 132 insertions, 128 deletions
diff --git a/exporting/README.md b/exporting/README.md
index c6ce32b65..013f86f32 100644
--- a/exporting/README.md
+++ b/exporting/README.md
@@ -284,7 +284,7 @@ Configure individual connectors and override any global settings with the follow
and names are human friendly labels (also unique). Most charts and metrics have the same ID and name, but in several
cases they are different: disks with device-mapper, interrupts, QoS classes, statsd synthetic charts, etc.
-- `send configured labels = yes | no` controls if labels defined in the `[host labels]` section in `netdata.conf`
+- `send configured labels = yes | no` controls if host labels defined in the `[host labels]` section in `netdata.conf`
should be sent to the external database
- `send automatic labels = yes | no` controls if automatically created labels, like `_os_name` or `_architecture`
diff --git a/exporting/WALKTHROUGH.md b/exporting/WALKTHROUGH.md
index 49cf6587b..86be758e4 100644
--- a/exporting/WALKTHROUGH.md
+++ b/exporting/WALKTHROUGH.md
@@ -74,10 +74,10 @@ this is your first time using Netdata I suggest you take a look around. The amou
Next I want to draw your attention to a particular endpoint. Navigate to
<http://localhost:19999/api/v1/allmetrics?format=prometheus&help=yes> In your browser. This is the endpoint which
publishes all the metrics in a format which Prometheus understands. Let's take a look at one of these metrics.
-`netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} 0.0831255 1501271696000` This
-metric is representing several things which I will go in more details in the section on Prometheus. For now understand
-that this metric: `netdata_system_cpu_percentage_average` has several labels: (`chart`, `family`, `dimension`). This
-corresponds with the first cpu chart you see on the Netdata dashboard.
+`netdata_disk_space_GiB_average{chart="disk_space._run",dimension="avail",family="/run",mount_point="/run",filesystem="tmpfs",mount_root="/"} 0.0298195 1684951093000`
+This metric is representing several things which I will go in more details in the section on Prometheus. For now understand
+that this metric: `netdata_disk_space_GiB_average` has several labels: (`chart`, `family`, `dimension`, `mountt_point`, `filesystem`, `mount_root`).
+This corresponds with disk space you see on the Netdata dashboard.
![](https://github.com/ldelossa/NetdataTutorial/raw/master/Screen%20Shot%202017-07-28%20at%204.00.45%20PM.png)
@@ -138,12 +138,13 @@ As explained we have two key elements in Prometheus metrics. We have the _metric
granularity between metrics. Let's use our previous example to further explain.
```conf
-netdata_system_cpu_percentage_average{chart="system.cpu",family="cpu",dimension="system"} 0.0831255 1501271696000
+netdata_disk_space_GiB_average{chart="disk_space._run",dimension="avail",family="/run",mount_point="/run",filesystem="tmpfs",mount_root="/"} 0.0298195 1684951093000
```
-Here our metric is `netdata_system_cpu_percentage_average` and our labels are `chart`, `family`, and `dimension`. The
-last two values constitute the actual metric value for the metric type (gauge, counter, etc…). We can begin graphing
-system metrics with this information, but first we need to hook up Prometheus to poll Netdata stats.
+Here our metric is `netdata_disk_space_GiB_average` and our common labels are `chart`, `family`, and `dimension`. The
+last two values constitute the actual metric value for the metric type (gauge, counter, etc…). We also have specific
+label for this chart named `mount_point`,`filesystem`, and `mount_root`. We can begin graphing system metrics with this information,
+but first we need to hook up Prometheus to poll Netdata stats.
Let's move our attention to Prometheus's configuration. Prometheus gets it config from the file located (in our example)
at `/opt/prometheus/prometheus.yml`. I won't spend an extensive amount of time going over the configuration values
diff --git a/exporting/clean_connectors.c b/exporting/clean_connectors.c
index e93563741..ab1fb5dd7 100644
--- a/exporting/clean_connectors.c
+++ b/exporting/clean_connectors.c
@@ -68,8 +68,7 @@ void simple_connector_cleanup(struct instance *instance)
}
#ifdef ENABLE_HTTPS
- if (simple_connector_data->conn)
- SSL_free(simple_connector_data->conn);
+ netdata_ssl_close(&simple_connector_data->ssl);
#endif
freez(simple_connector_data);
@@ -80,6 +79,4 @@ void simple_connector_cleanup(struct instance *instance)
info("EXPORTING: instance %s exited", instance->config.name);
instance->exited = 1;
-
- return;
}
diff --git a/exporting/exporting_engine.c b/exporting/exporting_engine.c
index 2ad8cdd96..8f957c7c5 100644
--- a/exporting/exporting_engine.c
+++ b/exporting/exporting_engine.c
@@ -10,7 +10,7 @@ void analytics_exporting_connectors_ssl(BUFFER *b)
if (netdata_ssl_exporting_ctx) {
for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
struct simple_connector_data *connector_specific_data = instance->connector_specific_data;
- if (connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
+ if (SSL_connection(&connector_specific_data->ssl)) {
buffer_strcat(b, "exporting");
break;
}
diff --git a/exporting/exporting_engine.h b/exporting/exporting_engine.h
index 5f961c303..c04bbeec3 100644
--- a/exporting/exporting_engine.h
+++ b/exporting/exporting_engine.h
@@ -126,8 +126,7 @@ struct simple_connector_data {
struct simple_connector_buffer *last_buffer;
#ifdef ENABLE_HTTPS
- SSL *conn; //SSL connection
- int flags; //The flags for SSL connection
+ NETDATA_SSL ssl;
#endif
};
diff --git a/exporting/graphite/graphite.c b/exporting/graphite/graphite.c
index f1964f3e5..3aff24926 100644
--- a/exporting/graphite/graphite.c
+++ b/exporting/graphite/graphite.c
@@ -20,10 +20,9 @@ int init_graphite_instance(struct instance *instance)
instance->connector_specific_data = connector_specific_data;
#ifdef ENABLE_HTTPS
- connector_specific_data->flags = NETDATA_SSL_START;
- connector_specific_data->conn = NULL;
+ connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
- security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
+ netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
}
#endif
diff --git a/exporting/json/json.c b/exporting/json/json.c
index 4cafd4c04..edbb98ef6 100644
--- a/exporting/json/json.c
+++ b/exporting/json/json.c
@@ -71,10 +71,9 @@ int init_json_http_instance(struct instance *instance)
instance->connector_specific_data = connector_specific_data;
#ifdef ENABLE_HTTPS
- connector_specific_data->flags = NETDATA_SSL_START;
- connector_specific_data->conn = NULL;
+ connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
- security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
+ netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
}
#endif
diff --git a/exporting/opentsdb/opentsdb.c b/exporting/opentsdb/opentsdb.c
index fc01ae461..0248469fa 100644
--- a/exporting/opentsdb/opentsdb.c
+++ b/exporting/opentsdb/opentsdb.c
@@ -21,10 +21,9 @@ int init_opentsdb_telnet_instance(struct instance *instance)
instance->connector_specific_data = connector_specific_data;
#ifdef ENABLE_HTTPS
- connector_specific_data->flags = NETDATA_SSL_START;
- connector_specific_data->conn = NULL;
+ connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
- security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
+ netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
}
#endif
@@ -77,10 +76,9 @@ int init_opentsdb_http_instance(struct instance *instance)
struct simple_connector_data *connector_specific_data = callocz(1, sizeof(struct simple_connector_data));
#ifdef ENABLE_HTTPS
- connector_specific_data->flags = NETDATA_SSL_START;
- connector_specific_data->conn = NULL;
+ connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
- security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
+ netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
}
#endif
instance->connector_specific_data = connector_specific_data;
diff --git a/exporting/prometheus/prometheus.c b/exporting/prometheus/prometheus.c
index 24bd215f4..0e0e8abf0 100644
--- a/exporting/prometheus/prometheus.c
+++ b/exporting/prometheus/prometheus.c
@@ -326,6 +326,53 @@ void format_host_labels_prometheus(struct instance *instance, RRDHOST *host)
rrdlabels_walkthrough_read(host->rrdlabels, format_prometheus_label_callback, &tmp);
}
+/**
+ * Format host labels for the Prometheus exporter
+ * We are using a structure instead a direct buffer to expand options quickly.
+ *
+ * @param labels_buffer is the buffer used to add labels.
+ */
+
+struct format_prometheus_chart_label_callback {
+ BUFFER *labels_buffer;
+};
+
+static int format_prometheus_chart_label_callback(const char *name, const char *value, RRDLABEL_SRC ls, void *data) {
+ struct format_prometheus_chart_label_callback *d = (struct format_prometheus_chart_label_callback *)data;
+
+ (void)ls;
+
+ if (name[0] == '_' )
+ return 1;
+
+ char k[PROMETHEUS_ELEMENT_MAX + 1];
+ char v[PROMETHEUS_ELEMENT_MAX + 1];
+
+ prometheus_name_copy(k, name, PROMETHEUS_ELEMENT_MAX);
+ prometheus_label_copy(v, value, PROMETHEUS_ELEMENT_MAX);
+
+ if (*k && *v) {
+ buffer_sprintf(d->labels_buffer, ",%s=\"%s\"", k, v);
+ }
+ return 1;
+}
+
+void format_chart_labels_prometheus(struct format_prometheus_chart_label_callback *plabel,
+ const char *chart,
+ const char *family,
+ const char *dim,
+ RRDSET *st)
+{
+ if (likely(plabel->labels_buffer))
+ buffer_reset(plabel->labels_buffer);
+ else {
+ plabel->labels_buffer = buffer_create(1024, NULL);
+ }
+ buffer_sprintf(plabel->labels_buffer, "chart=\"%s\",dimension=\"%s\",family=\"%s\"", chart, dim, family);
+
+ rrdlabels_walkthrough_read(st->rrdlabels, format_prometheus_chart_label_callback, plabel);
+}
+
struct host_variables_callback_options {
RRDHOST *host;
BUFFER *wb;
@@ -462,19 +509,31 @@ static void generate_as_collected_prom_help(BUFFER *wb, struct gen_parameters *p
* @param p parameters for generating the metric string.
* @param homogeneous a flag for homogeneous charts.
* @param prometheus_collector a flag for metrics from prometheus collector.
+ * @param chart_labels the dictionary with chart labels
*/
-static void generate_as_collected_prom_metric(BUFFER *wb, struct gen_parameters *p, int homogeneous, int prometheus_collector)
+static void generate_as_collected_prom_metric(BUFFER *wb,
+ struct gen_parameters *p,
+ int homogeneous,
+ int prometheus_collector,
+ DICTIONARY *chart_labels)
{
+ struct format_prometheus_chart_label_callback local_label;
+ local_label.labels_buffer = wb;
+
buffer_sprintf(wb, "%s_%s", p->prefix, p->context);
if (!homogeneous)
buffer_sprintf(wb, "_%s", p->dimension);
- buffer_sprintf(wb, "%s{chart=\"%s\",family=\"%s\"", p->suffix, p->chart, p->family);
+ buffer_sprintf(wb, "%s{chart=\"%s\"", p->suffix, p->chart);
if (homogeneous)
buffer_sprintf(wb, ",dimension=\"%s\"", p->dimension);
+ buffer_sprintf(wb, ",family=\"%s\"", p->family);
+
+ rrdlabels_walkthrough_read(chart_labels, format_prometheus_chart_label_callback, &local_label);
+
buffer_sprintf(wb, "%s} ", p->labels);
if (prometheus_collector)
@@ -564,6 +623,10 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
// for each chart
RRDSET *st;
+
+ static struct format_prometheus_chart_label_callback plabels = {
+ .labels_buffer = NULL,
+ };
rrdset_foreach_read(st, host) {
if (likely(can_send_rrdset(instance, st, filter))) {
@@ -655,7 +718,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
buffer_sprintf(wb, "# TYPE %s_%s%s %s\n", prefix, context, suffix, p.type);
- generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector);
+ generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector, st->rrdlabels);
}
else {
// the dimensions of the chart, do not have the same algorithm, multiplier or divisor
@@ -673,7 +736,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
buffer_sprintf(
wb, "# TYPE %s_%s_%s%s %s\n", prefix, context, dimension, suffix, p.type);
- generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector);
+ generate_as_collected_prom_metric(wb, &p, homogeneous, prometheus_collector, st->rrdlabels);
}
}
else {
@@ -694,6 +757,8 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
(output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rrddim_name(rd) : rrddim_id(rd),
PROMETHEUS_ELEMENT_MAX);
+ format_chart_labels_prometheus(&plabels, chart, family, dimension, st);
+
if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
buffer_sprintf(
wb,
@@ -713,30 +778,26 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(
if (output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
buffer_sprintf(
wb,
- "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " NETDATA_DOUBLE_FORMAT
+ "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT
" %llu\n",
prefix,
context,
units,
suffix,
- chart,
- family,
- dimension,
+ buffer_tostring(plabels.labels_buffer),
labels,
value,
last_time * MSEC_PER_SEC);
else
buffer_sprintf(
wb,
- "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " NETDATA_DOUBLE_FORMAT
+ "%s_%s%s%s{%s%s} " NETDATA_DOUBLE_FORMAT
"\n",
prefix,
context,
units,
suffix,
- chart,
- family,
- dimension,
+ buffer_tostring(plabels.labels_buffer),
labels,
value);
}
diff --git a/exporting/prometheus/remote_write/remote_write.c b/exporting/prometheus/remote_write/remote_write.c
index 1857ca333..660b798e4 100644
--- a/exporting/prometheus/remote_write/remote_write.c
+++ b/exporting/prometheus/remote_write/remote_write.c
@@ -115,10 +115,9 @@ int init_prometheus_remote_write_instance(struct instance *instance)
instance->connector_specific_data = simple_connector_data;
#ifdef ENABLE_HTTPS
- simple_connector_data->flags = NETDATA_SSL_START;
- simple_connector_data->conn = NULL;
+ simple_connector_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
- security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
+ netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
}
#endif
diff --git a/exporting/prometheus/remote_write/remote_write_request.cc b/exporting/prometheus/remote_write/remote_write_request.cc
index ecfa11fa8..a628082d1 100644
--- a/exporting/prometheus/remote_write/remote_write_request.cc
+++ b/exporting/prometheus/remote_write/remote_write_request.cc
@@ -45,16 +45,16 @@ void add_host_info(
label->set_name("__name__");
label->set_value(name);
- label = timeseries->add_labels();
- label->set_name("instance");
- label->set_value(instance);
-
if (application) {
label = timeseries->add_labels();
label->set_name("application");
label->set_value(application);
}
+ label = timeseries->add_labels();
+ label->set_name("instance");
+ label->set_value(instance);
+
if (version) {
label = timeseries->add_labels();
label->set_name("version");
@@ -118,10 +118,6 @@ void add_metric(
label->set_name("chart");
label->set_value(chart);
- label = timeseries->add_labels();
- label->set_name("family");
- label->set_value(family);
-
if (dimension) {
label = timeseries->add_labels();
label->set_name("dimension");
@@ -129,6 +125,10 @@ void add_metric(
}
label = timeseries->add_labels();
+ label->set_name("family");
+ label->set_value(family);
+
+ label = timeseries->add_labels();
label->set_name("instance");
label->set_value(instance);
diff --git a/exporting/send_data.c b/exporting/send_data.c
index 045aab6ed..d91fc50d7 100644
--- a/exporting/send_data.c
+++ b/exporting/send_data.c
@@ -81,37 +81,11 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
while (*sock != -1 && errno != EWOULDBLOCK) {
ssize_t r;
#ifdef ENABLE_HTTPS
- if (exporting_tls_is_enabled(instance->config.type, options) &&
- connector_specific_data->conn &&
- connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
- r = (ssize_t)SSL_read(connector_specific_data->conn,
- &response->buffer[response->len],
- (int) (response->size - response->len));
-
- if (likely(r > 0)) {
- // we received some data
- response->len += r;
- stats->received_bytes += r;
- stats->receptions++;
- continue;
- } else {
- int sslerrno = SSL_get_error(connector_specific_data->conn, (int) r);
- u_long sslerr = ERR_get_error();
- char buf[256];
- switch (sslerrno) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- goto endloop;
- default:
- ERR_error_string_n(sslerr, buf, sizeof(buf));
- error("SSL error (%s)",
- ERR_error_string((long)SSL_get_error(connector_specific_data->conn, (int)r), NULL));
- goto endloop;
- }
- }
- } else {
+ if (SSL_connection(&connector_specific_data->ssl))
+ r = netdata_ssl_read(&connector_specific_data->ssl, &response->buffer[response->len],
+ (int) (response->size - response->len));
+ else
r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
- }
#else
r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
#endif
@@ -120,11 +94,13 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
response->len += r;
stats->received_bytes += r;
stats->receptions++;
- } else if (r == 0) {
+ }
+ else if (r == 0) {
error("EXPORTING: '%s' closed the socket", instance->config.destination);
close(*sock);
*sock = -1;
- } else {
+ }
+ else {
// failed to receive data
if (errno != EAGAIN && errno != EWOULDBLOCK) {
error("EXPORTING: cannot receive data from '%s'.", instance->config.destination);
@@ -135,9 +111,6 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
break;
#endif
}
-#ifdef ENABLE_HTTPS
-endloop:
-#endif
// if we received data, process them
if (buffer_strlen(response))
@@ -174,14 +147,16 @@ void simple_connector_send_buffer(
size_t buffer_len = buffer_strlen(buffer);
#ifdef ENABLE_HTTPS
- if (exporting_tls_is_enabled(instance->config.type, options) &&
- connector_specific_data->conn &&
- connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
+ if (SSL_connection(&connector_specific_data->ssl)) {
+
if (header_len)
- header_sent_bytes = (ssize_t)SSL_write(connector_specific_data->conn, buffer_tostring(header), header_len);
+ header_sent_bytes = netdata_ssl_write(&connector_specific_data->ssl, buffer_tostring(header), header_len);
+
if ((size_t)header_sent_bytes == header_len)
- buffer_sent_bytes = (ssize_t)SSL_write(connector_specific_data->conn, buffer_tostring(buffer), buffer_len);
- } else {
+ buffer_sent_bytes = netdata_ssl_write(&connector_specific_data->ssl, buffer_tostring(buffer), buffer_len);
+
+ }
+ else {
if (header_len)
header_sent_bytes = send(*sock, buffer_tostring(header), header_len, flags);
if ((size_t)header_sent_bytes == header_len)
@@ -326,43 +301,19 @@ void simple_connector_worker(void *instance_p)
if (sock_delnonblock(sock) < 0)
error("Exporting cannot remove the non-blocking flag from socket %d", sock);
- if (connector_specific_data->conn == NULL) {
- connector_specific_data->conn = SSL_new(netdata_ssl_exporting_ctx);
- if (connector_specific_data->conn == NULL) {
- error("Failed to allocate SSL structure to socket %d.", sock);
- connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
- }
- } else {
- SSL_clear(connector_specific_data->conn);
- }
+ if(netdata_ssl_open(&connector_specific_data->ssl, netdata_ssl_exporting_ctx, sock)) {
+ if(netdata_ssl_connect(&connector_specific_data->ssl)) {
+ info("Exporting established a SSL connection.");
+
+ struct timeval tv;
+ tv.tv_sec = timeout.tv_sec / 4;
+ tv.tv_usec = 0;
+
+ if (!tv.tv_sec)
+ tv.tv_sec = 2;
- if (connector_specific_data->conn) {
- if (SSL_set_fd(connector_specific_data->conn, sock) != 1) {
- error("Failed to set the socket to the SSL on socket fd %d.", sock);
- connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
- } else {
- connector_specific_data->flags = NETDATA_SSL_HANDSHAKE_COMPLETE;
- SSL_set_connect_state(connector_specific_data->conn);
- int err = SSL_connect(connector_specific_data->conn);
- if (err != 1) {
- err = SSL_get_error(connector_specific_data->conn, err);
- error(
- "SSL cannot connect with the server: %s ",
- ERR_error_string((long)SSL_get_error(connector_specific_data->conn, err), NULL));
- connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
- } else {
- info("Exporting established a SSL connection.");
-
- struct timeval tv;
- tv.tv_sec = timeout.tv_sec / 4;
- tv.tv_usec = 0;
-
- if (!tv.tv_sec)
- tv.tv_sec = 2;
-
- if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)))
- error("Cannot set timeout to socket %d, this can block communication", sock);
- }
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)))
+ error("Cannot set timeout to socket %d, this can block communication", sock);
}
}
}