#include <limits.h>
#include <polyp/sample.h>
+#include <polyp/timeval.h>
+#include <polyp/utf8.h>
+#include <polyp/xmalloc.h>
+
#include <polypcore/esound.h>
#include <polypcore/memblock.h>
#include <polypcore/client.h>
#include <polypcore/sample-util.h>
#include <polypcore/authkey.h>
#include <polypcore/namereg.h>
-#include <polypcore/xmalloc.h>
#include <polypcore/log.h>
-#include <polypcore/util.h>
+#include <polypcore/core-util.h>
+#include <polypcore/core-error.h>
#include "endianmacros.h"
pa_source_output *source_output;
pa_memblockq *input_memblockq, *output_memblockq;
pa_defer_event *defer_event;
+
+ char *original_name;
struct {
pa_memblock *current_memblock;
{ 0, esd_proto_get_latency, "get latency" }
};
-
static void connection_free(struct connection *c) {
assert(c);
pa_idxset_remove_by_data(c->protocol->connections, c, NULL);
if (c->auth_timeout_event)
c->protocol->core->mainloop->time_free(c->auth_timeout_event);
-
+
+ pa_xfree(c->original_name);
pa_xfree(c);
}
}
static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
- char name[ESD_NAME_MAX];
+ char name[ESD_NAME_MAX], *utf8_name;
int32_t format, rate;
pa_sink *sink;
pa_sample_spec ss;
strncpy(name, data, sizeof(name));
name[sizeof(name)-1] = 0;
-
- pa_client_set_name(c->client, name);
+ utf8_name = pa_utf8_filter(name);
+
+ pa_client_set_name(c->client, utf8_name);
+ c->original_name = pa_xstrdup(name);
assert(!c->sink_input && !c->input_memblockq);
- c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1);
+ c->sink_input = pa_sink_input_new(sink, __FILE__, utf8_name, &ss, NULL, NULL, 0, -1);
+
+ pa_xfree(utf8_name);
CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
}
static int esd_proto_stream_record(struct connection *c, esd_proto_t request, const void *data, size_t length) {
- char name[ESD_NAME_MAX];
+ char name[ESD_NAME_MAX], *utf8_name;
int32_t format, rate;
pa_source *source;
pa_sample_spec ss;
strncpy(name, data, sizeof(name));
name[sizeof(name)-1] = 0;
- pa_client_set_name(c->client, name);
+ utf8_name = pa_utf8_filter(name);
+ pa_client_set_name(c->client, utf8_name);
+ pa_xfree(utf8_name);
+
+ c->original_name = pa_xstrdup(name);
assert(!c->output_memblockq && !c->source_output);
- if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) {
+ if (!(c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &ss, NULL, -1))) {
pa_log(__FILE__": failed to create source output");
return -1;
}
}
static int esd_proto_all_info(struct connection *c, esd_proto_t request, const void *data, size_t length) {
- uint8_t *response;
size_t t, k, s;
struct connection *conn;
uint32_t idx = PA_IDXSET_INVALID;
assert(t >= k*2+s);
if (conn->sink_input) {
+ pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input);
rate = conn->sink_input->sample_spec.rate;
- lvolume = (conn->sink_input->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM;
- rvolume = (conn->sink_input->volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM;
+ lvolume = (volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM;
+ rvolume = (volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM;
format = format_native2esd(&conn->sink_input->sample_spec);
}
connection_write(c, &id, sizeof(int32_t));
/* name */
- assert(conn->client);
- strncpy(name, conn->client->name, ESD_NAME_MAX);
+ memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
+ if (conn->original_name)
+ strncpy(name, conn->original_name, ESD_NAME_MAX);
+ else if (conn->client && conn->client->name)
+ strncpy(name, conn->client->name, ESD_NAME_MAX);
connection_write(c, name, ESD_NAME_MAX);
/* rate */
}
assert(t == s*(nsamples+1)+k);
- response += k;
t -= k;
connection_write(c, terminator, k);
connection_write(c, &id, sizeof(int32_t));
/* name */
+ memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0)
strncpy(name, ce->name+sizeof(SCACHE_PREFIX)-1, ESD_NAME_MAX);
else
rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, rvolume);
data = (const char*)data + sizeof(uint32_t);
- if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) {
- assert(conn->sink_input);
- conn->sink_input->volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
- conn->sink_input->volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
- conn->sink_input->volume.channels = 2;
+ if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx)) && conn->sink_input) {
+ pa_cvolume volume;
+ volume.values[0] = (lvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
+ volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
+ volume.channels = 2;
+ pa_sink_input_set_volume(conn->sink_input, &volume);
ok = 1;
} else
ok = 0;
strcpy(name, SCACHE_PREFIX);
strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
name[sizeof(name)-1] = 0;
+
+ CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
assert(!c->scache.memchunk.memblock);
c->scache.memchunk.memblock = pa_memblock_new(sc_length, c->protocol->core->memblock_stat);
strncpy(name+sizeof(SCACHE_PREFIX)-1, data, ESD_NAME_MAX);
name[sizeof(name)-1] = 0;
+ CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
+
ok = -1;
if ((idx = pa_scache_get_id_by_name(c->protocol->core, name)) != PA_IDXSET_INVALID)
ok = idx + 1;
assert(c->read_data_length < sizeof(c->request));
if ((r = pa_iochannel_read(c->io, ((uint8_t*) &c->request) + c->read_data_length, sizeof(c->request) - c->read_data_length)) <= 0) {
- pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF");
+ pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
}
assert(c->read_data && c->read_data_length < handler->data_length);
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) {
- pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF");
+ pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
}
assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length);
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) {
- pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF");
+ pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
}
}
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) {
- pa_log_debug(__FILE__": read() failed: %s", r < 0 ? strerror(errno) : "EOF");
+ pa_log_debug(__FILE__": read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
}
assert(c->write_data_index < c->write_data_length);
if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
- pa_log(__FILE__": write() failed: %s", strerror(errno));
+ pa_log(__FILE__": write(): %s", pa_cstrerror(errno));
return -1;
}
if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
pa_memblock_unref(chunk.memblock);
- pa_log(__FILE__": write(): %s", strerror(errno));
+ pa_log(__FILE__": write(): %s", pa_cstrerror(errno));
return -1;
}
c->scache.memchunk.memblock = NULL;
c->scache.name = NULL;
+ c->original_name = NULL;
+
if (!c->authorized) {
struct timeval tv;
pa_gettimeofday(&tv);