static bool setup_socket (xmmsc_connection_t *c, xmmsc_vis_udp_t *t, int32_t id, int32_t port) { struct addrinfo hints; struct addrinfo *result, *rp; char *host; char portstr[10]; char packet[1 + sizeof(int32_t)]; int32_t* packet_id = (int32_t*)&packet[1]; sprintf (portstr, "%d", port); memset (&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = 0; hints.ai_protocol = 0; host = xmms_ipc_hostname (c->path); if (!host) { host = strdup ("localhost"); } if (xmms_getaddrinfo (host, portstr, &hints, &result) != 0) { c->error = strdup("Couldn't setup socket!"); return false; } free (host); for (rp = result; rp != NULL; rp = rp->ai_next) { if (!xmms_socket_valid (t->socket[0] = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol))) { continue; } if (connect (t->socket[0], rp->ai_addr, rp->ai_addrlen) != -1) { /* Windows doesn't support MSG_DONTWAIT. Why should it? Ripping off BSD, but without mutilating it? No! */ xmms_socket_set_nonblock (t->socket[0]); /* init fallback socket for timing stuff */ t->socket[1] = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); connect (t->socket[1], rp->ai_addr, rp->ai_addrlen); break; } else { xmms_socket_close (t->socket[0]); } } if (rp == NULL) { c->error = strdup("Could not connect!"); return false; } xmms_freeaddrinfo (result); packet[0] = 'H'; *packet_id = htonl (id); send (t->socket[0], &packet, sizeof (packet), 0); t->timediff = udp_timediff (id, t->socket[1]); /* printf ("diff: %f\n", t->timediff); */ return true; }
static xmms_ipc_transport_t * xmms_ipc_tcp_accept (xmms_ipc_transport_t *transport) { xmms_socket_t fd; struct sockaddr sockaddr; socklen_t socklen; x_return_val_if_fail (transport, NULL); socklen = sizeof (sockaddr); fd = accept (transport->fd, &sockaddr, &socklen); if (xmms_socket_valid (fd)) { int _reuseaddr = 1; int _nodelay = 1; const char* reuseaddr = (const char*)&_reuseaddr; const char* nodelay = (const char*)&_nodelay; xmms_ipc_transport_t *ret; if (!xmms_socket_set_nonblock (fd)) { close (fd); return NULL; } setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr, sizeof (_reuseaddr)); setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, nodelay, sizeof (_nodelay)); ret = x_new0 (xmms_ipc_transport_t, 1); ret->fd = fd; ret->read_func = xmms_ipc_tcp_read; ret->write_func = xmms_ipc_tcp_write; ret->destroy_func = xmms_ipc_tcp_destroy; return ret; } return NULL; }
xmms_ipc_transport_t * xmms_ipc_tcp_client_init (const xmms_url_t *url, int ipv6) { xmms_socket_t fd = -1; xmms_ipc_transport_t *ipct; struct addrinfo hints; struct addrinfo *addrinfo; struct addrinfo *addrinfos; int gai_errno; if (!xmms_sockets_initialize ()) { return NULL; } memset (&hints, 0, sizeof (hints)); hints.ai_flags = 0; hints.ai_family = url->host[0] ? (ipv6 ? PF_INET6 : PF_INET) : PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((gai_errno = xmms_getaddrinfo (url->host[0] ? url->host : NULL, url->port[0] ? url->port : XMMS_STRINGIFY (XMMS_DEFAULT_TCP_PORT), &hints, &addrinfos))) { return NULL; } for (addrinfo = addrinfos; addrinfo; addrinfo = addrinfo->ai_next) { int _reuseaddr = 1; const char* reuseaddr = (const char*)&_reuseaddr; fd = socket (addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); if (!xmms_socket_valid (fd)) { return NULL; } setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, reuseaddr, sizeof (_reuseaddr)); if (connect (fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == 0) { break; } close (fd); } xmms_freeaddrinfo (addrinfos); if (!addrinfo) { return NULL; } assert (fd != -1); if (!xmms_socket_set_nonblock (fd)) { close (fd); return NULL; } ipct = x_new0 (xmms_ipc_transport_t, 1); ipct->fd = fd; ipct->path = strdup (url->host); ipct->read_func = xmms_ipc_tcp_read; ipct->write_func = xmms_ipc_tcp_write; ipct->destroy_func = xmms_ipc_tcp_destroy; return ipct; }