10 int64 buf_to_int(char *buf, int pos, int size);
11 void int_to_buf(int64 i, char *buf, int pos, int size);
13 #define BUF16_TO_INT(buf, pos) buf_to_int((buf), (pos), 2)
14 #define BUF32_TO_INT(buf, pos) buf_to_int((buf), (pos), 4)
15 #define BUF64_TO_INT(buf, pos) buf_to_int((buf), (pos), 8)
17 #define INT_TO_BUF16(i, buf, pos) int_to_buf((i), (buf), (pos), 2)
18 #define INT_TO_BUF32(i, buf, pos) int_to_buf((i), (buf), (pos), 4)
19 #define INT_TO_BUF64(i, buf, pos) int_to_buf((i), (buf), (pos), 8)
22 mldonkey_config mlconfig;
24 /* Call this function to update the information about mldonkey.
25 * Note that the function will not reconnect to mldonkey if the
26 * pointer to the mldonkey_config has not changed. As it uses static
27 * data, it cannot be used in a multithreaded env.
28 * Returns 1 if connected and info filled, 0 if connected but not filled,
52 Network_info, /* 20 */
62 DownloadedFiles, /* 30 */
72 File_info_v2, /* 40 */
81 Client_stats_v4, /* 49 */
84 #define MLDONKEY_DISCONNECTED 0
85 #define MLDONKEY_CONNECTING 1
86 #define MLDONKEY_AUTHENTICATING 2
87 #define MLDONKEY_CONNECTED 3
89 #define MAX_MESSAGE_LEN 65000
90 static int write_pos = 0;
91 static char write_buf[MAX_MESSAGE_LEN];
92 static char read_buf[MAX_MESSAGE_LEN];
94 static int mldonkey_sock = -1;
95 static int mldonkey_state = MLDONKEY_DISCONNECTED;
96 static mldonkey_config *old_config = NULL;
98 /* int64 ------------------------------ */
100 int64 buf_to_int(char *buf, int pos, int size)
105 for (i = 0; i < size; i++) {
106 res += (buf[pos + i] & 0xFF) << (8 * i);
111 void int_to_buf(int64 i, char *buf, int pos, int size)
115 for (j = 0; j < size; j++) {
116 buf[pos + j] = (i & (-1)) >> (8 * j);
120 /* Write operations --------------------- */
127 void write_int8(int code)
129 write_buf[write_pos++] = code;
132 void write_opcode(int code)
134 write_buf[write_pos++] = code;
137 void write_int16(int code)
139 INT_TO_BUF16(code, write_buf, write_pos);
143 void write_int32(int code)
145 INT_TO_BUF32(code, write_buf, write_pos);
149 void write_int64(int64 code)
151 INT_TO_BUF64(code, write_buf, write_pos);
155 void write_string(char *str)
160 int len = strlen(str);
162 memcpy((void *) (write_buf + write_pos), (void *) str,
169 int write_message(char *mtype)
173 INT_TO_BUF32(write_pos, header, 0);
174 if (4 != write(mldonkey_sock, header, 4) ||
175 write_pos != write(mldonkey_sock, (void *) write_buf,
176 (size_t) write_pos)) {
177 ERR("Error in transmitting %s\n", mtype);
180 /* Immediatly close the connection */
181 close(mldonkey_sock);
182 mldonkey_state = MLDONKEY_DISCONNECTED;
192 /* Read operations ----------------------------*/
196 return read_buf[read_pos++];
201 int i = BUF16_TO_INT(read_buf, read_pos);
208 int i = BUF32_TO_INT(read_buf, read_pos);
215 int64 i = BUF64_TO_INT(read_buf, read_pos);
225 len = BUF16_TO_INT(read_buf, read_pos);
228 buf = (char *) malloc((size_t) len + 1);
229 memmove(read_buf + read_pos, buf, len);
236 /* protocol impl. ----------------------------- */
240 /* This function returns the number of messages read, 0 if it blocks,
242 int cut_messages(int reinit)
245 static int toread = 0;
258 read(mldonkey_sock, read_buf + pos, 4 - pos);
260 if (errno == EAGAIN) {
271 toread = BUF32_TO_INT(read_buf, 0);
276 read(mldonkey_sock, read_buf + pos,
290 /* We have one message !!! */
305 if (mldonkey_sock >= 0)
306 close(mldonkey_sock);
308 mldonkey_state = MLDONKEY_DISCONNECTED;
312 int mldonkey_connect(mldonkey_config * config)
314 if (config != old_config) {
315 struct sockaddr_in sa;
321 /* resolve hostname */
322 memset(&sa, 0, sizeof(sa));
324 if (config->mldonkey_hostname == NULL)
325 config->mldonkey_hostname = "127.0.0.1";
326 if (config->mldonkey_hostname[0] >= '0' &&
327 config->mldonkey_hostname[0] <= '9') {
330 (config->mldonkey_hostname, &sa.sin_addr) == 0)
335 inet_addr(config->mldonkey_hostname);
336 if (sa.sin_addr.s_addr == (unsigned int) -1)
342 hp = gethostbyname(config->mldonkey_hostname);
343 if (hp == (struct hostent *) NULL)
346 (unsigned long) hp->h_addr_list[0];
349 sa.sin_port = htons(config->mldonkey_port);
350 sa.sin_family = AF_INET;
352 if ((mldonkey_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
353 ERR("Opening socket");
359 (mldonkey_sock, (struct sockaddr *) &sa,
361 if (errno != EAGAIN && errno != EINTR
362 && errno != EINPROGRESS
363 && errno != EWOULDBLOCK) {
364 // ERR("Connection failed");
370 retcode = fcntl(mldonkey_sock, F_GETFL, 0);
372 fcntl(mldonkey_sock, F_SETFL,
373 retcode | O_NONBLOCK) == -1) {
378 mldonkey_state = MLDONKEY_CONNECTING;
385 int mldonkey_can_read()
387 return cut_messages(0);
390 int mldonkey_info_message(mldonkey_info * info)
392 int opcode = read_int16();
399 write_int16(0); /* GUI protocol */
400 write_int32(10); /* Version 10 ! */
401 write_message("GuiProtocol");
403 write_int16(47); /* GUI protocol */
408 write_message("GuiExtensions");
411 write_int16(5); /* Password */
412 write_string(old_config->mldonkey_password);
413 write_message("Password");
418 ERR("Bad Password\n");
423 case Client_stats_v2:
424 case Client_stats_v3:
425 ERR("Client stats format too old...\n");
428 case Client_stats_v4:
429 mldonkey_state = MLDONKEY_CONNECTED;
431 info->upload_counter = read_int64();
432 info->download_counter = read_int64();
433 info->shared_counter = read_int64();
434 info->nshared_files = read_int32();
435 info->tcp_upload_rate = read_int32();
436 info->tcp_download_rate = read_int32();
437 info->udp_upload_rate = read_int32();
438 info->udp_download_rate = read_int32();
439 info->ndownloading_files = read_int32();
440 info->ndownloaded_files = read_int32();
448 int get_mldonkey_status(mldonkey_config * config, mldonkey_info * info)
450 if (mldonkey_connect(config) >= 0) {
451 while (mldonkey_can_read() > 0) {
452 mldonkey_info_message(info);
455 return mldonkey_state;