#include "sx.h"
static void _sx_client_element_start(void *arg, const char *name, const char **atts) {
sx_t s = (sx_t) arg;
int tflag = 0, fflag = 0, vflag = 0, iflag = 0, i;
const char **attr;
sx_error_t sxe;
if(s->fail) return;
i = strlen(uri_STREAMS) + 7;
if(strlen(name) < i || strncmp(name, uri_STREAMS "|stream", i) != 0 || (name[i] != '\0' && name[i] != '|')) {
_sx_gen_error(sxe, SX_ERR_STREAM, "Stream error", "Expected stream start");
_sx_event(s, event_ERROR, (void *) &sxe);
_sx_error(s, stream_err_BAD_FORMAT, NULL);
s->fail = 1;
return;
}
attr = atts;
while(attr[0] != NULL) {
if(!tflag && strcmp(attr[0], "to") == 0) {
s->res_to = strdup(attr[1]);
tflag = 1;
}
if(!fflag && strcmp(attr[0], "from") == 0) {
s->res_from = strdup(attr[1]);
fflag = 1;
}
if(!vflag && strcmp(attr[0], "version") == 0) {
s->res_version = strdup(attr[1]);
vflag = 1;
}
if(!iflag && strcmp(attr[0], "id") == 0) {
s->id = strdup(attr[1]);
iflag = 1;
}
attr += 2;
}
s->depth++;
_sx_debug(ZONE, "stream response: to %s from %s version %s id %s", s->res_to, s->res_from, s->res_version, s->id);
XML_SetElementHandler(s->expat, (void *) _sx_element_start, (void *) _sx_element_end);
XML_SetCharacterDataHandler(s->expat, (void *) _sx_cdata);
XML_SetStartNamespaceDeclHandler(s->expat, (void *) _sx_namespace_start);
if(s->env != NULL)
for(i = 0; i < s->env->nplugins; i++)
if(s->env->plugins[i]->stream != NULL)
(s->env->plugins[i]->stream)(s, s->env->plugins[i]);
if(s->state < state_STREAM) {
_sx_state(s, state_STREAM);
_sx_event(s, event_STREAM, NULL);
}
}
static void _sx_client_element_end(void *arg, const char *name) {
sx_t s = (sx_t) arg;
if(s->fail) return;
s->depth--;
}
static void _sx_client_notify_header(sx_t s, void *arg) {
XML_SetElementHandler(s->expat, (void *) _sx_client_element_start, (void *) _sx_client_element_end);
_sx_state(s, state_STREAM_SENT);
_sx_debug(ZONE, "stream header sent, waiting for reply");
s->want_read = 1;
}
void sx_client_init(sx_t s, unsigned int flags, char *ns, char *to, char *from, char *version) {
sx_buf_t buf;
char *c;
int i, len;
assert((int) s);
if(s->state != state_NONE)
return;
_sx_debug(ZONE, "doing client init for sx %d", s->tag);
s->type = type_CLIENT;
s->flags = flags;
if(ns != NULL) s->ns = strdup(ns);
if(to != NULL) s->req_to = strdup(to);
if(from != NULL) s->req_from = strdup(from);
if(version != NULL) s->req_version = strdup(version);
if(s->env != NULL)
for(i = 0; i < s->env->nplugins; i++)
if(s->env->plugins[i]->client != NULL)
(s->env->plugins[i]->client)(s, s->env->plugins[i]);
_sx_debug(ZONE, "stream request: ns %s to %s from %s version %s", ns, to, from, version);
len = strlen(uri_STREAMS) + 52;
if(ns != NULL) len += 9 + strlen(ns);
if(to != NULL) len += 6 + strlen(to);
if(from != NULL) len += 8 + strlen(from);
if(version != NULL) len += 11 + strlen(version);
buf = _sx_buffer_new(NULL, len+1, _sx_client_notify_header, NULL);
c = buf->data;
strcpy(c, "<?xml version='1.0'?><stream:stream xmlns:stream='" uri_STREAMS "'");
if(ns != NULL) { c = strchr(c, '\0'); sprintf(c, " xmlns='%s'", ns); }
if(to != NULL) { c = strchr(c, '\0'); sprintf(c, " to='%s'", to); }
if(from != NULL) { c = strchr(c, '\0'); sprintf(c, " from='%s'", from); }
if(version != NULL) { c = strchr(c, '\0'); sprintf(c, " version='%s'", version); }
c = strchr(c, '\0'); sprintf(c, ">");
assert(buf->len == strlen(buf->data)+1);
buf->len --;
if(s->env != NULL)
for(i = 0; i < s->env->nplugins; i++)
if(s->env->plugins[i]->header != NULL)
(s->env->plugins[i]->header)(s, s->env->plugins[i], buf);
_sx_debug(ZONE, "prepared stream header: %.*s", buf->len, buf->data);
jqueue_push(s->wbufq, buf, 0);
s->want_write = 1;
_sx_event(s, event_WANT_WRITE, NULL);
}