X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fteamspeak2.c;h=502145d36dc89bd459be4f32636da13747510665;hb=61a1fa91ba73e4fe3a34949f77c5f017056f2b7a;hp=e258645badd746e7c26c5fa6ba6bb61d1a1ba385;hpb=77a43aa53ab0a829a77499b85d78a8b67ec504b2;p=collectd.git diff --git a/src/teamspeak2.c b/src/teamspeak2.c index e258645b..502145d3 100644 --- a/src/teamspeak2.c +++ b/src/teamspeak2.c @@ -115,7 +115,8 @@ static int tss2_add_vserver (int vserver_port) return (0); } /* int tss2_add_vserver */ -static void tss2_submit_gauge (const char *plugin_instance, const char *type, +static void tss2_submit_gauge (const char *plugin_instance, + const char *type, const char *type_instance, gauge_t value) { /* @@ -128,15 +129,20 @@ static void tss2_submit_gauge (const char *plugin_instance, const char *type, vl.values = values; vl.values_len = 1; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin)); if (plugin_instance != NULL) sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + + sstrncpy (vl.type, type, sizeof (vl.type)); + + if (type_instance != NULL) + sstrncpy (vl.type_instance, type_instance, + sizeof (vl.type_instance)); - plugin_dispatch_values (type, &vl); + plugin_dispatch_values (&vl); } /* void tss2_submit_gauge */ static void tss2_submit_io (const char *plugin_instance, const char *type, @@ -153,15 +159,16 @@ static void tss2_submit_io (const char *plugin_instance, const char *type, vl.values = values; vl.values_len = 2; - vl.time = time (NULL); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin)); if (plugin_instance != NULL) sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); - - plugin_dispatch_values (type, &vl); + + sstrncpy (vl.type, type, sizeof (vl.type)); + + plugin_dispatch_values (&vl); } /* void tss2_submit_gauge */ static void tss2_close_socket (void) @@ -292,6 +299,13 @@ static int tss2_get_socket (FILE **ret_read_fh, FILE **ret_write_fh) char *buffer_ptr; buffer_ptr = fgets (buffer, sizeof (buffer), global_read_fh); + if (buffer_ptr == NULL) + { + WARNING ("teamspeak2 plugin: Unexpected EOF received " + "from remote host %s:%s.", + config_host ? config_host : DEFAULT_HOST, + config_port ? config_port : DEFAULT_PORT); + } buffer[sizeof (buffer) - 1] = 0; if (memcmp ("[TS]\r\n", buffer, 6) != 0) @@ -366,11 +380,8 @@ static int tss2_select_vserver (FILE *read_fh, FILE *write_fh, vserver_list_t *v char response[128]; int status; - DEBUG("teamspeak2 plugin: Select server %i", vserver->port); - /* Send request */ - snprintf (command, sizeof (command), "sel %i\r\n", vserver->port); - command[sizeof (command) - 1] = 0; + ssnprintf (command, sizeof (command), "sel %i\r\n", vserver->port); status = tss2_send_request (write_fh, command); if (status != 0) @@ -386,10 +397,10 @@ static int tss2_select_vserver (FILE *read_fh, FILE *write_fh, vserver_list_t *v ERROR ("teamspeak2 plugin: tss2_receive_line failed."); return (-1); } - response[sizeof (response)] = 0; + response[sizeof (response) - 1] = 0; /* Check answer */ - if ((strncmp ("OK", response, 2) == 0) + if ((strncasecmp ("OK", response, 2) == 0) && ((response[2] == 0) || (response[2] == '\n') || (response[2] == '\r'))) @@ -401,15 +412,104 @@ static int tss2_select_vserver (FILE *read_fh, FILE *write_fh, vserver_list_t *v return (-1); } /* int tss2_select_vserver */ +static int tss2_vserver_gapl (FILE *read_fh, FILE *write_fh, + gauge_t *ret_value) +{ + /* + * Reads the vserver's average packet loss and submits it to collectd. + * Be sure to run the tss2_read_vserver function before calling this so + * the vserver is selected correctly. + */ + gauge_t packet_loss = NAN; + int status; + + status = tss2_send_request (write_fh, "gapl\r\n"); + if (status != 0) + { + ERROR("teamspeak2 plugin: tss2_send_request (gapl) failed."); + return (-1); + } + + while (42) + { + char buffer[4096]; + char *value; + char *endptr = NULL; + + status = tss2_receive_line (read_fh, buffer, sizeof (buffer)); + if (status != 0) + { + /* Set to NULL just to make sure noone uses these FHs anymore. */ + read_fh = NULL; + write_fh = NULL; + ERROR ("teamspeak2 plugin: tss2_receive_line failed."); + return (-1); + } + buffer[sizeof (buffer) - 1] = 0; + + if (strncmp ("average_packet_loss=", buffer, + strlen ("average_packet_loss=")) == 0) + { + /* Got average packet loss, now interpret it */ + value = &buffer[20]; + /* Replace , with . */ + while (*value != 0) + { + if (*value == ',') + { + *value = '.'; + break; + } + value++; + } + + value = &buffer[20]; + + packet_loss = strtod (value, &endptr); + if (value == endptr) + { + /* Failed */ + WARNING ("teamspeak2 plugin: Could not read average package " + "loss from string: %s", buffer); + continue; + } + } + else if (strncasecmp ("OK", buffer, 2) == 0) + { + break; + } + else if (strncasecmp ("ERROR", buffer, 5) == 0) + { + ERROR ("teamspeak2 plugin: Server returned an error: %s", buffer); + return (-1); + } + else + { + WARNING ("teamspeak2 plugin: Server returned unexpected string: %s", + buffer); + } + } + + *ret_value = packet_loss; + return (0); +} /* int tss2_vserver_gapl */ + static int tss2_read_vserver (vserver_list_t *vserver) { + /* + * Poll information for the given vserver and submit it to collect. + * If vserver is NULL the global server information will be queried. + */ int status; gauge_t users = NAN; + gauge_t channels = NAN; + gauge_t servers = NAN; counter_t rx_octets = 0; counter_t tx_octets = 0; counter_t rx_packets = 0; counter_t tx_packets = 0; + gauge_t packet_loss = NAN; int valid = 0; char plugin_instance[DATA_MAX_NAME_LEN]; @@ -428,8 +528,6 @@ static int tss2_read_vserver (vserver_list_t *vserver) if (vserver == NULL) { /* Request global information */ - DEBUG("teamspeak2 plugin: Read global server information"); - memset (plugin_instance, 0, sizeof (plugin_instance)); status = tss2_send_request (write_fh, "gi\r\n"); @@ -437,11 +535,8 @@ static int tss2_read_vserver (vserver_list_t *vserver) else { /* Request server information */ - DEBUG("teamspeak2 plugin: Read vserver's %i information!", vserver->port); - - snprintf (plugin_instance, sizeof (plugin_instance), "vserver%i", + ssnprintf (plugin_instance, sizeof (plugin_instance), "vserver%i", vserver->port); - plugin_instance[sizeof (plugin_instance) - 1] = 0; /* Select the server */ status = tss2_select_vserver (read_fh, write_fh, vserver); @@ -476,13 +571,13 @@ static int tss2_read_vserver (vserver_list_t *vserver) break; } - if (strncmp ("ERROR", buffer, 5) == 0) + if (strncasecmp ("ERROR", buffer, 5) == 0) { ERROR ("teamspeak2 plugin: Server returned an error: %s", buffer); break; } - else if (strncmp ("OK", buffer, 2) == 0) + else if (strncasecmp ("OK", buffer, 2) == 0) { break; } @@ -507,6 +602,8 @@ static int tss2_read_vserver (vserver_list_t *vserver) value++; /* Check for known key and save the given value */ + /* global info: users_online, + * server info: currentusers. */ if ((strcmp ("currentusers", key) == 0) || (strcmp ("users_online", key) == 0)) { @@ -514,6 +611,22 @@ static int tss2_read_vserver (vserver_list_t *vserver) if (value != endptr) valid |= 0x01; } + /* global info: channels, + * server info: currentchannels. */ + else if ((strcmp ("currentchannels", key) == 0) + || (strcmp ("channels", key) == 0)) + { + channels = strtod (value, &endptr); + if (value != endptr) + valid |= 0x40; + } + /* global only */ + else if (strcmp ("servers", key) == 0) + { + servers = strtod (value, &endptr); + if (value != endptr) + valid |= 0x80; + } else if (strcmp ("bytesreceived", key) == 0) { rx_octets = strtoll (value, &endptr, 0); @@ -567,8 +680,24 @@ static int tss2_read_vserver (vserver_list_t *vserver) } } /* while (42) */ + /* Collect vserver packet loss rates only if the loop above did not exit + * with an error. */ + if ((status == 0) && (vserver != NULL)) + { + status = tss2_vserver_gapl (read_fh, write_fh, &packet_loss); + if (status == 0) + { + valid |= 0x20; + } + else + { + WARNING ("teamspeak2 plugin: Reading package loss " + "for vserver %i failed.", vserver->port); + } + } + if ((valid & 0x01) == 0x01) - tss2_submit_gauge (plugin_instance, "users", users); + tss2_submit_gauge (plugin_instance, "users", NULL, users); if ((valid & 0x06) == 0x06) tss2_submit_io (plugin_instance, "io_octets", rx_octets, tx_octets); @@ -576,6 +705,15 @@ static int tss2_read_vserver (vserver_list_t *vserver) if ((valid & 0x18) == 0x18) tss2_submit_io (plugin_instance, "io_packets", rx_packets, tx_packets); + if ((valid & 0x20) == 0x20) + tss2_submit_gauge (plugin_instance, "percent", "packet_loss", packet_loss); + + if ((valid & 0x40) == 0x40) + tss2_submit_gauge (plugin_instance, "gauge", "channels", channels); + + if ((valid & 0x80) == 0x80) + tss2_submit_gauge (plugin_instance, "gauge", "servers", servers); + if (valid == 0) return (-1); return (0); @@ -632,6 +770,10 @@ static int tss2_config (const char *key, const char *value) static int tss2_read (void) { + /* + * Poll function which collects global and vserver information + * and submits it to collectd + */ vserver_list_t *vserver; int success = 0; int status; @@ -647,6 +789,7 @@ static int tss2_read (void) WARNING ("teamspeak2 plugin: Reading global server variables failed."); } + /* Handle vservers */ for (vserver = server_list; vserver != NULL; vserver = vserver->next) { status = tss2_read_vserver (vserver);