1 /*
2     $Id: cddb_conn.c,v 1.39 2006/10/15 11:53:11 airborne Exp $
3 
4     Copyright (C) 2003, 2004, 2005 Kris Verbeeck <airborne@advalvas.be>
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15 
16     You should have received a copy of the GNU Library General Public
17     License along with this library; if not, write to the
18     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19     Boston, MA  02111-1307, USA.
20 */
21 
22 #include "cddb/cddb_ni.h"
23 
24 #ifdef HAVE_SYS_TYPES_H
25 #include <sys/types.h>
26 #endif
27 
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 
32 #ifdef HAVE_ARPA_INET_H
33 #include <arpa/inet.h>
34 #endif
35 
36 #ifdef HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif
39 
40 #ifdef HAVE_STRING_H
41 #include <string.h>
42 #endif
43 
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47 
48 
49 /* --- prototypes --- */
50 
51 
52 /**
53  * Send handshake to CDDB server.
54  */
55 static int cddb_handshake(cddb_conn_t *c);
56 
57 /**
58  * Reset proxy authentication credentials.
59  */
60 static void cddb_set_http_proxy_auth(cddb_conn_t *c,
61                                      const char *username,
62                                      const char *password);
63 
64 
65 /* --- construction / destruction --- */
66 
67 
cddb_new(void)68 cddb_conn_t *cddb_new(void)
69 {
70     cddb_conn_t *c;
71     const char *s;
72 
73     libcddb_init();             /* initialize globals if not yet done */
74     c = (cddb_conn_t*)malloc(sizeof(cddb_conn_t));
75     if (c) {
76         c->buf_size = DEFAULT_BUF_SIZE;
77         c->line = (char*)malloc(c->buf_size);
78 
79         c->cname = strdup(CLIENT_NAME);
80         c->cversion = strdup(CLIENT_VERSION);
81 
82         c->is_connected = FALSE;
83         c->socket = -1;
84         c->cache_fp = NULL;
85         c->server_name = strdup(DEFAULT_SERVER);
86         c->server_port = DEFAULT_PORT;
87         c->timeout = DEFAULT_TIMEOUT;
88 
89         c->http_path_query = strdup(DEFAULT_PATH_QUERY);
90         c->http_path_submit = strdup(DEFAULT_PATH_SUBMIT);
91 
92         c->is_http_enabled = FALSE;
93         c->is_http_proxy_enabled = FALSE;
94         c->http_proxy_server = NULL;
95         c->http_proxy_server_port = DEFAULT_PROXY_PORT;
96         c->http_proxy_username = NULL;
97         c->http_proxy_password = NULL;
98         c->http_proxy_auth = NULL;
99 
100         c->use_cache = CACHE_ON;
101         /* construct cache dir '$HOME/[DEFAULT_CACHE]' */
102         s = getenv("HOME");
103         c->cache_dir = (char*)malloc(strlen(s) + 1 + sizeof(DEFAULT_CACHE) + 1);
104         sprintf(c->cache_dir, "%s/%s", s, DEFAULT_CACHE);
105         c->cache_read = FALSE;
106 
107         /* use anonymous@localhost */
108         c->user = strdup(DEFAULT_USER);
109         c->hostname = strdup(DEFAULT_HOST);
110 
111         c->errnum = CDDB_ERR_OK;
112 
113         // XXX: handle out-of-memory
114         c->query_data = list_new((elem_destroy_cb*)cddb_disc_destroy);
115         c->sites_data = list_new((elem_destroy_cb*)cddb_site_destroy);
116 
117         c->charset = malloc(sizeof(struct cddb_iconv_s));
118         c->charset->cd_to_freedb = NULL;
119         c->charset->cd_from_freedb = NULL;
120 
121         c->srch.fields = SEARCH_ARTIST | SEARCH_TITLE;
122         c->srch.cats = SEARCH_ALL;
123     } else {
124         cddb_log_crit(cddb_error_str(CDDB_ERR_OUT_OF_MEMORY));
125     }
126 
127     return c;
128 }
129 
cddb_close_iconv(cddb_conn_t * c)130 static void cddb_close_iconv(cddb_conn_t *c)
131 {
132     if (c->charset) {
133 #ifdef HAVE_ICONV_H
134         if (c->charset->cd_to_freedb) {
135             iconv_close(c->charset->cd_to_freedb);
136         }
137         if (c->charset->cd_from_freedb) {
138             iconv_close(c->charset->cd_from_freedb);
139         }
140 #endif /* HAVE_ICONV_H */
141     }
142 }
143 
cddb_destroy(cddb_conn_t * c)144 void cddb_destroy(cddb_conn_t *c)
145 {
146     if (c) {
147         cddb_disconnect(c);
148         FREE_NOT_NULL(c->line);
149         FREE_NOT_NULL(c->cname);
150         FREE_NOT_NULL(c->cversion);
151         FREE_NOT_NULL(c->server_name);
152         FREE_NOT_NULL(c->http_path_query);
153         FREE_NOT_NULL(c->http_path_submit);
154         FREE_NOT_NULL(c->http_proxy_server);
155         FREE_NOT_NULL(c->http_proxy_username);
156         FREE_NOT_NULL(c->http_proxy_password);
157         FREE_NOT_NULL(c->cache_dir);
158         FREE_NOT_NULL(c->user);
159         FREE_NOT_NULL(c->hostname);
160         list_destroy(c->query_data);
161         list_destroy(c->sites_data);
162         cddb_close_iconv(c);
163         FREE_NOT_NULL(c->charset);
164         free(c);
165     }
166 }
167 
168 
169 /* --- getters & setters --- */
170 
171 
cddb_set_charset(cddb_conn_t * c,const char * charset)172 int cddb_set_charset(cddb_conn_t *c, const char *charset)
173 {
174 #ifdef HAVE_ICONV_H
175     cddb_close_iconv(c);
176     c->charset->cd_to_freedb = iconv_open(SERVER_CHARSET, charset);
177     if (c->charset->cd_to_freedb == (iconv_t)-1) {
178         c->charset->cd_to_freedb = NULL;
179         cddb_errno_set(c, CDDB_ERR_INVALID_CHARSET);
180         return FALSE;
181     }
182     c->charset->cd_from_freedb = iconv_open(charset, SERVER_CHARSET);
183     if (c->charset->cd_from_freedb == (iconv_t)-1) {
184         iconv_close(c->charset->cd_to_freedb);
185         c->charset->cd_to_freedb = NULL;
186         c->charset->cd_from_freedb = NULL;
187         cddb_errno_set(c, CDDB_ERR_INVALID_CHARSET);
188         return FALSE;
189     }
190     cddb_errno_set(c, CDDB_ERR_OK);
191     return TRUE;
192 #else
193     cddb_errno_set(c, CDDB_ERR_ICONV_FAIL);
194     return FALSE;
195 #endif /* HAVE_ICONV_H */
196 }
197 
cddb_set_buf_size(cddb_conn_t * c,unsigned int size)198 void cddb_set_buf_size(cddb_conn_t *c, unsigned int size)
199 {
200     FREE_NOT_NULL(c->line);
201     c->buf_size = size;
202     c->line = (char*)malloc(c->buf_size);
203 }
204 
cddb_set_site(cddb_conn_t * c,const cddb_site_t * site)205 cddb_error_t cddb_set_site(cddb_conn_t *c, const cddb_site_t *site)
206 {
207     cddb_error_t rv;
208     const char *server, *path;
209     unsigned int port;
210     cddb_protocol_t proto;
211 
212     ASSERT_NOT_NULL(c);
213     if ((rv = cddb_site_get_address(site, &server, &port)) != CDDB_ERR_OK) {
214         cddb_errno_set(c, rv);
215         return rv;
216     }
217     if ((proto = cddb_site_get_protocol(site)) == PROTO_UNKNOWN) {
218         cddb_errno_set(c, CDDB_ERR_INVALID);
219         return CDDB_ERR_INVALID;
220     }
221     if ((rv = cddb_site_get_query_path(site, &path)) != CDDB_ERR_OK) {
222         cddb_errno_set(c, rv);
223         return rv;
224     }
225     cddb_set_server_name(c, server);
226     cddb_set_server_port(c, port);
227     if (proto == PROTO_CDDBP) {
228         cddb_http_disable(c);
229     } else {
230         cddb_http_enable(c);
231         cddb_set_http_path_query(c, path);
232     }
233     return cddb_errno_set(c, CDDB_ERR_OK);
234 }
235 
cddb_get_server_name(const cddb_conn_t * c)236 const char *cddb_get_server_name(const cddb_conn_t *c)
237 {
238     const char *server = NULL;
239 
240     if (c) {
241         server = c->server_name;
242     }
243     RETURN_STR_OR_EMPTY(server);
244 }
245 
cddb_set_server_name(cddb_conn_t * c,const char * server)246 void cddb_set_server_name(cddb_conn_t *c, const char *server)
247 {
248     FREE_NOT_NULL(c->server_name);
249     c->server_name = strdup(server);
250 }
251 
cddb_get_server_port(const cddb_conn_t * c)252 unsigned int cddb_get_server_port(const cddb_conn_t *c)
253 {
254     if (c) {
255         return c->server_port;
256     }
257     return 0;
258 }
259 
cddb_set_server_port(cddb_conn_t * c,int port)260 void cddb_set_server_port(cddb_conn_t *c, int port)
261 {
262     c->server_port = port;
263 }
264 
cddb_get_timeout(const cddb_conn_t * c)265 unsigned int cddb_get_timeout(const cddb_conn_t *c)
266 {
267     if (c) {
268         return c->timeout;
269     }
270     return 0;
271 }
272 
cddb_set_timeout(cddb_conn_t * c,unsigned int t)273 void cddb_set_timeout(cddb_conn_t *c, unsigned int t)
274 {
275     if (c) {
276         c->timeout = t;
277     }
278 }
279 
cddb_get_http_path_query(const cddb_conn_t * c)280 const char *cddb_get_http_path_query(const cddb_conn_t *c)
281 {
282     const char *path = NULL;
283 
284     if (c) {
285         path = c->http_path_query;
286     }
287     RETURN_STR_OR_EMPTY(path);
288 }
289 
cddb_set_http_path_query(cddb_conn_t * c,const char * path)290 void cddb_set_http_path_query(cddb_conn_t *c, const char *path)
291 {
292     FREE_NOT_NULL(c->http_path_query);
293     c->http_path_query = strdup(path);
294 }
295 
cddb_get_http_path_submit(const cddb_conn_t * c)296 const char *cddb_get_http_path_submit(const cddb_conn_t *c)
297 {
298     const char *path = NULL;
299 
300     if (c) {
301         path = c->http_path_submit;
302     }
303     RETURN_STR_OR_EMPTY(path);
304 }
305 
cddb_set_http_path_submit(cddb_conn_t * c,const char * path)306 void cddb_set_http_path_submit(cddb_conn_t *c, const char *path)
307 {
308     FREE_NOT_NULL(c->http_path_submit);
309     c->http_path_submit = strdup(path);
310 }
311 
cddb_is_http_enabled(const cddb_conn_t * c)312 unsigned int cddb_is_http_enabled(const cddb_conn_t *c)
313 {
314     if (c) {
315         return c->is_http_enabled;
316     }
317     return FALSE;
318 }
319 
cddb_http_enable(cddb_conn_t * c)320 void cddb_http_enable(cddb_conn_t *c)
321 {
322     c->is_http_enabled = TRUE;
323     cddb_errno_set(c, CDDB_ERR_OK);
324 }
325 
cddb_http_disable(cddb_conn_t * c)326 void cddb_http_disable(cddb_conn_t *c)
327 {
328     c->is_http_enabled = FALSE;
329     cddb_errno_set(c, CDDB_ERR_OK);
330 }
331 
cddb_is_http_proxy_enabled(const cddb_conn_t * c)332 unsigned int cddb_is_http_proxy_enabled(const cddb_conn_t *c)
333 {
334     if (c) {
335         return c->is_http_proxy_enabled;
336     }
337     return FALSE;
338 }
339 
cddb_http_proxy_enable(cddb_conn_t * c)340 void cddb_http_proxy_enable(cddb_conn_t *c)
341 {
342     /* enabling HTTP proxy implies HTTP, but not vice versa */
343     cddb_http_enable(c);
344     c->is_http_proxy_enabled = TRUE;
345     cddb_errno_set(c, CDDB_ERR_OK);
346 }
347 
cddb_http_proxy_disable(cddb_conn_t * c)348 void cddb_http_proxy_disable(cddb_conn_t *c)
349 {
350     c->is_http_proxy_enabled = FALSE;
351     cddb_errno_set(c, CDDB_ERR_OK);
352 }
353 
cddb_get_http_proxy_server_name(const cddb_conn_t * c)354 const char *cddb_get_http_proxy_server_name(const cddb_conn_t *c)
355 {
356     const char *server = NULL;
357 
358     if (c) {
359         server = c->http_proxy_server;
360     }
361     RETURN_STR_OR_EMPTY(server);
362 }
363 
cddb_set_http_proxy_server_name(cddb_conn_t * c,const char * server)364 void cddb_set_http_proxy_server_name(cddb_conn_t *c, const char *server)
365 {
366     FREE_NOT_NULL(c->http_proxy_server);
367     c->http_proxy_server = strdup(server);
368 }
369 
cddb_get_http_proxy_server_port(const cddb_conn_t * c)370 unsigned int cddb_get_http_proxy_server_port(const cddb_conn_t *c)
371 {
372     if (c) {
373         return c->http_proxy_server_port;
374     }
375     return 0;
376 }
377 
cddb_set_http_proxy_server_port(cddb_conn_t * c,int port)378 void cddb_set_http_proxy_server_port(cddb_conn_t *c, int port)
379 {
380     c->http_proxy_server_port = port;
381 }
382 
cddb_set_http_proxy_auth(cddb_conn_t * c,const char * username,const char * password)383 static void cddb_set_http_proxy_auth(cddb_conn_t *c,
384                                      const char *username, const char *password)
385 {
386     int len;
387     char *auth, *auth_b64;
388 
389     FREE_NOT_NULL(c->http_proxy_auth);
390     len = 0;
391     if (username != NULL) {
392         len += strlen(username);
393     }
394     if (password != NULL) {
395         len += strlen(password);
396     }
397     len +=  2;                               /* colon and 0-byte */;
398     auth = (char*)malloc(len);
399     snprintf(auth, len, "%s:%s",
400                         (username ? username : ""),
401                         (password ? password : ""));
402     auth_b64 = (char*)malloc(len * 2); /* certainly big enough */
403     cddb_b64_encode(auth_b64, auth);
404     c->http_proxy_auth = strdup(auth_b64);
405     free(auth_b64);
406     free(auth);
407 }
408 
cddb_get_http_proxy_username(const cddb_conn_t * c)409 const char *cddb_get_http_proxy_username(const cddb_conn_t *c)
410 {
411     const char *user = NULL;
412 
413     if (c) {
414         user = c->http_proxy_username;
415     }
416     RETURN_STR_OR_EMPTY(user);
417 }
418 
cddb_set_http_proxy_username(cddb_conn_t * c,const char * username)419 void cddb_set_http_proxy_username(cddb_conn_t *c, const char *username)
420 {
421     FREE_NOT_NULL(c->http_proxy_username);
422     if (username) {
423         c->http_proxy_username = strdup(username);
424     }
425     /* remake authentication credentials */
426     cddb_set_http_proxy_auth(c, c->http_proxy_username, c->http_proxy_password);
427 }
428 
cddb_get_http_proxy_password(const cddb_conn_t * c)429 const char *cddb_get_http_proxy_password(const cddb_conn_t *c)
430 {
431     const char *password = NULL;
432 
433     if (c) {
434         password = c->http_proxy_password;
435     }
436     RETURN_STR_OR_EMPTY(password);
437 }
438 
cddb_set_http_proxy_password(cddb_conn_t * c,const char * password)439 void cddb_set_http_proxy_password(cddb_conn_t *c, const char *password)
440 {
441     FREE_NOT_NULL(c->http_proxy_password);
442     if (password) {
443         c->http_proxy_password = strdup(password);
444     }
445     /* remake authentication credentials */
446     cddb_set_http_proxy_auth(c, c->http_proxy_username, c->http_proxy_password);
447 }
448 
cddb_set_http_proxy_credentials(cddb_conn_t * c,const char * username,const char * password)449 void cddb_set_http_proxy_credentials(cddb_conn_t* c,
450                                      const char *username, const char* password)
451 {
452     /* remove cleartext credentials */
453     FREE_NOT_NULL(c->http_proxy_username);
454     FREE_NOT_NULL(c->http_proxy_password);
455     /* remake authentication credentials */
456     cddb_set_http_proxy_auth(c, username, password);
457 }
458 
cddb_errno(const cddb_conn_t * c)459 cddb_error_t cddb_errno(const cddb_conn_t *c)
460 {
461     if (c) {
462         return c->errnum;
463     }
464     return CDDB_ERR_INVALID;
465 }
466 
cddb_set_client(cddb_conn_t * c,const char * cname,const char * cversion)467 void cddb_set_client(cddb_conn_t *c, const char *cname, const char *cversion)
468 {
469     if (cname && cversion) {
470         FREE_NOT_NULL(c->cname);
471         FREE_NOT_NULL(c->cversion);
472         c->cname = strdup(cname);
473         c->cversion = strdup(cversion);
474     }
475 }
476 
cddb_set_email_address(cddb_conn_t * c,const char * email)477 int cddb_set_email_address(cddb_conn_t *c, const char *email)
478 {
479     char *at;
480     int len;
481 
482     cddb_log_debug("cddb_set_email_address()");
483     if ((email == NULL) ||
484         ((at = strchr(email, '@')) == NULL) ||
485         (at == email) ||
486         (*(at+1) == '\0')) {
487         cddb_errno_log_error(c, CDDB_ERR_EMAIL_INVALID);
488         return FALSE;
489     }
490     /* extract user name */
491     FREE_NOT_NULL(c->user);
492     len = at - email;
493     c->user = malloc(len + 1);
494     strncpy(c->user, email, len);
495     c->user[len] = '\0';
496     /* extract host name */
497     at++;
498     FREE_NOT_NULL(c->hostname);
499     c->hostname = strdup(at);
500     cddb_log_debug("...user name = '%s'", c->user);
501     cddb_log_debug("...host name = '%s'", c->hostname);
502 
503     return TRUE;
504 }
505 
cddb_cache_mode(const cddb_conn_t * c)506 cddb_cache_mode_t cddb_cache_mode(const cddb_conn_t *c)
507 {
508     if (c) {
509         return c->use_cache;
510     }
511     return CACHE_OFF;
512 }
513 
cddb_cache_enable(cddb_conn_t * c)514 void cddb_cache_enable(cddb_conn_t *c)
515 {
516     if (c) {
517         c->use_cache = CACHE_ON;
518     }
519 }
520 
cddb_cache_only(cddb_conn_t * c)521 void cddb_cache_only(cddb_conn_t *c)
522 {
523     if (c) {
524         c->use_cache = CACHE_ONLY;
525     }
526 }
527 
cddb_cache_disable(cddb_conn_t * c)528 void cddb_cache_disable(cddb_conn_t *c)
529 {
530     if (c) {
531         c->use_cache = CACHE_OFF;
532     }
533 }
534 
cddb_cache_get_dir(const cddb_conn_t * c)535 const char *cddb_cache_get_dir(const cddb_conn_t *c)
536 {
537     if (c) {
538         return c->cache_dir;;
539     }
540     return NULL;
541 }
542 
cddb_cache_set_dir(cddb_conn_t * c,const char * dir)543 int cddb_cache_set_dir(cddb_conn_t *c, const char *dir)
544 {
545     char *home;
546 
547     cddb_log_debug("cddb_cache_set_dir()");
548     if (dir) {
549         FREE_NOT_NULL(c->cache_dir);
550         if (dir[0] == '~') {
551             /* expand ~ to $HOME */
552             home = getenv("HOME");
553             if (home) {
554                 c->cache_dir = (char*)malloc(strlen(home) + strlen(dir));
555                 sprintf(c->cache_dir, "%s%s", home, dir + 1);
556             }
557         } else {
558             c->cache_dir = strdup(dir);
559         }
560     }
561     return TRUE;
562 }
563 
cddb_first_site(cddb_conn_t * c)564 const cddb_site_t *cddb_first_site(cddb_conn_t *c)
565 {
566     elem_t *e;
567 
568     e = list_first(c->sites_data);
569     if (e) {
570         return element_data(e);
571     }
572     return NULL;
573 }
574 
cddb_next_site(cddb_conn_t * c)575 const cddb_site_t *cddb_next_site(cddb_conn_t *c)
576 {
577     elem_t *e;
578 
579     e = list_next(c->sites_data);
580     if (e) {
581         return element_data(e);
582     }
583     return NULL;
584 }
585 
cddb_search_set_fields(cddb_conn_t * c,unsigned int fields)586 void cddb_search_set_fields(cddb_conn_t *c, unsigned int fields)
587 {
588     c->srch.fields = fields;
589 }
590 
cddb_search_set_categories(cddb_conn_t * c,unsigned int cats)591 void cddb_search_set_categories(cddb_conn_t *c, unsigned int cats)
592 {
593     c->srch.cats = cats;
594 }
595 
596 /* --- connecting / disconnecting --- */
597 
598 
cddb_handshake(cddb_conn_t * c)599 static int cddb_handshake(cddb_conn_t *c)
600 {
601     char *msg;
602     int code;
603 
604     cddb_log_debug("cddb_handshake()");
605     /* check sign-on banner */
606     switch (code = cddb_get_response_code(c, &msg)) {
607         case  -1:
608             return FALSE;
609         case 200:                   /* read/write */
610         case 201:                   /* read only */
611             break;
612         case 432:
613         case 433:
614         case 434:
615             cddb_errno_log_error(c, CDDB_ERR_PERMISSION_DENIED);
616             return FALSE;
617     }
618 
619     /* send hello and check response */
620     if (!cddb_send_cmd(c, CMD_HELLO, c->user, c->hostname, c->cname, c->cversion)) {
621         return FALSE;
622     }
623     switch (code = cddb_get_response_code(c, &msg)) {
624         case  -1:
625             return FALSE;
626         case 200:                   /* ok */
627         case 402:                   /* already shook hands */
628             break;
629         case 431:
630             cddb_errno_log_error(c, CDDB_ERR_PERMISSION_DENIED);
631             return FALSE;
632     }
633 
634     /* set protocol level */
635     if (!cddb_send_cmd(c, CMD_PROTO, DEFAULT_PROTOCOL_VERSION)) {
636         return FALSE;
637     }
638     switch (code = cddb_get_response_code(c, &msg)) {
639         case  -1:
640             return FALSE;
641         case 200:                   /* ok */
642         case 201:                   /* ok */
643         case 502:                   /* protocol already set */
644             break;
645         case 501:                   /* illegal protocol level */
646             /* ignore */
647             break;
648     }
649 
650     cddb_errno_set(c, CDDB_ERR_OK);
651     return TRUE;
652 }
653 
cddb_connect(cddb_conn_t * c)654 int cddb_connect(cddb_conn_t *c)
655 {
656     int rv = TRUE;
657 
658     cddb_log_debug("cddb_connect()");
659     if (!CONNECTION_OK(c)) {
660         struct hostent *he;
661 
662         /* resolve host name */
663         if (c->is_http_proxy_enabled) {
664             /* use HTTP proxy server name */
665             he = timeout_gethostbyname(c->http_proxy_server, c->timeout);
666             c->sa.sin_port = htons(c->http_proxy_server_port);
667         } else {
668             /* use CDDB server name */
669             he = timeout_gethostbyname(c->server_name, c->timeout);
670             c->sa.sin_port = htons(c->server_port);
671         }
672         if (he == NULL) {
673             cddb_errno_log_error(c, CDDB_ERR_UNKNOWN_HOST_NAME);
674             return FALSE;
675         }
676         /* initialize socket address */
677         c->sa.sin_family = AF_INET;
678         c->sa.sin_addr = *((struct in_addr*)he->h_addr);
679         memset(&(c->sa.sin_zero), 0, sizeof(c->sa.sin_zero));
680 
681         if ((c->socket  = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
682             cddb_errno_log_error(c, CDDB_ERR_CONNECT);
683             return FALSE;
684         }
685 
686         rv =  timeout_connect(c->socket, (struct sockaddr*)&(c->sa),
687                               sizeof(struct sockaddr), c->timeout);
688         if (rv == -1) {
689             cddb_errno_log_error(c, CDDB_ERR_CONNECT);
690             return FALSE;
691         }
692 
693         if (!c->is_http_enabled) {
694             /* send handshake message to CDDB server (CDDBP only) */
695             return cddb_handshake(c);
696         }
697     }
698 
699     cddb_errno_set(c, CDDB_ERR_OK);
700     return TRUE;
701 }
702 
cddb_disconnect(cddb_conn_t * c)703 void cddb_disconnect(cddb_conn_t *c)
704 {
705     cddb_log_debug("cddb_disconnect()");
706     if (CONNECTION_OK(c)) {
707         close(c->socket);
708         c->socket = -1;
709     }
710     cddb_errno_set(c, CDDB_ERR_OK);
711 }
712 
713 
714 /* --- miscellaneous --- */
715 
716 
cddb_clone_proxy(cddb_conn_t * dst,cddb_conn_t * src)717 void cddb_clone_proxy(cddb_conn_t *dst, cddb_conn_t *src)
718 {
719     if (cddb_is_http_proxy_enabled(src)) {
720         /* XXX: optimize? */
721         FREE_NOT_NULL(dst->http_proxy_server);
722         if (src->http_proxy_server) {
723             dst->http_proxy_server = strdup(src->http_proxy_server);
724         }
725         dst->http_proxy_server_port = src->http_proxy_server_port;
726         FREE_NOT_NULL(dst->http_proxy_auth);
727         if (src->http_proxy_auth) {
728             dst->http_proxy_auth = strdup(src->http_proxy_auth);
729         }
730         cddb_http_proxy_enable(dst);
731     }
732 }
733