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 void xmms_visualization_destroy (xmms_object_t *object) { XMMS_DBG ("Deactivating visualization object."); xmms_object_unref (vis->output); /* TODO: assure that the xform is already dead! */ g_mutex_clear (&vis->clientlock); xmms_log_debug ("starting cleanup of %d vis clients", vis->clientc); for (; vis->clientc > 0; --vis->clientc) { delete_client (vis->clientc - 1); } if (xmms_socket_valid (vis->socket)) { /* it seems there is no way to remove the watch */ g_io_channel_shutdown (vis->socketio, FALSE, NULL); xmms_socket_close (vis->socket); } xmms_visualization_unregister_ipc_commands (); }
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; }
int32_t init_udp (xmms_visualization_t *vis, int32_t id, xmms_error_t *err) { // TODO: we need the currently used port, not only the default one! */ int32_t port = XMMS_DEFAULT_TCP_PORT; xmms_vis_client_t *c; // setup socket if needed if (!xmms_socket_valid (vis->socket)) { struct addrinfo hints; struct addrinfo *result, *rp; int s; memset (&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; hints.ai_protocol = 0; if ((s = getaddrinfo (NULL, G_STRINGIFY (XMMS_DEFAULT_TCP_PORT), &hints, &result)) != 0) { xmms_log_error ("Could not setup socket! getaddrinfo: %s", gai_strerror (s)); xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "Could not setup socket!"); return -1; } for (rp = result; rp != NULL; rp = rp->ai_next) { vis->socket = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (!xmms_socket_valid (vis->socket)) { continue; } if (bind (vis->socket, rp->ai_addr, rp->ai_addrlen) != -1) { break; } else { close (vis->socket); } } if (rp == NULL) { xmms_log_error ("Could not bind socket!"); xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "Could not bind socket!"); freeaddrinfo (result); return -1; } freeaddrinfo (result); /* register into mainloop: */ /* perhaps needed, perhaps not .. #ifdef __WIN32__ vis->socketio = g_io_channel_win32_new_socket (vis->socket); #else */ vis->socketio = g_io_channel_unix_new (vis->socket); /*#endif */ g_io_channel_set_encoding (vis->socketio, NULL, NULL); g_io_channel_set_buffered (vis->socketio, FALSE); g_io_add_watch (vis->socketio, G_IO_IN, (GIOFunc) udpwatcher, vis); } /* set up client structure */ x_fetch_client (id); c->type = VIS_UDP; memset (&c->transport.udp.addr, 0, sizeof (c->transport.udp.addr)); c->transport.udp.socket[0] = 0; x_release_client (); xmms_log_info ("Visualization client %d initialised using UDP", id); return port; }
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; }