mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-05 21:07:52 +00:00
4d1d328de9
git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky@5 7f574dfc-610e-0410-a909-a81674777703
433 lines
8.9 KiB
C
433 lines
8.9 KiB
C
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <netdb.h>
|
|
#include <fcntl.h>
|
|
#include <arpa/inet.h>
|
|
#include "conky.h"
|
|
|
|
int64 buf_to_int(char *buf, int pos, int size);
|
|
void int_to_buf(int64 i, char *buf, int pos, int size);
|
|
|
|
#define BUF16_TO_INT(buf, pos) buf_to_int((buf), (pos), 2)
|
|
#define BUF32_TO_INT(buf, pos) buf_to_int((buf), (pos), 4)
|
|
#define BUF64_TO_INT(buf, pos) buf_to_int((buf), (pos), 8)
|
|
|
|
#define INT_TO_BUF16(i, buf, pos) int_to_buf((i), (buf), (pos), 2)
|
|
#define INT_TO_BUF32(i, buf, pos) int_to_buf((i), (buf), (pos), 4)
|
|
#define INT_TO_BUF64(i, buf, pos) int_to_buf((i), (buf), (pos), 8)
|
|
|
|
mldonkey_info mlinfo;
|
|
mldonkey_config mlconfig;
|
|
|
|
/* Call this function to update the information about mldonkey.
|
|
* Note that the function will not reconnect to mldonkey if the
|
|
* pointer to the mldonkey_config has not changed. As it uses static
|
|
* data, it cannot be used in a multithreaded env.
|
|
* Returns 1 if connected and info filled, 0 if connected but not filled,
|
|
* -1 otherwise. */
|
|
|
|
enum to_gui {
|
|
CoreProtocol, /* 0 */
|
|
Options_info,
|
|
RESERVED2,
|
|
DefineSearches,
|
|
Result_info,
|
|
Search_result,
|
|
Search_waiting,
|
|
File_info,
|
|
File_downloaded,
|
|
File_availability,
|
|
File_source, /* 10 */
|
|
Server_busy,
|
|
Server_user,
|
|
Server_state,
|
|
Server_info,
|
|
Client_info,
|
|
Client_state,
|
|
Client_friend,
|
|
Client_file,
|
|
Console,
|
|
Network_info, /* 20 */
|
|
User_info,
|
|
Room_info,
|
|
Room_message,
|
|
Room_add_user,
|
|
Client_stats,
|
|
Server_info_v2,
|
|
MessageFromClient,
|
|
ConnectedServers,
|
|
DownloadFiles,
|
|
DownloadedFiles, /* 30 */
|
|
Room_info_v2,
|
|
Room_remove_user,
|
|
Shared_file_info,
|
|
Shared_file_upload,
|
|
Shared_file_unshared,
|
|
Add_section_option,
|
|
Client_stats_v2,
|
|
Add_plugin_option,
|
|
Client_stats_v3,
|
|
File_info_v2, /* 40 */
|
|
DownloadFiles_v2,
|
|
DownloadedFiles_v2,
|
|
File_info_v3,
|
|
DownloadFiles_v3,
|
|
DownloadedFiles_v3,
|
|
File_downloaded_v2,
|
|
BadPassword,
|
|
Shared_file_info_v2,
|
|
Client_stats_v4, /* 49 */
|
|
};
|
|
|
|
#define MLDONKEY_DISCONNECTED 0
|
|
#define MLDONKEY_CONNECTING 1
|
|
#define MLDONKEY_AUTHENTICATING 2
|
|
#define MLDONKEY_CONNECTED 3
|
|
|
|
#define MAX_MESSAGE_LEN 65000
|
|
static int write_pos = 0;
|
|
static char write_buf[MAX_MESSAGE_LEN];
|
|
static char read_buf[MAX_MESSAGE_LEN];
|
|
static int read_pos;
|
|
static int mldonkey_sock = -1;
|
|
static int mldonkey_state = MLDONKEY_DISCONNECTED;
|
|
static mldonkey_config *old_config = NULL;
|
|
|
|
/* int64 ------------------------------ */
|
|
|
|
int64 buf_to_int(char *buf, int pos, int size)
|
|
{
|
|
int i;
|
|
int64 res = 0;
|
|
|
|
for(i = 0; i < size; i++){
|
|
res += (buf[pos + i] & 0xFF) << (8 * i);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
void int_to_buf(int64 i, char *buf, int pos, int size)
|
|
{
|
|
int j;
|
|
|
|
for(j = 0; j < size; j++){
|
|
buf[pos + j] = (i & (-1)) >> (8 * j);
|
|
}
|
|
}
|
|
|
|
/* Write operations --------------------- */
|
|
|
|
void init_message()
|
|
{ write_pos = 0; }
|
|
|
|
void write_int8(int code)
|
|
{
|
|
write_buf[write_pos++] = code;
|
|
}
|
|
|
|
void write_opcode(int code)
|
|
{
|
|
write_buf[write_pos++] = code;
|
|
}
|
|
|
|
void write_int16(int code)
|
|
{
|
|
INT_TO_BUF16(code, write_buf, write_pos);
|
|
write_pos += 2;
|
|
}
|
|
|
|
void write_int32(int code)
|
|
{
|
|
INT_TO_BUF32(code, write_buf, write_pos);
|
|
write_pos += 4;
|
|
}
|
|
|
|
void write_int64(int64 code)
|
|
{
|
|
INT_TO_BUF64(code, write_buf, write_pos);
|
|
write_pos += 8;
|
|
}
|
|
|
|
void write_string(char *str)
|
|
{
|
|
if(str == NULL){
|
|
write_int16(0);
|
|
} else {
|
|
int len = strlen(str);
|
|
write_int16(len);
|
|
memcpy((void *) (write_buf + write_pos), (void *) str, (size_t) len);
|
|
write_pos += len;
|
|
}
|
|
}
|
|
|
|
|
|
int write_message(char *mtype)
|
|
{
|
|
char header[4];
|
|
|
|
INT_TO_BUF32(write_pos, header, 0);
|
|
if(4 != write(mldonkey_sock, header, 4) ||
|
|
write_pos != write(mldonkey_sock,(void *)write_buf,(size_t)write_pos)){
|
|
ERR("Error in transmitting %s\n",mtype);
|
|
write_pos = 0;
|
|
|
|
/* Immediatly close the connection */
|
|
close(mldonkey_sock);
|
|
mldonkey_state = MLDONKEY_DISCONNECTED;
|
|
mldonkey_sock = -1;
|
|
return -1;
|
|
} else {
|
|
write_pos = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Read operations ----------------------------*/
|
|
|
|
int read_int8()
|
|
{
|
|
return read_buf[read_pos++];
|
|
}
|
|
|
|
int read_int16()
|
|
{
|
|
int i = BUF16_TO_INT(read_buf, read_pos);
|
|
read_pos += 2;
|
|
return i;
|
|
}
|
|
|
|
int read_int32()
|
|
{
|
|
int i = BUF32_TO_INT(read_buf, read_pos);
|
|
read_pos += 4;
|
|
return i;
|
|
}
|
|
|
|
int64 read_int64()
|
|
{
|
|
int64 i = BUF64_TO_INT(read_buf, read_pos);
|
|
read_pos += 8;
|
|
return i;
|
|
}
|
|
|
|
char* read_string()
|
|
{
|
|
char *buf;
|
|
int len;
|
|
|
|
len = BUF16_TO_INT(read_buf, read_pos);
|
|
read_pos += 2;
|
|
|
|
buf = (char *) malloc((size_t) len+1);
|
|
memmove(read_buf + read_pos, buf, len);
|
|
buf[len] = 0;
|
|
read_pos += len;
|
|
|
|
return buf;
|
|
}
|
|
|
|
/* protocol impl. ----------------------------- */
|
|
|
|
void close_sock();
|
|
|
|
/* This function returns the number of messages read, 0 if it blocks,
|
|
-1 on error. */
|
|
int cut_messages(int reinit)
|
|
{
|
|
int nread;
|
|
static int toread = 0;
|
|
static int pos = 0;
|
|
|
|
if(reinit){
|
|
toread = 0;
|
|
pos = 0;
|
|
read_pos = 0;
|
|
return 0;
|
|
}
|
|
|
|
while(1){
|
|
if(toread == 0){
|
|
nread = read(mldonkey_sock, read_buf+pos,4-pos);
|
|
if(nread <= 0){
|
|
if(errno == EAGAIN) {
|
|
return 0;
|
|
} else {
|
|
close_sock();
|
|
pos = 0; toread = 0; return -1; }
|
|
}
|
|
pos += nread;
|
|
if(pos == 4){
|
|
toread = BUF32_TO_INT(read_buf,0);
|
|
pos = 0;
|
|
}
|
|
} else {
|
|
nread = read(mldonkey_sock, read_buf+pos, toread - pos);
|
|
if(nread <= 0){
|
|
if(errno == EAGAIN) return 0; else {
|
|
pos = 0; toread = 0;
|
|
close_sock();
|
|
return -1; }
|
|
}
|
|
pos += nread;
|
|
if(pos == toread){
|
|
/* We have one message !!! */
|
|
int old_pos = pos;
|
|
read_pos = 0;
|
|
pos = 0;
|
|
toread = 0;
|
|
|
|
return old_pos;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void close_sock()
|
|
{
|
|
old_config = NULL;
|
|
if(mldonkey_sock >= 0) close(mldonkey_sock);
|
|
mldonkey_sock = -1;
|
|
mldonkey_state = MLDONKEY_DISCONNECTED;
|
|
cut_messages(1);
|
|
}
|
|
|
|
int mldonkey_connect(mldonkey_config *config)
|
|
{
|
|
if(config != old_config){
|
|
struct sockaddr_in sa;
|
|
int retcode;
|
|
close_sock();
|
|
|
|
|
|
old_config=config;
|
|
/* resolve hostname */
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
if(config->mldonkey_hostname == NULL)
|
|
config->mldonkey_hostname = "127.0.0.1";
|
|
if(config->mldonkey_hostname[0] >= '0' &&
|
|
config->mldonkey_hostname[0] <= '9'){
|
|
#ifdef HAS_INET_ATON
|
|
if (inet_aton(config->mldonkey_hostname, &sa.sin_addr) == 0) return -1;
|
|
#else
|
|
|
|
sa.sin_addr.s_addr = inet_addr(config->mldonkey_hostname);
|
|
if (sa.sin_addr.s_addr == (unsigned int) -1) return -1;
|
|
#endif
|
|
|
|
} else {
|
|
struct hostent * hp;
|
|
hp = gethostbyname(config->mldonkey_hostname);
|
|
if (hp == (struct hostent *) NULL) return -1;
|
|
sa.sin_addr.s_addr = (unsigned long)hp->h_addr_list[0];
|
|
}
|
|
|
|
sa.sin_port = htons(config->mldonkey_port);
|
|
sa.sin_family = AF_INET;
|
|
|
|
if ((mldonkey_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
|
|
ERR("Opening socket");
|
|
close_sock();
|
|
return -1;
|
|
}
|
|
|
|
if( connect(mldonkey_sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
|
if (errno != EAGAIN &&
|
|
errno != EINTR &&
|
|
errno != EINPROGRESS &&
|
|
errno != EWOULDBLOCK) {
|
|
// ERR("Connection failed");
|
|
close_sock();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
retcode = fcntl(mldonkey_sock, F_GETFL, 0);
|
|
if (retcode == -1 ||
|
|
fcntl(mldonkey_sock, F_SETFL, retcode | O_NONBLOCK) == -1){
|
|
return -1;
|
|
}
|
|
|
|
|
|
mldonkey_state = MLDONKEY_CONNECTING;
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int mldonkey_can_read()
|
|
{
|
|
return cut_messages(0);
|
|
}
|
|
|
|
int mldonkey_info_message(mldonkey_info *info)
|
|
{
|
|
int opcode = read_int16();
|
|
|
|
switch(opcode){
|
|
|
|
case CoreProtocol :
|
|
init_message();
|
|
|
|
write_int16(0); /* GUI protocol */
|
|
write_int32(10); /* Version 10 ! */
|
|
write_message("GuiProtocol");
|
|
|
|
write_int16(47); /* GUI protocol */
|
|
|
|
write_int16(1);
|
|
write_int32(1);
|
|
write_int8(1);
|
|
write_message("GuiExtensions");
|
|
|
|
init_message();
|
|
write_int16(5); /* Password */
|
|
write_string(old_config->mldonkey_password);
|
|
write_message("Password");
|
|
|
|
break;
|
|
|
|
case BadPassword :
|
|
ERR("Bad Password\n");
|
|
close_sock();
|
|
break;
|
|
|
|
case Client_stats:
|
|
case Client_stats_v2:
|
|
case Client_stats_v3:
|
|
ERR("Client stats format too old...\n");
|
|
break;
|
|
|
|
case Client_stats_v4:
|
|
mldonkey_state = MLDONKEY_CONNECTED;
|
|
|
|
info->upload_counter = read_int64();
|
|
info->download_counter = read_int64();
|
|
info->shared_counter = read_int64();
|
|
info->nshared_files = read_int32();
|
|
info->tcp_upload_rate = read_int32();
|
|
info->tcp_download_rate = read_int32();
|
|
info->udp_upload_rate = read_int32();
|
|
info->udp_download_rate = read_int32();
|
|
info->ndownloading_files = read_int32();
|
|
info->ndownloaded_files = read_int32();
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int get_mldonkey_status(mldonkey_config *config, mldonkey_info *info)
|
|
{
|
|
if( mldonkey_connect(config) >= 0){
|
|
while(mldonkey_can_read() > 0){
|
|
mldonkey_info_message(info);
|
|
}
|
|
}
|
|
return mldonkey_state;
|
|
}
|