9 int64 buf_to_int(char *buf, int pos, int size);
10 void int_to_buf(int64 i, char *buf, int pos, int size);
12 #define BUF16_TO_INT(buf, pos) buf_to_int((buf), (pos), 2)
13 #define BUF32_TO_INT(buf, pos) buf_to_int((buf), (pos), 4)
14 #define BUF64_TO_INT(buf, pos) buf_to_int((buf), (pos), 8)
16 #define INT_TO_BUF16(i, buf, pos) int_to_buf((i), (buf), (pos), 2)
17 #define INT_TO_BUF32(i, buf, pos) int_to_buf((i), (buf), (pos), 4)
18 #define INT_TO_BUF64(i, buf, pos) int_to_buf((i), (buf), (pos), 8)
21 mldonkey_config mlconfig;
23 /* Call this function to update the information about mldonkey.
24 * Note that the function will not reconnect to mldonkey if the
25 * pointer to the mldonkey_config has not changed. As it uses static
26 * data, it cannot be used in a multithreaded env.
27 * Returns 1 if connected and info filled, 0 if connected but not filled,
51 Network_info, /* 20 */
61 DownloadedFiles, /* 30 */
71 File_info_v2, /* 40 */
80 Client_stats_v4, /* 49 */
83 #define MLDONKEY_DISCONNECTED 0
84 #define MLDONKEY_CONNECTING 1
85 #define MLDONKEY_AUTHENTICATING 2
86 #define MLDONKEY_CONNECTED 3
88 #define MAX_MESSAGE_LEN 65000
89 static int write_pos = 0;
90 static char write_buf[MAX_MESSAGE_LEN];
91 static char read_buf[MAX_MESSAGE_LEN];
93 static int mldonkey_sock = -1;
94 static int mldonkey_state = MLDONKEY_DISCONNECTED;
95 static mldonkey_config *old_config = NULL;
97 /* int64 ------------------------------ */
99 int64 buf_to_int(char *buf, int pos, int size)
104 for(i = 0; i < size; i++){
105 res += (buf[pos + i] & 0xFF) << (8 * i);
110 void int_to_buf(int64 i, char *buf, int pos, int size)
114 for(j = 0; j < size; j++){
115 buf[pos + j] = (i & (-1)) >> (8 * j);
119 /* Write operations --------------------- */
124 void write_int8(int code)
126 write_buf[write_pos++] = code;
129 void write_opcode(int code)
131 write_buf[write_pos++] = code;
134 void write_int16(int code)
136 INT_TO_BUF16(code, write_buf, write_pos);
140 void write_int32(int code)
142 INT_TO_BUF32(code, write_buf, write_pos);
146 void write_int64(int64 code)
148 INT_TO_BUF64(code, write_buf, write_pos);
152 void write_string(char *str)
157 int len = strlen(str);
159 memcpy((void *) (write_buf + write_pos), (void *) str, (size_t) len);
165 int write_message(char *mtype)
169 INT_TO_BUF32(write_pos, header, 0);
170 if(4 != write(mldonkey_sock, header, 4) ||
171 write_pos != write(mldonkey_sock,(void *)write_buf,(size_t)write_pos)){
172 ERR("Error in transmitting %s\n",mtype);
175 /* Immediatly close the connection */
176 close(mldonkey_sock);
177 mldonkey_state = MLDONKEY_DISCONNECTED;
187 /* Read operations ----------------------------*/
191 return read_buf[read_pos++];
196 int i = BUF16_TO_INT(read_buf, read_pos);
203 int i = BUF32_TO_INT(read_buf, read_pos);
210 int64 i = BUF64_TO_INT(read_buf, read_pos);
220 len = BUF16_TO_INT(read_buf, read_pos);
223 buf = (char *) malloc((size_t) len+1);
224 memmove(read_buf + read_pos, buf, len);
231 /* protocol impl. ----------------------------- */
235 /* This function returns the number of messages read, 0 if it blocks,
237 int cut_messages(int reinit)
240 static int toread = 0;
252 nread = read(mldonkey_sock, read_buf+pos,4-pos);
254 if(errno == EAGAIN) {
258 pos = 0; toread = 0; return -1; }
262 toread = BUF32_TO_INT(read_buf,0);
266 nread = read(mldonkey_sock, read_buf+pos, toread - pos);
268 if(errno == EAGAIN) return 0; else {
275 /* We have one message !!! */
290 if(mldonkey_sock >= 0) close(mldonkey_sock);
292 mldonkey_state = MLDONKEY_DISCONNECTED;
296 int mldonkey_connect(mldonkey_config *config)
298 if(config != old_config){
299 struct sockaddr_in sa;
305 /* resolve hostname */
306 memset(&sa, 0, sizeof(sa));
308 if(config->mldonkey_hostname == NULL)
309 config->mldonkey_hostname = "127.0.0.1";
310 if(config->mldonkey_hostname[0] >= '0' &&
311 config->mldonkey_hostname[0] <= '9'){
313 if (inet_aton(config->mldonkey_hostname, &sa.sin_addr) == 0) return -1;
316 sa.sin_addr.s_addr = inet_addr(config->mldonkey_hostname);
317 if (sa.sin_addr.s_addr == (unsigned int) -1) return -1;
322 hp = gethostbyname(config->mldonkey_hostname);
323 if (hp == (struct hostent *) NULL) return -1;
324 sa.sin_addr.s_addr = (unsigned long)hp->h_addr_list[0];
327 sa.sin_port = htons(config->mldonkey_port);
328 sa.sin_family = AF_INET;
330 if ((mldonkey_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
331 ERR("Opening socket");
336 if( connect(mldonkey_sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
337 if (errno != EAGAIN &&
339 errno != EINPROGRESS &&
340 errno != EWOULDBLOCK) {
341 // ERR("Connection failed");
347 retcode = fcntl(mldonkey_sock, F_GETFL, 0);
349 fcntl(mldonkey_sock, F_SETFL, retcode | O_NONBLOCK) == -1){
354 mldonkey_state = MLDONKEY_CONNECTING;
361 int mldonkey_can_read()
363 return cut_messages(0);
366 int mldonkey_info_message(mldonkey_info *info)
368 int opcode = read_int16();
375 write_int16(0); /* GUI protocol */
376 write_int32(10); /* Version 10 ! */
377 write_message("GuiProtocol");
379 write_int16(47); /* GUI protocol */
384 write_message("GuiExtensions");
387 write_int16(5); /* Password */
388 write_string(old_config->mldonkey_password);
389 write_message("Password");
394 ERR("Bad Password\n");
399 case Client_stats_v2:
400 case Client_stats_v3:
401 ERR("Client stats format too old...\n");
404 case Client_stats_v4:
405 mldonkey_state = MLDONKEY_CONNECTED;
407 info->upload_counter = read_int64();
408 info->download_counter = read_int64();
409 info->shared_counter = read_int64();
410 info->nshared_files = read_int32();
411 info->tcp_upload_rate = read_int32();
412 info->tcp_download_rate = read_int32();
413 info->udp_upload_rate = read_int32();
414 info->udp_download_rate = read_int32();
415 info->ndownloading_files = read_int32();
416 info->ndownloaded_files = read_int32();
424 int get_mldonkey_status(mldonkey_config *config, mldonkey_info *info)
426 if( mldonkey_connect(config) >= 0){
427 while(mldonkey_can_read() > 0){
428 mldonkey_info_message(info);
431 return mldonkey_state;