mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 17:38:59 +00:00
Christmas Presence
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3083 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
|
||||
#include "ldl_compat.h"
|
||||
#include "libdingaling.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#define microsleep(x) apr_sleep(x * 1000)
|
||||
|
||||
@@ -89,6 +90,12 @@ struct ldl_buffer {
|
||||
int hit;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CS_NEW,
|
||||
CS_START,
|
||||
CS_CONNECTED
|
||||
} ldl_handle_state_t;
|
||||
|
||||
struct ldl_handle {
|
||||
iksparser *parser;
|
||||
iksid *acc;
|
||||
@@ -116,6 +123,7 @@ struct ldl_handle {
|
||||
apr_pool_t *pool;
|
||||
void *private_info;
|
||||
FILE *log_stream;
|
||||
ldl_handle_state_t state;
|
||||
};
|
||||
|
||||
struct ldl_session {
|
||||
@@ -125,6 +133,7 @@ struct ldl_session {
|
||||
char *initiator;
|
||||
char *them;
|
||||
char *ip;
|
||||
char *login;
|
||||
ldl_payload_t payloads[LDL_MAX_PAYLOADS];
|
||||
unsigned int payload_len;
|
||||
ldl_candidate_t candidates[LDL_MAX_CANDIDATES];
|
||||
@@ -193,7 +202,7 @@ char *ldl_session_get_id(ldl_session_t *session)
|
||||
|
||||
void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body)
|
||||
{
|
||||
ldl_handle_send_msg(session->handle, session->them, subject, body);
|
||||
ldl_handle_send_msg(session->handle, session->login, session->them, subject, body);
|
||||
}
|
||||
|
||||
ldl_status ldl_session_destroy(ldl_session_t **session_p)
|
||||
@@ -235,14 +244,21 @@ ldl_status ldl_session_create(ldl_session_t **session_p, ldl_handle_t *handle, c
|
||||
*session_p = NULL;
|
||||
return LDL_STATUS_MEMERR;
|
||||
}
|
||||
|
||||
memset(session, 0, sizeof(ldl_session_t));
|
||||
apr_pool_create(&session->pool, globals.memory_pool);
|
||||
session->id = apr_pstrdup(session->pool, id);
|
||||
session->them = apr_pstrdup(session->pool, them);
|
||||
if (me) {
|
||||
session->initiator = apr_pstrdup(session->pool, me);
|
||||
|
||||
//if (me) {
|
||||
//session->initiator = apr_pstrdup(session->pool, them);
|
||||
//}
|
||||
|
||||
if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
session->login = apr_pstrdup(session->pool, me);
|
||||
} else {
|
||||
session->login = apr_pstrdup(session->pool, handle->login);
|
||||
}
|
||||
|
||||
apr_hash_set(handle->sessions, session->id, APR_HASH_KEY_STRING, session);
|
||||
apr_hash_set(handle->sessions, session->them, APR_HASH_KEY_STRING, session);
|
||||
session->handle = handle;
|
||||
@@ -259,7 +275,7 @@ ldl_status ldl_session_create(ldl_session_t **session_p, ldl_handle_t *handle, c
|
||||
return LDL_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from, iks *xml, char *xtype)
|
||||
static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from, char *to, iks *xml, char *xtype)
|
||||
{
|
||||
ldl_session_t *session = NULL;
|
||||
ldl_signal_t signal = LDL_SIGNAL_NONE;
|
||||
@@ -267,7 +283,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
|
||||
char *msg = NULL;
|
||||
|
||||
if (!(session = apr_hash_get(handle->sessions, id, APR_HASH_KEY_STRING))) {
|
||||
ldl_session_create(&session, handle, id, from, initiator);
|
||||
ldl_session_create(&session, handle, id, from, to);
|
||||
if (!session) {
|
||||
return LDL_STATUS_MEMERR;
|
||||
}
|
||||
@@ -433,7 +449,7 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
|
||||
}
|
||||
|
||||
if (handle->session_callback && signal) {
|
||||
handle->session_callback(handle, session, signal, from, id, msg);
|
||||
handle->session_callback(handle, session, signal, to, from, id, msg);
|
||||
}
|
||||
|
||||
return LDL_STATUS_SUCCESS;
|
||||
@@ -441,10 +457,208 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
|
||||
|
||||
const char *marker = "TRUE";
|
||||
|
||||
static int on_disco_info(void *user_data, ikspak *pak)
|
||||
{
|
||||
ldl_handle_t *handle = user_data;
|
||||
|
||||
if (pak->subtype == IKS_TYPE_RESULT) {
|
||||
if (iks_find_with_attrib(pak->query, "feature", "var", "http://www.google.com/xmpp/protocol/voice/v1")) {
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
char id[1024];
|
||||
char *resource;
|
||||
struct ldl_buffer *buffer;
|
||||
size_t x;
|
||||
|
||||
if (!apr_hash_get(handle->sub_hash, from, APR_HASH_KEY_STRING)) {
|
||||
iks *msg;
|
||||
apr_hash_set(handle->sub_hash, apr_pstrdup(handle->pool, from), APR_HASH_KEY_STRING, &marker);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling....");
|
||||
apr_queue_push(handle->queue, msg);
|
||||
}
|
||||
|
||||
apr_cpystrn(id, from, sizeof(id));
|
||||
if ((resource = strchr(id, '/'))) {
|
||||
*resource++ = '\0';
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
for (x = 0; x < strlen(resource); x++) {
|
||||
resource[x] = (char)tolower((int)resource[x]);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource && strstr(resource, "talk") && (buffer = apr_hash_get(handle->probe_hash, id, APR_HASH_KEY_STRING))) {
|
||||
apr_cpystrn(buffer->buf, from, buffer->len);
|
||||
fflush(stderr);
|
||||
buffer->hit = 1;
|
||||
}
|
||||
}
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
if (pak->subtype == IKS_TYPE_GET) {
|
||||
iks *iq, *query, *tag;
|
||||
uint8_t send = 0;
|
||||
|
||||
if ((iq = iks_new("iq"))) {
|
||||
do {
|
||||
iks_insert_attrib(iq, "from", handle->login);
|
||||
iks_insert_attrib(iq, "to", pak->from->full);
|
||||
iks_insert_attrib(iq, "id", pak->id);
|
||||
iks_insert_attrib(iq, "type", "result");
|
||||
|
||||
if (!(query = iks_insert (iq, "query"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
|
||||
|
||||
if (!(tag = iks_insert (query, "identity"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "category", "client");
|
||||
iks_insert_attrib(tag, "type", "voice");
|
||||
iks_insert_attrib(tag, "name", "LibDingaLing");
|
||||
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "http://jabber.org/protocol/disco#info");
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "http://www.google.com/xmpp/protocol/voice/v1");
|
||||
|
||||
iks_send(handle->parser, iq);
|
||||
send = 1;
|
||||
} while (0);
|
||||
|
||||
iks_delete(iq);
|
||||
}
|
||||
|
||||
if (!send) {
|
||||
globals.logger(DL_LOG_DEBUG, "Memory Error!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static int on_component_disco_info(void *user_data, ikspak *pak)
|
||||
{
|
||||
char *node = iks_find_attrib(pak->query, "node");
|
||||
ldl_handle_t *handle = user_data;
|
||||
|
||||
if (pak->subtype == IKS_TYPE_RESULT) {
|
||||
globals.logger(DL_LOG_DEBUG, "FixME!!! node=[%s]\n", node?node:"");
|
||||
} else if (pak->subtype == IKS_TYPE_GET) {
|
||||
// if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
if (node) {
|
||||
|
||||
} else {
|
||||
iks *iq, *query, *tag;
|
||||
uint8_t send = 0;
|
||||
|
||||
if ((iq = iks_new("iq"))) {
|
||||
do {
|
||||
iks_insert_attrib(iq, "from", handle->login);
|
||||
iks_insert_attrib(iq, "to", pak->from->full);
|
||||
iks_insert_attrib(iq, "id", pak->id);
|
||||
iks_insert_attrib(iq, "type", "result");
|
||||
|
||||
if (!(query = iks_insert (iq, "query"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
|
||||
|
||||
if (!(tag = iks_insert (query, "identity"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "category", "gateway");
|
||||
iks_insert_attrib(tag, "type", "voice");
|
||||
iks_insert_attrib(tag, "name", "LibDingaLing");
|
||||
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "http://jabber.org/protocol/disco");
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "jabber:iq:register");
|
||||
|
||||
/*
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "http://jabber.org/protocol/commands");
|
||||
*/
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "jabber:iq:gateway");
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "jabber:iq:version");
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "vcard-temp");
|
||||
|
||||
if (!(tag = iks_insert (query, "feature"))) {
|
||||
break;
|
||||
}
|
||||
iks_insert_attrib(tag, "var", "jabber:iq:search");
|
||||
|
||||
iks_send(handle->parser, iq);
|
||||
send = 1;
|
||||
} while (0);
|
||||
|
||||
iks_delete(iq);
|
||||
}
|
||||
|
||||
if (!send) {
|
||||
globals.logger(DL_LOG_DEBUG, "Memory Error!\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int on_disco_items(void *user_data, ikspak *pak)
|
||||
{
|
||||
globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static int on_disco_reg_in(void *user_data, ikspak *pak)
|
||||
{
|
||||
globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static int on_disco_reg_out(void *user_data, ikspak *pak)
|
||||
{
|
||||
globals.logger(DL_LOG_DEBUG, "FixME!!!\n");
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static int on_presence(void *user_data, ikspak *pak)
|
||||
{
|
||||
ldl_handle_t *handle = user_data;
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
char *to = iks_find_attrib(pak->x, "to");
|
||||
char *type = iks_find_attrib(pak->x, "type");
|
||||
char *show = iks_find_cdata(pak->x, "show");
|
||||
char *status = iks_find_cdata(pak->x, "status");
|
||||
@@ -454,6 +668,7 @@ static int on_presence(void *user_data, ikspak *pak)
|
||||
size_t x;
|
||||
ldl_signal_t signal;
|
||||
|
||||
|
||||
if (type && !strcasecmp(type, "unavailable")) {
|
||||
signal = LDL_SIGNAL_PRESENCE_OUT;
|
||||
} else {
|
||||
@@ -464,9 +679,7 @@ static int on_presence(void *user_data, ikspak *pak)
|
||||
status = type;
|
||||
}
|
||||
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, signal, from, status ? status : "n/a", show ? show : "n/a");
|
||||
}
|
||||
|
||||
|
||||
if (!apr_hash_get(handle->sub_hash, from, APR_HASH_KEY_STRING)) {
|
||||
iks *msg;
|
||||
@@ -491,20 +704,104 @@ static int on_presence(void *user_data, ikspak *pak)
|
||||
fflush(stderr);
|
||||
buffer->hit = 1;
|
||||
}
|
||||
|
||||
if (!type || (type && strcasecmp(type, "probe"))) {
|
||||
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, signal, to, from, status ? status : "n/a", show ? show : "n/a");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static void do_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message)
|
||||
{
|
||||
iks *pres;
|
||||
char buf[512];
|
||||
iks *tag;
|
||||
|
||||
if (!strchr(from, '/')) {
|
||||
snprintf(buf, sizeof(buf), "%s/talk", from);
|
||||
from = buf;
|
||||
}
|
||||
|
||||
if ((pres = iks_new("presence"))) {
|
||||
iks_insert_attrib(pres, "xmlns", "jabber:client");
|
||||
if (from) {
|
||||
iks_insert_attrib(pres, "from", from);
|
||||
}
|
||||
if (to) {
|
||||
iks_insert_attrib(pres, "to", to);
|
||||
}
|
||||
if (type) {
|
||||
iks_insert_attrib(pres, "type", type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (message) {
|
||||
if ((tag = iks_insert (pres, "status"))) {
|
||||
iks_insert_cdata(tag, message ? message : "", 0);
|
||||
if ((tag = iks_insert(pres, "c"))) {
|
||||
iks_insert_attrib(tag, "node", "http://www.freeswitch.org/xmpp/client/caps");
|
||||
iks_insert_attrib(tag, "ver", "1.0.0.1");
|
||||
iks_insert_attrib(tag, "ext", "sidebar voice-v1");
|
||||
iks_insert_attrib(tag, "client", "libdingaling2");
|
||||
iks_insert_attrib(tag, "xmlns", "http://jabber.org/protocol/caps");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apr_queue_push(handle->queue, pres);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_roster(ldl_handle_t *handle)
|
||||
{
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_ROSTER, NULL, handle->login, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int on_unsubscribe(void *user_data, ikspak *pak)
|
||||
{
|
||||
ldl_handle_t *handle = user_data;
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
char *to = iks_find_attrib(pak->x, "to");
|
||||
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_SUBSCRIBE, to, from, NULL, NULL);
|
||||
}
|
||||
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
static int on_subscribe(void *user_data, ikspak *pak)
|
||||
{
|
||||
ldl_handle_t *handle = user_data;
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
char *to = iks_find_attrib(pak->x, "to");
|
||||
iks *msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, from, "Ding A Ling....");
|
||||
|
||||
if (to && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
iks_insert_attrib(msg, "from", to);
|
||||
}
|
||||
|
||||
apr_queue_push(handle->queue, msg);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, from, "Ding A Ling....");
|
||||
|
||||
if (to && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
iks_insert_attrib(msg, "from", to);
|
||||
}
|
||||
|
||||
apr_queue_push(handle->queue, msg);
|
||||
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_SUBSCRIBE, to, from, NULL, NULL);
|
||||
}
|
||||
|
||||
return IKS_FILTER_EAT;
|
||||
}
|
||||
|
||||
@@ -526,7 +823,7 @@ static int on_commands(void *user_data, ikspak *pak)
|
||||
{
|
||||
ldl_handle_t *handle = user_data;
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
//char *to = iks_find_attrib(pak->x, "to");
|
||||
char *to = iks_find_attrib(pak->x, "to");
|
||||
char *iqid = iks_find_attrib(pak->x, "id");
|
||||
char *type = iks_find_attrib(pak->x, "type");
|
||||
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
|
||||
@@ -540,9 +837,10 @@ static int on_commands(void *user_data, ikspak *pak)
|
||||
if (!strcasecmp(iks_name(tag), "bind")) {
|
||||
char *jid = iks_find_cdata(tag, "jid");
|
||||
char *resource = strchr(jid, '/');
|
||||
iks *iq, *x;
|
||||
//iks *iq, *x;
|
||||
handle->acc->resource = apr_pstrdup(handle->pool, resource);
|
||||
handle->login = apr_pstrdup(handle->pool, jid);
|
||||
#if 0
|
||||
if ((iq = iks_new("iq"))) {
|
||||
iks_insert_attrib(iq, "type", "get");
|
||||
iks_insert_attrib(iq, "id", "roster");
|
||||
@@ -555,6 +853,7 @@ static int on_commands(void *user_data, ikspak *pak)
|
||||
iks_delete(iq);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
tag = iks_next_tag(tag);
|
||||
}
|
||||
@@ -579,10 +878,11 @@ static int on_commands(void *user_data, ikspak *pak)
|
||||
if (!strcasecmp(name, "session")) {
|
||||
char *id = iks_find_attrib(xml, "id");
|
||||
//printf("SESSION type=%s name=%s id=%s\n", type, name, id);
|
||||
if (parse_session_code(handle, id, from, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
|
||||
if (parse_session_code(handle, id, from, to, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
|
||||
iks *reply;
|
||||
reply = iks_make_iq(IKS_TYPE_RESULT, NULL);
|
||||
iks_insert_attrib(reply, "to", from);
|
||||
iks_insert_attrib(reply, "from", to);
|
||||
iks_insert_attrib(reply, "id", iqid);
|
||||
apr_queue_push(handle->queue, reply);
|
||||
}
|
||||
@@ -644,7 +944,88 @@ static int b64encode(unsigned char *in, uint32_t ilen, unsigned char *out, uint3
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_stream(ldl_handle_t *handle, int type, iks * node)
|
||||
static void sha1_hash(char *out, char *in)
|
||||
{
|
||||
sha_context_t sha;
|
||||
char *p;
|
||||
int x;
|
||||
unsigned char digest[20];
|
||||
|
||||
SHA1Init(&sha);
|
||||
|
||||
SHA1Update(&sha, (unsigned char *) in, strlen(in));
|
||||
|
||||
SHA1Final(digest, &sha);
|
||||
|
||||
p = out;
|
||||
for (x = 0; x < 20; x++) {
|
||||
p += sprintf(p, "%2.2x", digest[x]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int on_stream_component(ldl_handle_t *handle, int type, iks *node)
|
||||
{
|
||||
ikspak *pak = iks_packet(node);
|
||||
|
||||
switch (type) {
|
||||
case IKS_NODE_START:
|
||||
if (handle->state == CS_NEW) {
|
||||
char secret[256];
|
||||
char hash[256];
|
||||
char handshake[512];
|
||||
snprintf(secret, sizeof(secret), "%s%s", pak->id, handle->password);
|
||||
sha1_hash(hash, secret);
|
||||
snprintf(handshake, sizeof(handshake), "<handshake>%s</handshake>", hash);
|
||||
iks_send_raw(handle->parser, handshake);
|
||||
handle->state = CS_START;
|
||||
if (iks_recv(handle->parser, 1) == 2) {
|
||||
handle->state = CS_CONNECTED;
|
||||
if (!ldl_test_flag(handle, LDL_FLAG_AUTHORIZED)) {
|
||||
ldl_set_flag_locked(handle, LDL_FLAG_READY);
|
||||
do_roster(handle);
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "user", "core", "Login Success", handle->login);
|
||||
}
|
||||
globals.logger(DL_LOG_DEBUG, "XMPP authenticated\n");
|
||||
ldl_set_flag_locked(handle, LDL_FLAG_AUTHORIZED);
|
||||
}
|
||||
} else {
|
||||
globals.logger(DL_LOG_ERR, "LOGIN ERROR!\n");
|
||||
handle->state = CS_NEW;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case IKS_NODE_NORMAL:
|
||||
break;
|
||||
|
||||
case IKS_NODE_ERROR:
|
||||
globals.logger(DL_LOG_ERR, "NODE ERROR!\n");
|
||||
return IKS_HOOK;
|
||||
|
||||
case IKS_NODE_STOP:
|
||||
globals.logger(DL_LOG_ERR, "DISCONNECTED!\n");
|
||||
return IKS_HOOK;
|
||||
}
|
||||
|
||||
|
||||
pak = iks_packet(node);
|
||||
iks_filter_packet(handle->filter, pak);
|
||||
|
||||
if (handle->job_done == 1) {
|
||||
return IKS_HOOK;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
iks_delete(node);
|
||||
}
|
||||
|
||||
return IKS_OK;
|
||||
}
|
||||
|
||||
static int on_stream(ldl_handle_t *handle, int type, iks *node)
|
||||
{
|
||||
handle->counter = opt_timeout;
|
||||
|
||||
@@ -708,20 +1089,20 @@ static int on_stream(ldl_handle_t *handle, int type, iks * node)
|
||||
} else if (strcmp("failure", iks_name(node)) == 0) {
|
||||
globals.logger(DL_LOG_DEBUG, "sasl authentication failed\n");
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_FAILURE, "core", "Login Failure", handle->login);
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_FAILURE, "user", "core", "Login Failure", handle->login);
|
||||
}
|
||||
} else if (strcmp("success", iks_name(node)) == 0) {
|
||||
globals.logger(DL_LOG_DEBUG, "XMPP server connected\n");
|
||||
iks_send_header(handle->parser, handle->acc->server);
|
||||
ldl_set_flag_locked(handle, LDL_FLAG_CONNECTED);
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_CONNECTED, "core", "Server Connected", handle->login);
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_CONNECTED, "user", "core", "Server Connected", handle->login);
|
||||
}
|
||||
} else {
|
||||
ikspak *pak;
|
||||
if (!ldl_test_flag(handle, LDL_FLAG_AUTHORIZED)) {
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "core", "Login Success", handle->login);
|
||||
handle->session_callback(handle, NULL, LDL_SIGNAL_LOGIN_SUCCESS, "user", "core", "Login Success", handle->login);
|
||||
}
|
||||
globals.logger(DL_LOG_DEBUG, "XMPP authenticated\n");
|
||||
ldl_set_flag_locked(handle, LDL_FLAG_AUTHORIZED);
|
||||
@@ -754,6 +1135,7 @@ static int on_stream(ldl_handle_t *handle, int type, iks * node)
|
||||
static int on_msg(void *user_data, ikspak *pak)
|
||||
{
|
||||
char *cmd = iks_find_cdata(pak->x, "body");
|
||||
char *to = iks_find_attrib(pak->x, "to");
|
||||
char *from = iks_find_attrib(pak->x, "from");
|
||||
char *subject = iks_find_attrib(pak->x, "subject");
|
||||
ldl_handle_t *handle = user_data;
|
||||
@@ -764,7 +1146,7 @@ static int on_msg(void *user_data, ikspak *pak)
|
||||
}
|
||||
|
||||
if (handle->session_callback) {
|
||||
handle->session_callback(handle, session, LDL_SIGNAL_MSG, from, subject ? subject : "N/A", cmd);
|
||||
handle->session_callback(handle, session, LDL_SIGNAL_MSG, to, from, subject ? subject : "N/A", cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -789,18 +1171,13 @@ static void on_log(ldl_handle_t *handle, const char *data, size_t size, int is_i
|
||||
fprintf(stderr, "[%s]\n", data);
|
||||
}
|
||||
|
||||
static void j_setup_filter(ldl_handle_t *handle, char *login)
|
||||
static void j_setup_filter(ldl_handle_t *handle)
|
||||
{
|
||||
if (handle->filter) {
|
||||
iks_filter_delete(handle->filter);
|
||||
}
|
||||
handle->filter = iks_filter_new();
|
||||
|
||||
/*
|
||||
iks_filter_add_rule(handle->filter, on_msg, 0,
|
||||
IKS_RULE_TYPE, IKS_PAK_MESSAGE,
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_FROM, login, IKS_RULE_DONE);
|
||||
*/
|
||||
iks_filter_add_rule(handle->filter, on_msg, handle, IKS_RULE_TYPE, IKS_PAK_MESSAGE, IKS_RULE_SUBTYPE, IKS_TYPE_CHAT, IKS_RULE_DONE);
|
||||
|
||||
iks_filter_add_rule(handle->filter, on_result, handle,
|
||||
@@ -832,9 +1209,31 @@ static void j_setup_filter(ldl_handle_t *handle, char *login)
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_SUBSCRIBE,
|
||||
IKS_RULE_DONE);
|
||||
|
||||
iks_filter_add_rule(handle->filter, on_unsubscribe, handle,
|
||||
IKS_RULE_TYPE, IKS_PAK_S10N,
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_UNSUBSCRIBE,
|
||||
IKS_RULE_DONE);
|
||||
|
||||
iks_filter_add_rule(handle->filter, on_error, handle,
|
||||
IKS_RULE_TYPE, IKS_PAK_IQ,
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_ERROR, IKS_RULE_ID, "auth", IKS_RULE_DONE);
|
||||
|
||||
|
||||
|
||||
if (ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
iks_filter_add_rule(handle->filter, on_component_disco_info, handle,
|
||||
IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
|
||||
iks_filter_add_rule(handle->filter, on_disco_items, handle,
|
||||
IKS_RULE_NS, "http://jabber.org/protocol/disco#items", IKS_RULE_DONE);
|
||||
iks_filter_add_rule(handle->filter, on_disco_reg_in, handle,
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_GET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
|
||||
iks_filter_add_rule(handle->filter, on_disco_reg_out, handle,
|
||||
IKS_RULE_SUBTYPE, IKS_TYPE_SET, IKS_RULE_NS, "jabber:iq:register", IKS_RULE_DONE);
|
||||
} else {
|
||||
iks_filter_add_rule(handle->filter, on_disco_info, handle,
|
||||
IKS_RULE_NS, "http://jabber.org/protocol/disco#info", IKS_RULE_DONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void ldl_flush_queue(ldl_handle_t *handle)
|
||||
@@ -928,26 +1327,35 @@ static void xmpp_connect(ldl_handle_t *handle, char *jabber_id, char *pass)
|
||||
{
|
||||
while (ldl_test_flag(handle, LDL_FLAG_RUNNING)) {
|
||||
int e;
|
||||
char tmp[512], *sl;
|
||||
|
||||
handle->parser = iks_stream_new(ldl_test_flag(handle, LDL_FLAG_COMPONENT) ? IKS_NS_COMPONENT : IKS_NS_CLIENT,
|
||||
handle,
|
||||
(iksStreamHook *) (ldl_test_flag(handle, LDL_FLAG_COMPONENT) ? on_stream_component : on_stream));
|
||||
|
||||
handle->parser = iks_stream_new(IKS_NS_CLIENT, handle, (iksStreamHook *) on_stream);
|
||||
if (globals.debug) {
|
||||
iks_set_log_hook(handle->parser, (iksLogHook *) on_log);
|
||||
}
|
||||
handle->acc = iks_id_new(iks_parser_stack(handle->parser), jabber_id);
|
||||
if (NULL == handle->acc->resource) {
|
||||
|
||||
strncpy(tmp, jabber_id, sizeof(tmp)-1);
|
||||
sl = strchr(tmp, '/');
|
||||
|
||||
if (!sl && !ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
/* user gave no resource name, use the default */
|
||||
char tmp[512];
|
||||
sprintf(tmp, "%s@%s/%s", handle->acc->user, handle->acc->server, "dingaling");
|
||||
handle->acc = iks_id_new(iks_parser_stack(handle->parser), tmp);
|
||||
snprintf(tmp + strlen(tmp), sizeof(tmp) - strlen(tmp), "/%s", "talk");
|
||||
} else if (sl && ldl_test_flag(handle, LDL_FLAG_COMPONENT)) {
|
||||
*sl = '\0';
|
||||
}
|
||||
|
||||
handle->acc = iks_id_new(iks_parser_stack(handle->parser), tmp);
|
||||
|
||||
handle->password = pass;
|
||||
|
||||
j_setup_filter(handle, "fixme");
|
||||
j_setup_filter(handle);
|
||||
|
||||
e = iks_connect_via(handle->parser,
|
||||
handle->server ? handle->server : handle->acc->server,
|
||||
handle->port ? handle->port : IKS_JABBER_PORT,
|
||||
//handle->server ? handle->server : handle->acc->server);
|
||||
handle->acc->server);
|
||||
|
||||
switch (e) {
|
||||
@@ -1040,7 +1448,7 @@ static ldl_status new_session_iq(ldl_session_t *session, iks **iqp, iks **sessp,
|
||||
snprintf(idbuf, sizeof(idbuf), "%u", myid);
|
||||
iq = iks_new("iq");
|
||||
iks_insert_attrib(iq, "xmlns", "jabber:client");
|
||||
iks_insert_attrib(iq, "from", session->handle->login);
|
||||
iks_insert_attrib(iq, "from", session->login);
|
||||
iks_insert_attrib(iq, "to", session->them);
|
||||
iks_insert_attrib(iq, "type", "set");
|
||||
iks_insert_attrib(iq, "id", idbuf);
|
||||
@@ -1092,6 +1500,11 @@ char *ldl_session_get_caller(ldl_session_t *session)
|
||||
return session->them;
|
||||
}
|
||||
|
||||
char *ldl_session_get_callee(ldl_session_t *session)
|
||||
{
|
||||
return session->login;
|
||||
}
|
||||
|
||||
void ldl_session_set_ip(ldl_session_t *session, char *ip)
|
||||
{
|
||||
session->ip = apr_pstrdup(session->pool, ip);
|
||||
@@ -1123,7 +1536,7 @@ void ldl_session_accept_candidate(ldl_session_t *session, ldl_candidate_t *candi
|
||||
iq = iks_new("iq");
|
||||
iks_insert_attrib(iq, "type", "set");
|
||||
iks_insert_attrib(iq, "id", idbuf);
|
||||
iks_insert_attrib(iq, "from", session->handle->login);
|
||||
iks_insert_attrib(iq, "from", session->login);
|
||||
iks_insert_attrib(iq, "to", session->them);
|
||||
sess = iks_insert (iq, "session");
|
||||
iks_insert_attrib(sess, "xmlns", "http://www.google.com/session");
|
||||
@@ -1142,7 +1555,12 @@ void *ldl_handle_get_private(ldl_handle_t *handle)
|
||||
return handle->private_info;
|
||||
}
|
||||
|
||||
void ldl_handle_send_msg(ldl_handle_t *handle, char *to, char *subject, char *body)
|
||||
void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message)
|
||||
{
|
||||
do_presence(handle, from, to, type, message);
|
||||
}
|
||||
|
||||
void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body)
|
||||
{
|
||||
iks *msg;
|
||||
|
||||
@@ -1153,6 +1571,12 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *to, char *subject, char *bo
|
||||
msg = iks_make_msg(IKS_TYPE_NONE, to, body);
|
||||
iks_insert_attrib(msg, "type", "chat");
|
||||
|
||||
if (!from) {
|
||||
from = handle->login;
|
||||
}
|
||||
|
||||
iks_insert_attrib(msg, "from", from);
|
||||
|
||||
if (subject) {
|
||||
iks_insert_attrib(msg, "subject", subject);
|
||||
}
|
||||
@@ -1235,7 +1659,7 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
|
||||
return id;
|
||||
}
|
||||
|
||||
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len)
|
||||
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
|
||||
{
|
||||
iks *pres, *msg;
|
||||
char *lid = NULL;
|
||||
@@ -1251,11 +1675,13 @@ char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int l
|
||||
|
||||
pres = iks_new("presence");
|
||||
iks_insert_attrib(pres, "type", "probe");
|
||||
iks_insert_attrib(pres, "from", from);
|
||||
iks_insert_attrib(pres, "to", id);
|
||||
|
||||
|
||||
apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, &buffer);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice);
|
||||
iks_insert_attrib(pres, "from", from);
|
||||
apr_queue_push(handle->queue, msg);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, id, notice);
|
||||
apr_queue_push(handle->queue, msg);
|
||||
@@ -1263,6 +1689,75 @@ char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int l
|
||||
|
||||
//schedule_packet(handle, next_id(), pres, LDL_RETRY);
|
||||
|
||||
started = apr_time_now();
|
||||
for(;;) {
|
||||
elapsed = (unsigned int)((apr_time_now() - started) / 1000);
|
||||
if (elapsed > 5000 && ! again) {
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice);
|
||||
iks_insert_attrib(pres, "from", from);
|
||||
apr_queue_push(handle->queue, msg);
|
||||
again++;
|
||||
}
|
||||
if (elapsed > 10000) {
|
||||
break;
|
||||
}
|
||||
if (buffer.hit) {
|
||||
lid = buffer.buf;
|
||||
break;
|
||||
}
|
||||
ldl_yield(1000);
|
||||
}
|
||||
|
||||
apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, NULL);
|
||||
return lid;
|
||||
}
|
||||
|
||||
|
||||
char *ldl_handle_disco(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
|
||||
{
|
||||
iks *iq, *query, *msg;
|
||||
char *lid = NULL;
|
||||
struct ldl_buffer buffer;
|
||||
apr_time_t started;
|
||||
unsigned int elapsed;
|
||||
char *notice = "Call Me!";
|
||||
int again = 0;
|
||||
unsigned int myid;
|
||||
char idbuf[80];
|
||||
|
||||
myid = next_id();
|
||||
snprintf(idbuf, sizeof(idbuf), "%u", myid);
|
||||
|
||||
buffer.buf = buf;
|
||||
buffer.len = len;
|
||||
buffer.hit = 0;
|
||||
|
||||
if ((iq = iks_new("iq"))) {
|
||||
if ((query = iks_insert(iq, "query"))) {
|
||||
iks_insert_attrib(iq, "type", "get");
|
||||
iks_insert_attrib(iq, "to", id);
|
||||
iks_insert_attrib(iq,"from", from);
|
||||
iks_insert_attrib(iq, "id", idbuf);
|
||||
iks_insert_attrib(query, "xmlns", "http://jabber.org/protocol/disco#info");
|
||||
} else {
|
||||
iks_delete(iq);
|
||||
globals.logger(DL_LOG_DEBUG, "Memory ERROR!\n");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
globals.logger(DL_LOG_DEBUG, "Memory ERROR!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apr_hash_set(handle->probe_hash, id, APR_HASH_KEY_STRING, &buffer);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBE, id, notice);
|
||||
apr_queue_push(handle->queue, msg);
|
||||
msg = iks_make_s10n (IKS_TYPE_SUBSCRIBED, id, notice);
|
||||
apr_queue_push(handle->queue, msg);
|
||||
apr_queue_push(handle->queue, iq);
|
||||
|
||||
//schedule_packet(handle, next_id(), pres, LDL_RETRY);
|
||||
|
||||
started = apr_time_now();
|
||||
for(;;) {
|
||||
elapsed = (unsigned int)((apr_time_now() - started) / 1000);
|
||||
|
@@ -50,6 +50,7 @@ extern "C" {
|
||||
#define LDL_MAX_CANDIDATES 10
|
||||
#define LDL_MAX_PAYLOADS 50
|
||||
#define LDL_RETRY 3
|
||||
#define IKS_NS_COMPONENT "jabber:component:accept"
|
||||
|
||||
/*! \brief A structure to store a jingle candidate */
|
||||
struct ldl_candidate {
|
||||
@@ -105,13 +106,14 @@ typedef enum {
|
||||
LDL_FLAG_AUTHORIZED = (1 << 2),
|
||||
LDL_FLAG_READY = (1 << 3),
|
||||
LDL_FLAG_CONNECTED = (1 << 4),
|
||||
LDL_FLAG_QUEUE_RUNNING = (1 << 5),
|
||||
LDL_FLAG_QUEUE_RUNNING = (1 << 5)
|
||||
} ldl_flag_t;
|
||||
|
||||
typedef enum {
|
||||
LDL_FLAG_TLS = (1 << 10),
|
||||
LDL_FLAG_SASL_PLAIN = (1 << 11),
|
||||
LDL_FLAG_SASL_MD5 = (1 << 12)
|
||||
LDL_FLAG_SASL_MD5 = (1 << 12),
|
||||
LDL_FLAG_COMPONENT = (1 << 13),
|
||||
} ldl_user_flag_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -121,6 +123,9 @@ typedef enum {
|
||||
LDL_SIGNAL_MSG,
|
||||
LDL_SIGNAL_PRESENCE_IN,
|
||||
LDL_SIGNAL_PRESENCE_OUT,
|
||||
LDL_SIGNAL_ROSTER,
|
||||
LDL_SIGNAL_SUBSCRIBE,
|
||||
LDL_SIGNAL_UNSUBSCRIBE,
|
||||
LDL_SIGNAL_TERMINATE,
|
||||
LDL_SIGNAL_ERROR,
|
||||
LDL_SIGNAL_LOGIN_SUCCESS,
|
||||
@@ -156,7 +161,7 @@ typedef enum {
|
||||
#define DL_LOG_EMERG DL_PRE, 0
|
||||
|
||||
typedef ldl_status (*ldl_loop_callback_t)(ldl_handle_t *);
|
||||
typedef ldl_status (*ldl_session_callback_t)(ldl_handle_t *, ldl_session_t *, ldl_signal_t, char *, char *, char *);
|
||||
typedef ldl_status (*ldl_session_callback_t)(ldl_handle_t *, ldl_session_t *, ldl_signal_t, char *, char *, char *, char *);
|
||||
typedef ldl_status (*ldl_response_callback_t)(ldl_handle_t *, char *);
|
||||
typedef void (*ldl_logger_t)(char *file, const char *func, int line, int level, char *fmt, ...);
|
||||
|
||||
@@ -265,6 +270,13 @@ char *ldl_session_get_id(ldl_session_t *session);
|
||||
*/
|
||||
char *ldl_session_get_caller(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Get the callee name of a session
|
||||
\param session the session to get the callee from
|
||||
\return the callee name
|
||||
*/
|
||||
char *ldl_session_get_callee(ldl_session_t *session);
|
||||
|
||||
/*!
|
||||
\brief Set the ip of a session
|
||||
\param session the session to set the ip on
|
||||
@@ -310,11 +322,23 @@ void ldl_global_set_logger(ldl_logger_t logger);
|
||||
\brief Perform a probe on a given id to resolve the proper Jingle Resource
|
||||
\param handle the connection handle to use.
|
||||
\param id the id to probe
|
||||
\param from the from string
|
||||
\param buf a string to store the result
|
||||
\param len the size in bytes of the string
|
||||
\return a pointer to buf if a successful lookup was made otherwise NULL
|
||||
*/
|
||||
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *buf, unsigned int len);
|
||||
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len);
|
||||
|
||||
/*!
|
||||
\brief Perform a discovery on a given id to resolve the proper Jingle Resource
|
||||
\param handle the connection handle to use.
|
||||
\param id the id to probe
|
||||
\param from the from string
|
||||
\param buf a string to store the result
|
||||
\param len the size in bytes of the string
|
||||
\return a pointer to buf if a successful lookup was made otherwise NULL
|
||||
*/
|
||||
char *ldl_handle_disco(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len);
|
||||
|
||||
/*!
|
||||
\brief Signal a termination request on a given session
|
||||
@@ -339,14 +363,25 @@ void *ldl_handle_get_private(ldl_handle_t *handle);
|
||||
*/
|
||||
void ldl_session_send_msg(ldl_session_t *session, char *subject, char *body);
|
||||
|
||||
/*!
|
||||
\brief Send a presence notification to a target
|
||||
\param handle the handle to send with
|
||||
\param from the from address
|
||||
\param to the to address
|
||||
\param type the type of presence
|
||||
\param message a status message
|
||||
*/
|
||||
void ldl_handle_send_presence(ldl_handle_t *handle, char *from, char *to, char *type, char *message);
|
||||
|
||||
/*!
|
||||
\brief Send a message
|
||||
\param handle the conection handle
|
||||
\param from the message sender
|
||||
\param to the message recipiant
|
||||
\param subject optional subject
|
||||
\param body body of the message
|
||||
*/
|
||||
void ldl_handle_send_msg(ldl_handle_t *handle, char *to, char *subject, char *body);
|
||||
void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, char *subject, char *body);
|
||||
|
||||
/*!
|
||||
\brief Offer candidates to a potential session
|
||||
|
203
libs/libdingaling/src/sha1.c
Normal file
203
libs/libdingaling/src/sha1.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Steve Reid <steve@edmweb.com>
|
||||
*
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Steve Reid <steve@edmweb.com>
|
||||
*
|
||||
* sha1.h
|
||||
*
|
||||
*/
|
||||
/*! \file sha1.c
|
||||
\brief SHA1
|
||||
*/
|
||||
|
||||
/*
|
||||
ORIGINAL HEADERS
|
||||
----------------------------------------------------------------------------------------------
|
||||
SHA-1 in C
|
||||
By Steve Reid <steve@edmweb.com>
|
||||
100% Public Domain
|
||||
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
|
||||
/* #define SHA1HANDSOFF * Copies data before messing with it. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|
||||
|(rol(block->l[i],8)&0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
|
||||
{
|
||||
unsigned long a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
unsigned long l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
static unsigned char workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16*)buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(sha_context_t* context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(sha_context_t* context, unsigned char* data, unsigned int len)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], sha_context_t* context)
|
||||
{
|
||||
unsigned long i, j;
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = j = 0;
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(&finalcount, 0, 8);
|
||||
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
58
libs/libdingaling/src/sha1.h
Normal file
58
libs/libdingaling/src/sha1.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* libDingaLing XMPP Jingle Library
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libDingaLing XMPP Jingle Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Steve Reid <steve@edmweb.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Steve Reid <steve@edmweb.com>
|
||||
*
|
||||
* sha1.h
|
||||
*
|
||||
*/
|
||||
/*! \file sha1.h
|
||||
\brief SHA1
|
||||
*/
|
||||
|
||||
#ifndef __SHA1_H
|
||||
#define __SHA1_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#ifdef __STUPIDFORMATBUG__
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long state[5];
|
||||
unsigned long count[2];
|
||||
unsigned char buffer[64];
|
||||
} sha_context_t;
|
||||
|
||||
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
|
||||
void SHA1Init(sha_context_t* context);
|
||||
void SHA1Update(sha_context_t* context, unsigned char* data, unsigned int len);
|
||||
void SHA1Final(unsigned char digest[20], sha_context_t* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
Reference in New Issue
Block a user