reorg: xmppipe_send*

master
Michael Santos 5 years ago
parent d6dcc88bc6
commit 895ad40ee2

@ -54,10 +54,7 @@ void xmppipe_stream_close(xmppipe_state_t *);
void xmppipe_muc_join(xmppipe_state_t *);
void xmppipe_muc_unlock(xmppipe_state_t *);
void xmppipe_muc_subject(xmppipe_state_t *, char *);
void xmppipe_send_stanza(xmppipe_state_t *, char *, size_t);
void xmppipe_send_stanza_fmt(xmppipe_state_t *state, char *buf, size_t len);
void xmppipe_send_message(xmppipe_state_t *, char *, char *, char *, size_t);
void xmppipe_send(xmppipe_state_t *, xmpp_stanza_t *const);
void xmppipe_ping(xmppipe_state_t *);
enum {
@ -1118,179 +1115,6 @@ xmppipe_muc_subject(xmppipe_state_t *state, char *buf)
(void)xmpp_stanza_release(message);
}
void
xmppipe_send_stanza(xmppipe_state_t *state, char *buf, size_t len)
{
switch (state->format) {
case XMPPIPE_FMT_TEXT:
xmppipe_send_message(state,
state->out,
(state->opt & XMPPIPE_OPT_GROUPCHAT) ? "groupchat" : "chat",
buf, len);
return;
case XMPPIPE_FMT_CSV:
xmppipe_send_stanza_fmt(state, buf, len);
break;
default:
if (state->verbose)
(void)fprintf(stderr, "unsupported format: %d\n", state->format);
return;
}
}
void
xmppipe_send_stanza_fmt(xmppipe_state_t *state, char *buf, size_t len)
{
char *to = NULL;
char *type = NULL;
char *default_type;
int i;
size_t n;
char *tmp;
char *start;
char *end;
char *body = NULL;
int valid = 0;
default_type = (state->opt & XMPPIPE_OPT_GROUPCHAT) ? "groupchat" : "chat";
tmp = xmppipe_strdup(buf);
start = tmp;
/* trailing newline */
end = strchr(start, '\n');
if (end != NULL)
*end = '\0';
for (i = 0; start != NULL; i++) {
end = strchr(start, ':');
if (end != NULL)
*end++ = '\0';
n = strlen(start);
if (state->verbose)
(void)fprintf(stderr, "message:%d:%s\n", i,
n == 0 ? "<empty>" : start);
switch (i) {
case 0:
if (n != 1) {
if (state->verbose)
(void)fprintf(stderr, "stanza required\n");
goto XMPPIPE_DONE;
}
switch (start[0]) {
case 'm':
break;
case 'p':
/* unsupported: fall through */
default:
if (state->verbose)
(void)fprintf(stderr, "unsupported stanza: %c\n", start[0]);
goto XMPPIPE_DONE;
}
break;
case 1:
type = xmppipe_fmt_decode((n == 0) ? default_type : start);
if (type == NULL)
goto XMPPIPE_DONE;
break;
case 2:
to = xmppipe_fmt_decode((n == 0) ? state->out : start);
if (to == NULL)
goto XMPPIPE_DONE;
break;
case 3:
break;
case 4:
body = xmppipe_fmt_decode(start);
if (body == NULL)
goto XMPPIPE_DONE;
valid = 1;
break;
default:
goto XMPPIPE_DONE;
}
start = end;
}
XMPPIPE_DONE:
if (valid == 1)
xmppipe_send_message(state, to, type, body, strlen(body));
else
if (state->verbose)
(void)fprintf(stderr, "invalid input\n");
free(tmp);
free(type);
free(to);
free(body);
}
void
xmppipe_send_message(xmppipe_state_t *state, char *to, char *type, char *buf,
size_t len)
{
xmpp_stanza_t *message = NULL;
xmpp_stanza_t *body = NULL;
xmpp_stanza_t *text = NULL;
char *id = NULL;
id = xmpp_uuid_gen(state->ctx);
if (id == NULL) {
errx(EXIT_FAILURE, "unable to allocate message id");
}
message = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(message, "message");
xmppipe_stanza_set_type(message, type);
xmppipe_stanza_set_attribute(message, "to", to);
xmppipe_stanza_set_id(message, id);
body = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(body, "body");
text = xmppipe_stanza_new(state->ctx);
if (state->encode) {
size_t len = strlen(buf);
char *b64 = xmpp_base64_encode(state->ctx, (unsigned char *)buf, len);
if (b64 == NULL)
errx(EXIT_FAILURE, "encode: invalid input: %zu", len);
xmppipe_stanza_set_text(text, b64);
xmpp_free(state->ctx, b64);
}
else {
xmppipe_stanza_set_text(text, buf);
}
xmppipe_stanza_add_child(body, text);
xmppipe_stanza_add_child(message, body);
xmppipe_send(state, message);
(void)xmpp_stanza_release(message);
xmpp_free(state->ctx, id);
}
void
xmppipe_ping(xmppipe_state_t *state)
{
@ -1315,30 +1139,6 @@ xmppipe_ping(xmppipe_state_t *state)
state->keepalive_fail++;
}
void
xmppipe_send(xmppipe_state_t *state, xmpp_stanza_t *const stanza)
{
xmpp_stanza_t *r = NULL;
state->sm_request++;
xmpp_send(state->conn, stanza);
if (state->sm_enabled == 0)
return;
if (state->sm_request % state->sm_request_interval != 0)
return;
r = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(r, "r");
xmppipe_stanza_set_ns(r, "urn:xmpp:sm:3");
xmpp_send(state->conn, r);
state->sm_request_unack++;
(void)xmpp_stanza_release(r);
}
void
xmppipe_stream_close(xmppipe_state_t *state)
{

@ -103,6 +103,11 @@ typedef struct {
int handle_message(xmpp_conn_t * const, xmpp_stanza_t * const, void * const);
void xmppipe_send_stanza(xmppipe_state_t *, char *, size_t);
void xmppipe_send_stanza_fmt(xmppipe_state_t *state, char *buf, size_t len);
void xmppipe_send_message(xmppipe_state_t *, char *, char *, char *, size_t);
void xmppipe_send(xmppipe_state_t *, xmpp_stanza_t *const);
int xmppipe_fmt_init();
char *xmppipe_fmt_encode(const char *);
char *xmppipe_nfmt_encode(const char *, size_t);

@ -0,0 +1,212 @@
/* Copyright (c) 2019, Michael Santos <michael.santos@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "xmppipe.h"
void
xmppipe_send_stanza(xmppipe_state_t *state, char *buf, size_t len)
{
switch (state->format) {
case XMPPIPE_FMT_TEXT:
xmppipe_send_message(state,
state->out,
(state->opt & XMPPIPE_OPT_GROUPCHAT) ? "groupchat" : "chat",
buf, len);
return;
case XMPPIPE_FMT_CSV:
xmppipe_send_stanza_fmt(state, buf, len);
break;
default:
if (state->verbose)
(void)fprintf(stderr, "unsupported format: %d\n", state->format);
return;
}
}
void
xmppipe_send_stanza_fmt(xmppipe_state_t *state, char *buf, size_t len)
{
char *to = NULL;
char *type = NULL;
char *default_type;
int i;
size_t n;
char *tmp;
char *start;
char *end;
char *body = NULL;
int valid = 0;
default_type = (state->opt & XMPPIPE_OPT_GROUPCHAT) ? "groupchat" : "chat";
tmp = xmppipe_strdup(buf);
start = tmp;
/* trailing newline */
end = strchr(start, '\n');
if (end != NULL)
*end = '\0';
for (i = 0; start != NULL; i++) {
end = strchr(start, ':');
if (end != NULL)
*end++ = '\0';
n = strlen(start);
if (state->verbose)
(void)fprintf(stderr, "message:%d:%s\n", i,
n == 0 ? "<empty>" : start);
switch (i) {
case 0:
if (n != 1) {
if (state->verbose)
(void)fprintf(stderr, "stanza required\n");
goto XMPPIPE_DONE;
}
switch (start[0]) {
case 'm':
break;
case 'p':
/* unsupported: fall through */
default:
if (state->verbose)
(void)fprintf(stderr, "unsupported stanza: %c\n", start[0]);
goto XMPPIPE_DONE;
}
break;
case 1:
type = xmppipe_fmt_decode((n == 0) ? default_type : start);
if (type == NULL)
goto XMPPIPE_DONE;
break;
case 2:
to = xmppipe_fmt_decode((n == 0) ? state->out : start);
if (to == NULL)
goto XMPPIPE_DONE;
break;
case 3:
break;
case 4:
body = xmppipe_fmt_decode(start);
if (body == NULL)
goto XMPPIPE_DONE;
valid = 1;
break;
default:
goto XMPPIPE_DONE;
}
start = end;
}
XMPPIPE_DONE:
if (valid == 1)
xmppipe_send_message(state, to, type, body, strlen(body));
else
if (state->verbose)
(void)fprintf(stderr, "invalid input\n");
free(tmp);
free(type);
free(to);
free(body);
}
void
xmppipe_send_message(xmppipe_state_t *state, char *to, char *type, char *buf,
size_t len)
{
xmpp_stanza_t *message = NULL;
xmpp_stanza_t *body = NULL;
xmpp_stanza_t *text = NULL;
char *id = NULL;
id = xmpp_uuid_gen(state->ctx);
if (id == NULL) {
errx(EXIT_FAILURE, "unable to allocate message id");
}
message = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(message, "message");
xmppipe_stanza_set_type(message, type);
xmppipe_stanza_set_attribute(message, "to", to);
xmppipe_stanza_set_id(message, id);
body = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(body, "body");
text = xmppipe_stanza_new(state->ctx);
if (state->encode) {
size_t len = strlen(buf);
char *b64 = xmpp_base64_encode(state->ctx, (unsigned char *)buf, len);
if (b64 == NULL)
errx(EXIT_FAILURE, "encode: invalid input: %zu", len);
xmppipe_stanza_set_text(text, b64);
xmpp_free(state->ctx, b64);
}
else {
xmppipe_stanza_set_text(text, buf);
}
xmppipe_stanza_add_child(body, text);
xmppipe_stanza_add_child(message, body);
xmppipe_send(state, message);
(void)xmpp_stanza_release(message);
xmpp_free(state->ctx, id);
}
void
xmppipe_send(xmppipe_state_t *state, xmpp_stanza_t *const stanza)
{
xmpp_stanza_t *r = NULL;
state->sm_request++;
xmpp_send(state->conn, stanza);
if (state->sm_enabled == 0)
return;
if (state->sm_request % state->sm_request_interval != 0)
return;
r = xmppipe_stanza_new(state->ctx);
xmppipe_stanza_set_name(r, "r");
xmppipe_stanza_set_ns(r, "urn:xmpp:sm:3");
xmpp_send(state->conn, r);
state->sm_request_unack++;
(void)xmpp_stanza_release(r);
}
Loading…
Cancel
Save