summaryrefslogtreecommitdiff
path: root/src/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/message.c')
-rw-r--r--src/message.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/message.c b/src/message.c
new file mode 100644
index 0000000..b0e33e1
--- /dev/null
+++ b/src/message.c
@@ -0,0 +1,138 @@
+/**
+ * @file message.c SIP MESSAGE -- RFC 3428
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "core.h"
+
+
+static struct sip_lsnr *lsnr;
+static message_recv_h *recvh;
+static void *recvarg;
+
+
+static void handle_message(struct ua *ua, const struct sip_msg *msg)
+{
+ static const char *ctype_text = "text/plain";
+ struct pl mtype;
+ (void)ua;
+
+ if (re_regex(msg->ctype.p, msg->ctype.l, "[^;]+", &mtype))
+ mtype = msg->ctype;
+
+ if (0==pl_strcasecmp(&mtype, ctype_text) && recvh) {
+ recvh(&msg->from.auri, &msg->ctype, msg->mb, recvarg);
+ (void)sip_reply(uag_sip(), msg, 200, "OK");
+ }
+ else {
+ (void)sip_replyf(uag_sip(), msg, 415, "Unsupported Media Type",
+ "Accept: %s\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n",
+ ctype_text);
+ }
+}
+
+
+static bool request_handler(const struct sip_msg *msg, void *arg)
+{
+ struct ua *ua;
+
+ (void)arg;
+
+ if (pl_strcmp(&msg->met, "MESSAGE"))
+ return false;
+
+ ua = uag_find(&msg->uri.user);
+ if (!ua) {
+ (void)sip_treply(NULL, uag_sip(), msg, 404, "Not Found");
+ return true;
+ }
+
+ handle_message(ua, msg);
+
+ return true;
+}
+
+
+static void resp_handler(int err, const struct sip_msg *msg, void *arg)
+{
+ struct ua *ua = arg;
+
+ (void)ua;
+
+ if (err) {
+ (void)re_fprintf(stderr, " \x1b[31m%m\x1b[;m\n", err);
+ return;
+ }
+
+ if (msg->scode >= 300) {
+ (void)re_fprintf(stderr, " \x1b[31m%u %r\x1b[;m\n",
+ msg->scode, &msg->reason);
+ }
+}
+
+
+int message_init(message_recv_h *h, void *arg)
+{
+ int err;
+
+ err = sip_listen(&lsnr, uag_sip(), true, request_handler, NULL);
+ if (err)
+ return err;
+
+ recvh = h;
+ recvarg = arg;
+
+ return 0;
+}
+
+
+void message_close(void)
+{
+ lsnr = mem_deref(lsnr);
+}
+
+
+/**
+ * Send SIP instant MESSAGE to a peer
+ *
+ * @param ua User-Agent object
+ * @param peer Peer SIP Address
+ * @param msg Message to send
+ *
+ * @return 0 if success, otherwise errorcode
+ */
+int message_send(struct ua *ua, const char *peer, const char *msg)
+{
+ struct sip_addr addr;
+ struct pl pl;
+ char *uri = NULL;
+ int err = 0;
+
+ if (!ua || !peer || !msg)
+ return EINVAL;
+
+ pl_set_str(&pl, peer);
+
+ err = sip_addr_decode(&addr, &pl);
+ if (err)
+ return err;
+
+ err = pl_strdup(&uri, &addr.auri);
+ if (err)
+ return err;
+
+ err = sip_req_send(ua, "MESSAGE", uri, resp_handler, ua,
+ "Accept: text/plain\r\n"
+ "Content-Type: text/plain\r\n"
+ "Content-Length: %zu\r\n"
+ "\r\n%s",
+ str_len(msg), msg);
+
+ mem_deref(uri);
+
+ return err;
+}