mirror of https://github.com/bqv/weechat-xmpp
basic connection
parent
86bfc6359c
commit
4acb753cae
@ -1,291 +0,0 @@
|
|||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
#include <libwebsockets.h>
|
|
||||||
#include <json.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "weechat-plugin.h"
|
|
||||||
#include "slack.h"
|
|
||||||
#include "slack-workspace.h"
|
|
||||||
#include "slack-api.h"
|
|
||||||
#include "api/slack-api-hello.h"
|
|
||||||
#include "api/slack-api-error.h"
|
|
||||||
#include "api/slack-api-message.h"
|
|
||||||
#include "api/slack-api-user-typing.h"
|
|
||||||
|
|
||||||
struct stringcase
|
|
||||||
{
|
|
||||||
const char *string;
|
|
||||||
int (*func)(struct t_slack_workspace *workspace,
|
|
||||||
json_object *message);
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct stringcase cases[] =
|
|
||||||
{ { "hello", &slack_api_hello }
|
|
||||||
, { "error", &slack_api_error }
|
|
||||||
, { "message", &slack_api_message }
|
|
||||||
, { "user_typing", &slack_api_user_typing }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int stringcase_cmp(const void *p1, const void *p2)
|
|
||||||
{
|
|
||||||
return strcasecmp(((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string);
|
|
||||||
}
|
|
||||||
|
|
||||||
void slack_api_init()
|
|
||||||
{
|
|
||||||
size_t case_count = sizeof(cases) / sizeof(cases[0]);
|
|
||||||
qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp);
|
|
||||||
|
|
||||||
slack_api_message_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
static int callback_ws(struct lws* wsi, enum lws_callback_reasons reason,
|
|
||||||
void *user, void* in, size_t len)
|
|
||||||
{
|
|
||||||
struct t_slack_workspace *workspace = (struct t_slack_workspace *)user;
|
|
||||||
|
|
||||||
(void) wsi;
|
|
||||||
|
|
||||||
switch (reason)
|
|
||||||
{
|
|
||||||
/* because we are protocols[0] ... */
|
|
||||||
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: error connecting to slack: %s"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
|
||||||
in ? (char *)in : "(null)");
|
|
||||||
workspace->client_wsi = NULL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LWS_CALLBACK_CLIENT_ESTABLISHED:
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: waiting for hello..."),
|
|
||||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* data is never chunked */
|
|
||||||
case LWS_CALLBACK_CLIENT_RECEIVE:
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: received data: %s"),
|
|
||||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
|
||||||
(const char *)in);
|
|
||||||
{
|
|
||||||
int data_size;
|
|
||||||
char *json_string;
|
|
||||||
json_object *response, *type;
|
|
||||||
struct t_json_chunk *new_chunk, *last_chunk, *chunk_ptr;
|
|
||||||
|
|
||||||
new_chunk = malloc(sizeof(*new_chunk));
|
|
||||||
new_chunk->data = malloc(((int)len) + 1);
|
|
||||||
new_chunk->data[0] = '\0';
|
|
||||||
new_chunk->next = NULL;
|
|
||||||
|
|
||||||
strncat(new_chunk->data, in, (int)len);
|
|
||||||
|
|
||||||
if (workspace->json_chunks)
|
|
||||||
{
|
|
||||||
for (last_chunk = workspace->json_chunks; last_chunk->next;
|
|
||||||
last_chunk = last_chunk->next);
|
|
||||||
last_chunk->next = new_chunk;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
workspace->json_chunks = new_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_size = 0;
|
|
||||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next)
|
|
||||||
{
|
|
||||||
data_size += strlen(chunk_ptr->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
json_string = malloc(data_size + 1);
|
|
||||||
json_string[0] = '\0';
|
|
||||||
|
|
||||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; chunk_ptr = chunk_ptr->next)
|
|
||||||
{
|
|
||||||
strcat(json_string, chunk_ptr->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
response = json_tokener_parse(json_string);
|
|
||||||
if (response)
|
|
||||||
{
|
|
||||||
for (chunk_ptr = workspace->json_chunks; chunk_ptr; workspace->json_chunks = chunk_ptr)
|
|
||||||
{
|
|
||||||
chunk_ptr = chunk_ptr->next;
|
|
||||||
free(workspace->json_chunks->data);
|
|
||||||
free(workspace->json_chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = json_object_object_get(response, "type");
|
|
||||||
if (!type)
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: unexpected data received from websocket: closing"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
|
||||||
|
|
||||||
slack_workspace_disconnect(workspace, 0);
|
|
||||||
|
|
||||||
json_object_put(response);
|
|
||||||
free(json_string);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!slack_api_route_message(workspace,
|
|
||||||
json_object_get_string(type), response))
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: error while handling message: %s"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
|
||||||
json_string);
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: closing connection."),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
|
||||||
|
|
||||||
slack_workspace_disconnect(workspace, 0);
|
|
||||||
|
|
||||||
json_object_put(response);
|
|
||||||
free(json_string);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
json_object_put(response);
|
|
||||||
free(json_string);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
free(json_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0; /* don't passthru */
|
|
||||||
|
|
||||||
case LWS_CALLBACK_CLIENT_WRITEABLE:
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: websocket is writeable"),
|
|
||||||
weechat_prefix("network"), SLACK_PLUGIN_NAME);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LWS_CALLBACK_CLOSED:
|
|
||||||
workspace->client_wsi = NULL;
|
|
||||||
workspace->disconnected = 1;
|
|
||||||
/* start reconnect timer */
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lws_callback_http_dummy(wsi, reason, user, in, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct lws_protocols protocols[] = {
|
|
||||||
{
|
|
||||||
"default",
|
|
||||||
callback_ws,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
{ NULL, NULL, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void slack_api_connect(struct t_slack_workspace *workspace)
|
|
||||||
{
|
|
||||||
struct lws_context_creation_info ctxinfo;
|
|
||||||
struct lws_client_connect_info ccinfo;
|
|
||||||
const char *url_protocol, *url_path;
|
|
||||||
char path[512];
|
|
||||||
|
|
||||||
memset(&ctxinfo, 0, sizeof(ctxinfo));
|
|
||||||
memset(&ccinfo, 0, sizeof(ccinfo));
|
|
||||||
|
|
||||||
ccinfo.port = 443;
|
|
||||||
|
|
||||||
if (lws_parse_uri(workspace->ws_url,
|
|
||||||
&url_protocol, &ccinfo.address,
|
|
||||||
&ccinfo.port, &url_path))
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: error connecting to slack: bad websocket uri"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path[0] = '/';
|
|
||||||
strncpy(path + 1, url_path, sizeof(path) - 2);
|
|
||||||
path[sizeof(path) - 1] = '\0';
|
|
||||||
|
|
||||||
ccinfo.path = path;
|
|
||||||
|
|
||||||
ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
|
||||||
ctxinfo.port = CONTEXT_PORT_NO_LISTEN;
|
|
||||||
ctxinfo.protocols = protocols;
|
|
||||||
ctxinfo.uid = -1;
|
|
||||||
ctxinfo.gid = -1;
|
|
||||||
|
|
||||||
workspace->context = lws_create_context(&ctxinfo);
|
|
||||||
if (!workspace->context)
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: error connecting to slack: lws init failed"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: connecting to %s://%s:%d%s"),
|
|
||||||
weechat_prefix("network"), SLACK_PLUGIN_NAME,
|
|
||||||
url_protocol, ccinfo.address, ccinfo.port, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
ccinfo.context = workspace->context;
|
|
||||||
ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
|
||||||
ccinfo.host = ccinfo.address;
|
|
||||||
ccinfo.origin = ccinfo.address;
|
|
||||||
ccinfo.ietf_version_or_minus_one = -1;
|
|
||||||
ccinfo.protocol = protocols[0].name;
|
|
||||||
ccinfo.pwsi = &workspace->client_wsi;
|
|
||||||
ccinfo.userdata = workspace;
|
|
||||||
|
|
||||||
lws_client_connect_via_info(&ccinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
int slack_api_route_message(struct t_slack_workspace *workspace,
|
|
||||||
const char *type, json_object *message)
|
|
||||||
{
|
|
||||||
struct stringcase key;
|
|
||||||
key.string = type;
|
|
||||||
|
|
||||||
size_t case_count = sizeof(cases) / sizeof(cases[0]);
|
|
||||||
void *entry_ptr = bsearch(&key, cases, case_count,
|
|
||||||
sizeof(struct stringcase), stringcase_cmp);
|
|
||||||
|
|
||||||
if (entry_ptr)
|
|
||||||
{
|
|
||||||
struct stringcase *entry = (struct stringcase *)entry_ptr;
|
|
||||||
return (*entry->func)(workspace, message);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
weechat_printf(
|
|
||||||
workspace->buffer,
|
|
||||||
_("%s%s: got unhandled message of type: %s"),
|
|
||||||
weechat_prefix("error"), SLACK_PLUGIN_NAME,
|
|
||||||
type);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
// License, version 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
#ifndef _SLACK_API_H_
|
|
||||||
#define _SLACK_API_H_
|
|
||||||
|
|
||||||
void slack_api_init();
|
|
||||||
|
|
||||||
void slack_api_connect(struct t_slack_workspace *workspace);
|
|
||||||
|
|
||||||
int slack_api_route_message(struct t_slack_workspace *workspace,
|
|
||||||
const char *type, json_object *message);
|
|
||||||
|
|
||||||
#endif /*SLACK_API_H*/
|
|
@ -0,0 +1,146 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#include <json.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strophe.h>
|
||||||
|
#include <weechat/weechat-plugin.h>
|
||||||
|
|
||||||
|
#include "xmpp.h"
|
||||||
|
#include "xmpp-config.h"
|
||||||
|
#include "xmpp-connection.h"
|
||||||
|
//#include "api/xmpp-api-hello.h"
|
||||||
|
//#include "api/xmpp-api-error.h"
|
||||||
|
//#include "api/xmpp-api-message.h"
|
||||||
|
//#include "api/xmpp-api-user-typing.h"
|
||||||
|
|
||||||
|
xmpp_ctx_t *xmpp_context = NULL;
|
||||||
|
|
||||||
|
xmpp_conn_t *xmpp_connection = NULL;
|
||||||
|
|
||||||
|
void xmpp_log_emit_weechat(void *const userdata, const xmpp_log_level_t level, const char *const area, const char *const msg)
|
||||||
|
{
|
||||||
|
(void) userdata;
|
||||||
|
time_t date = time(NULL);
|
||||||
|
const char *timestamp = weechat_util_get_time_string(&date);
|
||||||
|
|
||||||
|
weechat_printf(
|
||||||
|
NULL,
|
||||||
|
_("%s%s %d | %s: %s - %s"),
|
||||||
|
weechat_prefix("error"), XMPP_PLUGIN_NAME,
|
||||||
|
level, timestamp, area, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_log_t xmpp_logger = {
|
||||||
|
&xmpp_log_emit_weechat,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
void xmpp_connection_init()
|
||||||
|
{
|
||||||
|
|
||||||
|
xmpp_initialize();
|
||||||
|
xmpp_context = xmpp_ctx_new(NULL, &xmpp_logger);
|
||||||
|
xmpp_connection = xmpp_conn_new(xmpp_context);
|
||||||
|
xmpp_conn_set_jid(xmpp_connection,
|
||||||
|
weechat_config_string(xmpp_config_serverdef_jid));
|
||||||
|
xmpp_conn_set_pass(xmpp_connection,
|
||||||
|
weechat_config_string(xmpp_config_serverdef_password));
|
||||||
|
//size_t case_count = sizeof(cases) / sizeof(cases[0]);
|
||||||
|
//qsort(cases, case_count, sizeof(struct stringcase), stringcase_cmp);
|
||||||
|
|
||||||
|
//xmpp_api_message_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void xmpp_connection_connect(xmpp_conn_t *connection)
|
||||||
|
{
|
||||||
|
//struct lws_context_creation_info ctxinfo;
|
||||||
|
//struct lws_client_connect_info ccinfo;
|
||||||
|
//const char *url_protocol, *url_path;
|
||||||
|
//char path[512];
|
||||||
|
|
||||||
|
//memset(&ctxinfo, 0, sizeof(ctxinfo));
|
||||||
|
//memset(&ccinfo, 0, sizeof(ccinfo));
|
||||||
|
|
||||||
|
//ccinfo.port = 443;
|
||||||
|
|
||||||
|
//if (lws_parse_uri(workspace->ws_url,
|
||||||
|
// &url_protocol, &ccinfo.address,
|
||||||
|
// &ccinfo.port, &url_path))
|
||||||
|
//{
|
||||||
|
// weechat_printf(
|
||||||
|
// workspace->buffer,
|
||||||
|
// _("%s%s: error connecting to xmpp: bad websocket uri"),
|
||||||
|
// weechat_prefix("error"), XMPP_PLUGIN_NAME);
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//path[0] = '/';
|
||||||
|
//strncpy(path + 1, url_path, sizeof(path) - 2);
|
||||||
|
//path[sizeof(path) - 1] = '\0';
|
||||||
|
|
||||||
|
//ccinfo.path = path;
|
||||||
|
|
||||||
|
//ctxinfo.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
|
||||||
|
//ctxinfo.port = CONTEXT_PORT_NO_LISTEN;
|
||||||
|
//ctxinfo.protocols = protocols;
|
||||||
|
//ctxinfo.uid = -1;
|
||||||
|
//ctxinfo.gid = -1;
|
||||||
|
|
||||||
|
//workspace->context = lws_create_context(&ctxinfo);
|
||||||
|
//if (!workspace->context)
|
||||||
|
//{
|
||||||
|
// weechat_printf(
|
||||||
|
// workspace->buffer,
|
||||||
|
// _("%s%s: error connecting to xmpp: lws init failed"),
|
||||||
|
// weechat_prefix("error"), XMPP_PLUGIN_NAME);
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// weechat_printf(
|
||||||
|
// workspace->buffer,
|
||||||
|
// _("%s%s: connecting to %s://%s:%d%s"),
|
||||||
|
// weechat_prefix("network"), XMPP_PLUGIN_NAME,
|
||||||
|
// url_protocol, ccinfo.address, ccinfo.port, path);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//ccinfo.context = workspace->context;
|
||||||
|
//ccinfo.ssl_connection = LCCSCF_USE_SSL;
|
||||||
|
//ccinfo.host = ccinfo.address;
|
||||||
|
//ccinfo.origin = ccinfo.address;
|
||||||
|
//ccinfo.ietf_version_or_minus_one = -1;
|
||||||
|
//ccinfo.protocol = protocols[0].name;
|
||||||
|
//ccinfo.pwsi = &workspace->client_wsi;
|
||||||
|
//ccinfo.userdata = workspace;
|
||||||
|
|
||||||
|
//lws_client_connect_via_info(&ccinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xmpp_connection_route_message(xmpp_conn_t *workspace,
|
||||||
|
const char *type, json_object *message)
|
||||||
|
{
|
||||||
|
//struct stringcase key;
|
||||||
|
//key.string = type;
|
||||||
|
|
||||||
|
//size_t case_count = sizeof(cases) / sizeof(cases[0]);
|
||||||
|
//void *entry_ptr = bsearch(&key, cases, case_count,
|
||||||
|
// sizeof(struct stringcase), stringcase_cmp);
|
||||||
|
|
||||||
|
//if (entry_ptr)
|
||||||
|
//{
|
||||||
|
// struct stringcase *entry = (struct stringcase *)entry_ptr;
|
||||||
|
// return (*entry->func)(workspace, message);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// weechat_printf(
|
||||||
|
// workspace->buffer,
|
||||||
|
// _("%s%s: got unhandled message of type: %s"),
|
||||||
|
// weechat_prefix("error"), XMPP_PLUGIN_NAME,
|
||||||
|
// type);
|
||||||
|
return 1;
|
||||||
|
//}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, version 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
#ifndef _XMPP_CONNECTION_H_
|
||||||
|
#define _XMPP_CONNECTION_H_
|
||||||
|
|
||||||
|
extern xmpp_ctx_t *xmpp_context;
|
||||||
|
|
||||||
|
extern xmpp_conn_t *xmpp_connection;
|
||||||
|
|
||||||
|
void xmpp_connection_init();
|
||||||
|
|
||||||
|
void xmpp_connection_connect(xmpp_conn_t *connection);
|
||||||
|
|
||||||
|
int xmpp_connection_route_message(xmpp_conn_t *connection,
|
||||||
|
const char *type, json_object *message);
|
||||||
|
|
||||||
|
#endif /*XMPP_CONNECTION_H*/
|
Loading…
Reference in New Issue