00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <stdlib.h>
00018 #include <unistd.h>
00019 #include "common.h"
00020
00021 static gboolean
00022 udpwatcher (GIOChannel *src, GIOCondition cond, xmms_visualization_t *vis)
00023 {
00024 struct sockaddr_storage from;
00025 socklen_t sl = sizeof (from);
00026 xmmsc_vis_udp_timing_t packet_d;
00027 char* packet = packet_init_timing (&packet_d);
00028 if ((recvfrom (vis->socket, packet, packet_d.size, 0, (struct sockaddr *)&from, &sl)) > 0) {
00029 if (*packet_d.__unaligned_type == 'H') {
00030 xmms_vis_client_t *c;
00031 int32_t id;
00032
00033 XMMSC_VIS_UNALIGNED_READ (id, packet_d.__unaligned_id, int32_t);
00034 id = ntohl (id);
00035
00036
00037
00038
00039
00040
00041
00042 g_mutex_lock (vis->clientlock);
00043 c = get_client (id);
00044 if (!c || c->type != VIS_UDP) {
00045 g_mutex_unlock (vis->clientlock);
00046 return TRUE;
00047 }
00048
00049 memcpy (&c->transport.udp.addr, &from, sizeof (from));
00050 c->transport.udp.socket[0] = 1;
00051 c->transport.udp.grace = 2000;
00052 g_mutex_unlock (vis->clientlock);
00053 } else if (*packet_d.__unaligned_type == 'T') {
00054 struct timeval time;
00055 xmms_vis_client_t *c;
00056 int32_t id;
00057
00058 XMMSC_VIS_UNALIGNED_READ (id, packet_d.__unaligned_id, int32_t);
00059 id = ntohl (id);
00060
00061 g_mutex_lock (vis->clientlock);
00062 c = get_client (id);
00063 if (!c || c->type != VIS_UDP) {
00064 g_mutex_unlock (vis->clientlock);
00065 free (packet);
00066 return TRUE;
00067 }
00068 c->transport.udp.grace = 2000;
00069 g_mutex_unlock (vis->clientlock);
00070
00071
00072 gettimeofday (&time, NULL);
00073
00074 struct timeval cts, sts;
00075
00076 XMMSC_VIS_UNALIGNED_READ (cts.tv_sec, &packet_d.__unaligned_clientstamp[0], int32_t);
00077 XMMSC_VIS_UNALIGNED_READ (cts.tv_usec, &packet_d.__unaligned_clientstamp[1], int32_t);
00078 cts.tv_sec = ntohl (cts.tv_sec);
00079 cts.tv_usec = ntohl (cts.tv_usec);
00080
00081 sts.tv_sec = time.tv_sec - cts.tv_sec;
00082 sts.tv_usec = time.tv_usec - cts.tv_usec;
00083 if (sts.tv_usec < 0) {
00084 sts.tv_sec--;
00085 sts.tv_usec += 1000000;
00086 }
00087
00088 XMMSC_VIS_UNALIGNED_WRITE (&packet_d.__unaligned_serverstamp[0],
00089 (int32_t)htonl (sts.tv_sec), int32_t);
00090 XMMSC_VIS_UNALIGNED_WRITE (&packet_d.__unaligned_serverstamp[1],
00091 (int32_t)htonl (sts.tv_usec), int32_t);
00092
00093 sendto (vis->socket, packet, packet_d.size, 0, (struct sockaddr *)&from, sl);
00094
00095
00096
00097
00098 } else {
00099 xmms_log_error ("Received invalid UDP package!");
00100 }
00101 }
00102 free (packet);
00103 return TRUE;
00104 }
00105
00106 int32_t
00107 init_udp (xmms_visualization_t *vis, int32_t id, xmms_error_t *err)
00108 {
00109
00110 int32_t port = XMMS_DEFAULT_TCP_PORT;
00111 xmms_vis_client_t *c;
00112
00113
00114 if (!xmms_socket_valid (vis->socket)) {
00115 struct addrinfo hints;
00116 struct addrinfo *result, *rp;
00117 int s;
00118
00119 memset (&hints, 0, sizeof (hints));
00120 hints.ai_family = AF_UNSPEC;
00121 hints.ai_socktype = SOCK_DGRAM;
00122 hints.ai_flags = AI_PASSIVE;
00123 hints.ai_protocol = 0;
00124
00125 if ((s = getaddrinfo (NULL, G_STRINGIFY (XMMS_DEFAULT_TCP_PORT), &hints, &result)) != 0)
00126 {
00127 xmms_log_error ("Could not setup socket! getaddrinfo: %s", gai_strerror (s));
00128 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "Could not setup socket!");
00129 return -1;
00130 }
00131
00132 for (rp = result; rp != NULL; rp = rp->ai_next) {
00133 vis->socket = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
00134 if (!xmms_socket_valid (vis->socket)) {
00135 continue;
00136 }
00137 if (bind (vis->socket, rp->ai_addr, rp->ai_addrlen) != -1) {
00138 break;
00139 } else {
00140 close (vis->socket);
00141 }
00142 }
00143 if (rp == NULL) {
00144 xmms_log_error ("Could not bind socket!");
00145 xmms_error_set (err, XMMS_ERROR_NO_SAUSAGE, "Could not bind socket!");
00146 freeaddrinfo (result);
00147 return -1;
00148 }
00149 freeaddrinfo (result);
00150
00151
00152
00153
00154
00155 vis->socketio = g_io_channel_unix_new (vis->socket);
00156
00157 g_io_channel_set_encoding (vis->socketio, NULL, NULL);
00158 g_io_channel_set_buffered (vis->socketio, FALSE);
00159 g_io_add_watch (vis->socketio, G_IO_IN, (GIOFunc) udpwatcher, vis);
00160 }
00161
00162
00163 x_fetch_client (id);
00164 c->type = VIS_UDP;
00165 memset (&c->transport.udp.addr, 0, sizeof (c->transport.udp.addr));
00166 c->transport.udp.socket[0] = 0;
00167 x_release_client ();
00168
00169 xmms_log_info ("Visualization client %d initialised using UDP", id);
00170 return port;
00171 }
00172
00173 void
00174 cleanup_udp (xmmsc_vis_udp_t *t, xmms_socket_t socket)
00175 {
00176 socklen_t sl = sizeof (t->addr);
00177 char packet = 'K';
00178 sendto (socket, &packet, 1, 0, (struct sockaddr *)&t->addr, sl);
00179 }
00180
00181 gboolean
00182 write_udp (xmmsc_vis_udp_t *t, xmms_vis_client_t *c, int32_t id, struct timeval *time, int channels, int size, short *buf, int socket)
00183 {
00184 xmmsc_vis_udp_data_t packet_d;
00185 xmmsc_vischunk_t *__unaligned_dest;
00186 short res;
00187 int offset;
00188 char* packet;
00189
00190
00191 if (t->grace == 0) {
00192 delete_client (id);
00193 return FALSE;
00194 }
00195 if (t->socket == 0) {
00196 return FALSE;
00197 }
00198
00199 packet = packet_init_data (&packet_d);
00200 t->grace--;
00201 XMMSC_VIS_UNALIGNED_WRITE (packet_d.__unaligned_grace, htons (t->grace), uint16_t);
00202 __unaligned_dest = packet_d.__unaligned_data;
00203
00204 XMMSC_VIS_UNALIGNED_WRITE (&__unaligned_dest->timestamp[0],
00205 (int32_t)htonl (time->tv_sec), int32_t);
00206 XMMSC_VIS_UNALIGNED_WRITE (&__unaligned_dest->timestamp[1],
00207 (int32_t)htonl (time->tv_usec), int32_t);
00208
00209
00210 XMMSC_VIS_UNALIGNED_WRITE (&__unaligned_dest->format, (uint16_t)htons (c->format), uint16_t);
00211 res = fill_buffer (__unaligned_dest->data, &c->prop, channels, size, buf);
00212 XMMSC_VIS_UNALIGNED_WRITE (&__unaligned_dest->size, (uint16_t)htons (res), uint16_t);
00213
00214 offset = ((char*)&__unaligned_dest->data - (char*)__unaligned_dest);
00215
00216 sendto (socket, packet, XMMS_VISPACKET_UDP_OFFSET + offset + res * sizeof (int16_t), 0, (struct sockaddr *)&t->addr, sizeof (t->addr));
00217 free (packet);
00218
00219
00220 return TRUE;
00221 }