Minor code style changes
This commit is contained in:
@@ -86,16 +86,19 @@ send_response(struct MHD_Connection* conn, const char* body, int status_code)
|
|||||||
response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_YES);
|
response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response)
|
if (!response) {
|
||||||
return MHD_NO;
|
return MHD_NO;
|
||||||
|
}
|
||||||
|
|
||||||
int ret = MHD_queue_response(conn, status_code, response);
|
int ret = MHD_queue_response(conn, status_code, response);
|
||||||
MHD_destroy_response(response);
|
MHD_destroy_response(response);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method,
|
int
|
||||||
const char* version, const char* data, size_t* size, void** con_cls)
|
connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const char* method, const char* version,
|
||||||
|
const char* data, size_t* size, void** con_cls)
|
||||||
{
|
{
|
||||||
#ifdef PLATFORM_OSX
|
#ifdef PLATFORM_OSX
|
||||||
pthread_setname_np("http");
|
pthread_setname_np("http");
|
||||||
@@ -129,55 +132,49 @@ int connection_cb(void* cls, struct MHD_Connection* conn, const char* url, const
|
|||||||
*size = 0;
|
*size = 0;
|
||||||
|
|
||||||
return MHD_YES;
|
return MHD_YES;
|
||||||
} else {
|
}
|
||||||
const char *id = NULL;
|
|
||||||
const char *query = NULL;
|
|
||||||
|
|
||||||
switch (con_info->stbbr_op) {
|
const char *id = NULL;
|
||||||
case STBBR_OP_SEND:
|
const char *query = NULL;
|
||||||
{
|
int res = 0;
|
||||||
server_send(con_info->body->str);
|
|
||||||
return send_response(conn, NULL, MHD_HTTP_OK);
|
|
||||||
}
|
|
||||||
case STBBR_OP_FOR:
|
|
||||||
{
|
|
||||||
id = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "id");
|
|
||||||
query = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "query");
|
|
||||||
if (id && query) {
|
|
||||||
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id) {
|
switch (con_info->stbbr_op) {
|
||||||
prime_for_id(id, con_info->body->str);
|
case STBBR_OP_SEND:
|
||||||
return send_response(conn, NULL, MHD_HTTP_CREATED);
|
server_send(con_info->body->str);
|
||||||
}
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
prime_for_query(query, con_info->body->str);
|
|
||||||
return send_response(conn, NULL, MHD_HTTP_CREATED);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return send_response(conn, NULL, MHD_HTTP_OK);
|
||||||
|
case STBBR_OP_FOR:
|
||||||
|
id = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "id");
|
||||||
|
query = MHD_lookup_connection_value(conn, MHD_GET_ARGUMENT_KIND, "query");
|
||||||
|
if (id && query) {
|
||||||
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
case STBBR_OP_VERIFY:
|
|
||||||
{
|
if (id) {
|
||||||
int res = verify_any(con_info->body->str, TRUE);
|
prime_for_id(id, con_info->body->str);
|
||||||
if (res) {
|
return send_response(conn, NULL, MHD_HTTP_CREATED);
|
||||||
return send_response(conn, "true", MHD_HTTP_OK);
|
|
||||||
} else {
|
|
||||||
return send_response(conn, "false", MHD_HTTP_OK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
{
|
if (query) {
|
||||||
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
prime_for_query(query, con_info->body->str);
|
||||||
|
return send_response(conn, NULL, MHD_HTTP_CREATED);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
||||||
|
case STBBR_OP_VERIFY:
|
||||||
|
res = verify_any(con_info->body->str, TRUE);
|
||||||
|
if (res) {
|
||||||
|
return send_response(conn, "true", MHD_HTTP_OK);
|
||||||
|
} else {
|
||||||
|
return send_response(conn, "false", MHD_HTTP_OK);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return send_response(conn, NULL, MHD_HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void request_completed(void* cls, struct MHD_Connection* conn,
|
void
|
||||||
void** con_cls, enum MHD_RequestTerminationCode termcode)
|
request_completed(void* cls, struct MHD_Connection* conn, void** con_cls, enum MHD_RequestTerminationCode termcode)
|
||||||
{
|
{
|
||||||
ConnectionInfo *con_info = (ConnectionInfo*) *con_cls;
|
ConnectionInfo *con_info = (ConnectionInfo*) *con_cls;
|
||||||
if (con_info) {
|
if (con_info) {
|
||||||
|
|||||||
217
src/server/log.c
217
src/server/log.c
@@ -41,75 +41,11 @@ static gboolean logready = FALSE;
|
|||||||
static stbbr_log_t minlevel;
|
static stbbr_log_t minlevel;
|
||||||
pthread_mutex_t loglock;
|
pthread_mutex_t loglock;
|
||||||
|
|
||||||
gchar *
|
static gchar* _xdg_get_data_home(void);
|
||||||
_xdg_get_data_home(void)
|
static gchar* _get_main_log_file(void);
|
||||||
{
|
static gboolean _create_dir(char *name);
|
||||||
gchar *xdg_data_home = getenv("XDG_DATA_HOME");
|
static gboolean _mkdir_recursive(const char *dir);
|
||||||
if (xdg_data_home)
|
static char* _levelstr(stbbr_log_t loglevel);
|
||||||
g_strstrip(xdg_data_home);
|
|
||||||
|
|
||||||
if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) {
|
|
||||||
return strdup(xdg_data_home);
|
|
||||||
} else {
|
|
||||||
GString *default_path = g_string_new(getenv("HOME"));
|
|
||||||
g_string_append(default_path, "/.local/share");
|
|
||||||
gchar *result = strdup(default_path->str);
|
|
||||||
g_string_free(default_path, TRUE);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gchar *
|
|
||||||
_get_main_log_file(void)
|
|
||||||
{
|
|
||||||
gchar *xdg_data = _xdg_get_data_home();
|
|
||||||
GString *logfile = g_string_new(xdg_data);
|
|
||||||
g_string_append(logfile, "/stabber/logs/stabber");
|
|
||||||
g_string_append(logfile, ".log");
|
|
||||||
gchar *result = strdup(logfile->str);
|
|
||||||
free(xdg_data);
|
|
||||||
g_string_free(logfile, TRUE);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
_create_dir(char *name)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
if (stat(name, &sb) != 0) {
|
|
||||||
if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((sb.st_mode & S_IFDIR) != S_IFDIR) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
_mkdir_recursive(const char *dir)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
gboolean result = TRUE;
|
|
||||||
|
|
||||||
for (i = 1; i <= strlen(dir); i++) {
|
|
||||||
if (dir[i] == '/' || dir[i] == '\0') {
|
|
||||||
gchar *next_dir = g_strndup(dir, i);
|
|
||||||
result = _create_dir(next_dir);
|
|
||||||
g_free(next_dir);
|
|
||||||
if (!result) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_init(stbbr_log_t loglevel)
|
log_init(stbbr_log_t loglevel)
|
||||||
@@ -131,49 +67,39 @@ log_init(stbbr_log_t loglevel)
|
|||||||
pthread_mutex_unlock(&loglock);
|
pthread_mutex_unlock(&loglock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
|
||||||
_levelstr(stbbr_log_t loglevel)
|
|
||||||
{
|
|
||||||
switch (loglevel) {
|
|
||||||
case STBBR_LOGERROR: return "ERR";
|
|
||||||
case STBBR_LOGWARN: return "WRN";
|
|
||||||
case STBBR_LOGINFO: return "INF";
|
|
||||||
case STBBR_LOGDEBUG: return "DBG";
|
|
||||||
default: return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_println(stbbr_log_t loglevel, const char * const msg, ...)
|
log_println(stbbr_log_t loglevel, const char * const msg, ...)
|
||||||
{
|
{
|
||||||
if (logready && loglevel >= minlevel) {
|
if (!logready || loglevel < minlevel) {
|
||||||
pthread_mutex_lock(&loglock);
|
return;
|
||||||
va_list arg;
|
}
|
||||||
va_start(arg, msg);
|
|
||||||
GString *fmt_msg = g_string_new(NULL);
|
pthread_mutex_lock(&loglock);
|
||||||
g_string_vprintf(fmt_msg, msg, arg);
|
va_list arg;
|
||||||
GTimeZone *tz = g_time_zone_new_local();
|
va_start(arg, msg);
|
||||||
GDateTime *dt = g_date_time_new_now(tz);
|
GString *fmt_msg = g_string_new(NULL);
|
||||||
gchar *date_fmt = g_date_time_format(dt, "%d/%m/%Y %H:%M:%S");
|
g_string_vprintf(fmt_msg, msg, arg);
|
||||||
char thr_name[16];
|
GTimeZone *tz = g_time_zone_new_local();
|
||||||
|
GDateTime *dt = g_date_time_new_now(tz);
|
||||||
|
gchar *date_fmt = g_date_time_format(dt, "%d/%m/%Y %H:%M:%S");
|
||||||
|
char thr_name[16];
|
||||||
|
|
||||||
#ifdef PLATFORM_OSX
|
#ifdef PLATFORM_OSX
|
||||||
pthread_t self = pthread_self();
|
pthread_t self = pthread_self();
|
||||||
pthread_getname_np(self, thr_name, 16);
|
pthread_getname_np(self, thr_name, 16);
|
||||||
#else
|
#else
|
||||||
prctl(PR_GET_NAME, thr_name);
|
prctl(PR_GET_NAME, thr_name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *levelstr = _levelstr(loglevel);
|
char *levelstr = _levelstr(loglevel);
|
||||||
fprintf(logp, "%s: [%s] [%s] %s\n", date_fmt, thr_name, levelstr, fmt_msg->str);
|
fprintf(logp, "%s: [%s] [%s] %s\n", date_fmt, thr_name, levelstr, fmt_msg->str);
|
||||||
g_date_time_unref(dt);
|
g_date_time_unref(dt);
|
||||||
g_time_zone_unref(tz);
|
g_time_zone_unref(tz);
|
||||||
fflush(logp);
|
fflush(logp);
|
||||||
g_free(date_fmt);
|
g_free(date_fmt);
|
||||||
g_string_free(fmt_msg, TRUE);
|
g_string_free(fmt_msg, TRUE);
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
pthread_mutex_unlock(&loglock);
|
pthread_mutex_unlock(&loglock);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -186,3 +112,86 @@ log_close(void)
|
|||||||
logready = FALSE;
|
logready = FALSE;
|
||||||
pthread_mutex_unlock(&loglock);
|
pthread_mutex_unlock(&loglock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
_xdg_get_data_home(void)
|
||||||
|
{
|
||||||
|
gchar *xdg_data_home = getenv("XDG_DATA_HOME");
|
||||||
|
if (xdg_data_home) {
|
||||||
|
g_strstrip(xdg_data_home);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xdg_data_home && (strcmp(xdg_data_home, "") != 0)) {
|
||||||
|
return strdup(xdg_data_home);
|
||||||
|
}
|
||||||
|
|
||||||
|
GString *default_path = g_string_new(getenv("HOME"));
|
||||||
|
g_string_append(default_path, "/.local/share");
|
||||||
|
gchar *result = strdup(default_path->str);
|
||||||
|
g_string_free(default_path, TRUE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
_get_main_log_file(void)
|
||||||
|
{
|
||||||
|
gchar *xdg_data = _xdg_get_data_home();
|
||||||
|
GString *logfile = g_string_new(xdg_data);
|
||||||
|
g_string_append(logfile, "/stabber/logs/stabber");
|
||||||
|
g_string_append(logfile, ".log");
|
||||||
|
gchar *result = strdup(logfile->str);
|
||||||
|
free(xdg_data);
|
||||||
|
g_string_free(logfile, TRUE);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_create_dir(char *name)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
if (stat(name, &sb) != 0) {
|
||||||
|
if (errno != ENOENT || mkdir(name, S_IRWXU) != 0) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((sb.st_mode & S_IFDIR) != S_IFDIR) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_mkdir_recursive(const char *dir)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
gboolean result = TRUE;
|
||||||
|
|
||||||
|
for (i = 1; i <= strlen(dir); i++) {
|
||||||
|
if (dir[i] == '/' || dir[i] == '\0') {
|
||||||
|
gchar *next_dir = g_strndup(dir, i);
|
||||||
|
result = _create_dir(next_dir);
|
||||||
|
g_free(next_dir);
|
||||||
|
if (!result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
_levelstr(stbbr_log_t loglevel)
|
||||||
|
{
|
||||||
|
switch (loglevel) {
|
||||||
|
case STBBR_LOGERROR: return "ERR";
|
||||||
|
case STBBR_LOGWARN: return "WRN";
|
||||||
|
case STBBR_LOGINFO: return "INF";
|
||||||
|
case STBBR_LOGDEBUG: return "DBG";
|
||||||
|
default: return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ prime_required_passwd(char *password)
|
|||||||
required_passwd = strdup(password);
|
required_passwd = strdup(password);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char*
|
||||||
prime_get_passwd(void)
|
prime_get_passwd(void)
|
||||||
{
|
{
|
||||||
return required_passwd;
|
return required_passwd;
|
||||||
@@ -76,11 +76,12 @@ prime_get_passwd(void)
|
|||||||
void
|
void
|
||||||
prime_for_id(const char *id, char *stream)
|
prime_for_id(const char *id, char *stream)
|
||||||
{
|
{
|
||||||
if (idstubs) {
|
if (!idstubs) {
|
||||||
log_println(STBBR_LOGDEBUG, "Received stub for id: %s, stanza: %s", id, stream);
|
return;
|
||||||
|
|
||||||
g_hash_table_insert(idstubs, strdup(id), strdup(stream));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGDEBUG, "Received stub for id: %s, stanza: %s", id, stream);
|
||||||
|
g_hash_table_insert(idstubs, strdup(id), strdup(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
@@ -92,15 +93,16 @@ prime_get_for_id(const char *id)
|
|||||||
void
|
void
|
||||||
prime_for_query(const char *query, char *stream)
|
prime_for_query(const char *query, char *stream)
|
||||||
{
|
{
|
||||||
if (querystubs) {
|
if (!querystubs) {
|
||||||
log_println(STBBR_LOGDEBUG, "Received stub for query: %s, stanza: %s", query, stream);
|
return;
|
||||||
|
|
||||||
XMPPStanza *stanza = stanza_parse(stream);
|
|
||||||
g_hash_table_insert(querystubs, strdup(query), stanza);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGDEBUG, "Received stub for query: %s, stanza: %s", query, stream);
|
||||||
|
XMPPStanza *stanza = stanza_parse(stream);
|
||||||
|
g_hash_table_insert(querystubs, strdup(query), stanza);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMPPStanza *
|
XMPPStanza*
|
||||||
prime_get_for_query(const char *query)
|
prime_get_for_query(const char *query)
|
||||||
{
|
{
|
||||||
return g_hash_table_lookup(querystubs, query);
|
return g_hash_table_lookup(querystubs, query);
|
||||||
|
|||||||
@@ -53,17 +53,17 @@
|
|||||||
#define STREAM_END "</stream:stream>"
|
#define STREAM_END "</stream:stream>"
|
||||||
|
|
||||||
pthread_mutex_t send_queue_lock;
|
pthread_mutex_t send_queue_lock;
|
||||||
|
|
||||||
static GList *send_queue;
|
static GList *send_queue;
|
||||||
|
|
||||||
static XMPPClient *client;
|
static XMPPClient *client;
|
||||||
|
|
||||||
static void _shutdown(void);
|
|
||||||
|
|
||||||
static int listen_socket;
|
static int listen_socket;
|
||||||
static pthread_t server_thread;
|
static pthread_t server_thread;
|
||||||
static gboolean kill_recv = FALSE;
|
static gboolean kill_recv = FALSE;
|
||||||
static gboolean httpapi_run = FALSE;
|
static gboolean httpapi_run = FALSE;
|
||||||
|
|
||||||
|
static void _shutdown(void);
|
||||||
|
static void* _start_server_cb(void* userdata);
|
||||||
|
|
||||||
void
|
void
|
||||||
write_stream(const char * const stream)
|
write_stream(const char * const stream)
|
||||||
{
|
{
|
||||||
@@ -225,23 +225,27 @@ void
|
|||||||
id_callback(const char *id)
|
id_callback(const char *id)
|
||||||
{
|
{
|
||||||
char *stream = prime_get_for_id(id);
|
char *stream = prime_get_for_id(id);
|
||||||
if (stream) {
|
if (!stream) {
|
||||||
log_println(STBBR_LOGINFO, "--> ID callback fired for '%s'", id);
|
return;
|
||||||
write_stream(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGINFO, "--> ID callback fired for '%s'", id);
|
||||||
|
write_stream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
query_callback(const char *query, const char *id)
|
query_callback(const char *query, const char *id)
|
||||||
{
|
{
|
||||||
XMPPStanza *stanza = prime_get_for_query(query);
|
XMPPStanza *stanza = prime_get_for_query(query);
|
||||||
if (stanza) {
|
if (!stanza) {
|
||||||
log_println(STBBR_LOGINFO, "--> QUERY callback fired for '%s'", query);
|
return;
|
||||||
stanza_set_id(stanza, id);
|
|
||||||
char *stream = stanza_to_string(stanza);
|
|
||||||
write_stream(stream);
|
|
||||||
free(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGINFO, "--> QUERY callback fired for '%s'", query);
|
||||||
|
stanza_set_id(stanza, id);
|
||||||
|
char *stream = stanza_to_string(stanza);
|
||||||
|
write_stream(stream);
|
||||||
|
free(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -258,54 +262,6 @@ server_wait_for(char *id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void*
|
|
||||||
_start_server_cb(void* userdata)
|
|
||||||
{
|
|
||||||
#ifdef PLATFORM_OSX
|
|
||||||
pthread_setname_np("stbr");
|
|
||||||
#else
|
|
||||||
prctl(PR_SET_NAME, "stbr");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct sockaddr_in client_addr;
|
|
||||||
|
|
||||||
// listen socket non blocking
|
|
||||||
int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK);
|
|
||||||
if (res == -1) {
|
|
||||||
log_println(STBBR_LOGERROR, "Error setting nonblocking on listen socket: %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_println(STBBR_LOGINFO, "Waiting for incoming connection...");
|
|
||||||
|
|
||||||
// wait for connection
|
|
||||||
int c = sizeof(struct sockaddr_in);
|
|
||||||
int client_socket;
|
|
||||||
errno = 0;
|
|
||||||
while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) {
|
|
||||||
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
|
||||||
log_println(STBBR_LOGERROR, "Accept failed: %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
errno = 0;
|
|
||||||
usleep(1000 * 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// client socket non blocking
|
|
||||||
res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK);
|
|
||||||
if (res == -1) {
|
|
||||||
log_println(STBBR_LOGERROR, "Error setting nonblocking on client socket: %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
client = xmppclient_new(client_addr, client_socket);
|
|
||||||
parser_init(stream_start_callback, auth_callback, id_callback, query_callback);
|
|
||||||
|
|
||||||
read_stream();
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
server_run(stbbr_log_t loglevel, int port, int httpport)
|
server_run(stbbr_log_t loglevel, int port, int httpport)
|
||||||
{
|
{
|
||||||
@@ -401,11 +357,61 @@ server_send(char *stream)
|
|||||||
void
|
void
|
||||||
server_stop(void)
|
server_stop(void)
|
||||||
{
|
{
|
||||||
if (!kill_recv) {
|
if (kill_recv) {
|
||||||
log_println(STBBR_LOGINFO, "SERVER STOP");
|
return;
|
||||||
kill_recv = TRUE;
|
|
||||||
pthread_join(server_thread, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGINFO, "SERVER STOP");
|
||||||
|
kill_recv = TRUE;
|
||||||
|
pthread_join(server_thread, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
_start_server_cb(void* userdata)
|
||||||
|
{
|
||||||
|
#ifdef PLATFORM_OSX
|
||||||
|
pthread_setname_np("stbr");
|
||||||
|
#else
|
||||||
|
prctl(PR_SET_NAME, "stbr");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
|
||||||
|
// listen socket non blocking
|
||||||
|
int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK);
|
||||||
|
if (res == -1) {
|
||||||
|
log_println(STBBR_LOGERROR, "Error setting nonblocking on listen socket: %s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGINFO, "Waiting for incoming connection...");
|
||||||
|
|
||||||
|
// wait for connection
|
||||||
|
int c = sizeof(struct sockaddr_in);
|
||||||
|
int client_socket;
|
||||||
|
errno = 0;
|
||||||
|
while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) {
|
||||||
|
if (errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||||
|
log_println(STBBR_LOGERROR, "Accept failed: %s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
usleep(1000 * 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// client socket non blocking
|
||||||
|
res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK);
|
||||||
|
if (res == -1) {
|
||||||
|
log_println(STBBR_LOGERROR, "Error setting nonblocking on client socket: %s", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
client = xmppclient_new(client_addr, client_socket);
|
||||||
|
parser_init(stream_start_callback, auth_callback, id_callback, query_callback);
|
||||||
|
|
||||||
|
read_stream();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ typedef struct parse_state_t {
|
|||||||
XMPPStanza *curr_stanza;
|
XMPPStanza *curr_stanza;
|
||||||
} ParseState;
|
} ParseState;
|
||||||
|
|
||||||
|
static void _start_element(void *data, const char *element, const char **attributes);
|
||||||
|
static void _end_element(void *data, const char *element);
|
||||||
|
static void _handle_data(void *data, const char *content, int length);
|
||||||
|
static void _attrs_free(XMPPAttr *attr);
|
||||||
|
|
||||||
XMPPStanza*
|
XMPPStanza*
|
||||||
stanza_new(const char *name, const char **attributes)
|
stanza_new(const char *name, const char **attributes)
|
||||||
{
|
{
|
||||||
@@ -40,20 +45,18 @@ stanza_new(const char *name, const char **attributes)
|
|||||||
stanza->content = NULL;
|
stanza->content = NULL;
|
||||||
stanza->children = NULL;
|
stanza->children = NULL;
|
||||||
stanza->attrs = NULL;
|
stanza->attrs = NULL;
|
||||||
if (attributes[0]) {
|
int i;
|
||||||
int i;
|
for (i = 0; attributes[i]; i += 2) {
|
||||||
for (i = 0; attributes[i]; i += 2) {
|
XMPPAttr *attr = malloc(sizeof(XMPPAttr));
|
||||||
XMPPAttr *attr = malloc(sizeof(XMPPAttr));
|
attr->name = strdup(attributes[i]);
|
||||||
attr->name = strdup(attributes[i]);
|
attr->value = strdup(attributes[i+1]);
|
||||||
attr->value = strdup(attributes[i+1]);
|
stanza->attrs = g_list_append(stanza->attrs, attr);
|
||||||
stanza->attrs = g_list_append(stanza->attrs, attr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stanza;
|
return stanza;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char*
|
||||||
stanza_to_string(XMPPStanza *stanza)
|
stanza_to_string(XMPPStanza *stanza)
|
||||||
{
|
{
|
||||||
GString *stanza_str = g_string_new("<");
|
GString *stanza_str = g_string_new("<");
|
||||||
@@ -168,7 +171,7 @@ stanza_get_child_by_name(XMPPStanza *stanza, char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char*
|
||||||
stanza_get_id(XMPPStanza *stanza)
|
stanza_get_id(XMPPStanza *stanza)
|
||||||
{
|
{
|
||||||
if (!stanza) {
|
if (!stanza) {
|
||||||
@@ -213,7 +216,7 @@ stanza_set_id(XMPPStanza *stanza, const char *id)
|
|||||||
stanza->attrs = g_list_append(stanza->attrs, attrnew);
|
stanza->attrs = g_list_append(stanza->attrs, attrnew);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char*
|
||||||
stanza_get_attr(XMPPStanza *stanza, const char *name)
|
stanza_get_attr(XMPPStanza *stanza, const char *name)
|
||||||
{
|
{
|
||||||
if (!stanza->attrs) {
|
if (!stanza->attrs) {
|
||||||
@@ -233,7 +236,7 @@ stanza_get_attr(XMPPStanza *stanza, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char*
|
||||||
stanza_get_query_request(XMPPStanza *stanza)
|
stanza_get_query_request(XMPPStanza *stanza)
|
||||||
{
|
{
|
||||||
if (g_strcmp0(stanza->name, "iq") != 0) {
|
if (g_strcmp0(stanza->name, "iq") != 0) {
|
||||||
@@ -258,32 +261,42 @@ stanza_get_query_request(XMPPStanza *stanza)
|
|||||||
return xmlns;
|
return xmlns;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_attrs_free(XMPPAttr *attr)
|
|
||||||
{
|
|
||||||
if (attr) {
|
|
||||||
free(attr->name);
|
|
||||||
free(attr->value);
|
|
||||||
free(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
stanza_free(XMPPStanza *stanza)
|
stanza_free(XMPPStanza *stanza)
|
||||||
{
|
{
|
||||||
if (stanza) {
|
if (!stanza) {
|
||||||
free(stanza->name);
|
return;
|
||||||
if (stanza->content) {
|
|
||||||
g_string_free(stanza->content, TRUE);
|
|
||||||
}
|
|
||||||
g_list_free_full(stanza->attrs, (GDestroyNotify)_attrs_free);
|
|
||||||
g_list_free_full(stanza->children, (GDestroyNotify)stanza_free);
|
|
||||||
free(stanza);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(stanza->name);
|
||||||
|
if (stanza->content) {
|
||||||
|
g_string_free(stanza->content, TRUE);
|
||||||
|
}
|
||||||
|
g_list_free_full(stanza->attrs, (GDestroyNotify)_attrs_free);
|
||||||
|
g_list_free_full(stanza->children, (GDestroyNotify)stanza_free);
|
||||||
|
free(stanza);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMPPStanza*
|
||||||
|
stanza_parse(char *stanza_text)
|
||||||
|
{
|
||||||
|
ParseState *state = malloc(sizeof(ParseState));
|
||||||
|
state->depth = 0;
|
||||||
|
state->curr_stanza = NULL;
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
XML_SetElementHandler(parser, _start_element, _end_element);
|
||||||
|
XML_SetCharacterDataHandler(parser, _handle_data);
|
||||||
|
XML_SetUserData(parser, state);
|
||||||
|
|
||||||
|
XML_Parse(parser, stanza_text, strlen(stanza_text), 0);
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
|
||||||
|
return state->curr_stanza;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_element(void *data, const char *element, const char **attributes)
|
_start_element(void *data, const char *element, const char **attributes)
|
||||||
{
|
{
|
||||||
ParseState *state = data;
|
ParseState *state = data;
|
||||||
|
|
||||||
@@ -300,7 +313,7 @@ start_element(void *data, const char *element, const char **attributes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
end_element(void *data, const char *element)
|
_end_element(void *data, const char *element)
|
||||||
{
|
{
|
||||||
ParseState *state = data;
|
ParseState *state = data;
|
||||||
|
|
||||||
@@ -313,7 +326,7 @@ end_element(void *data, const char *element)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_data(void *data, const char *content, int length)
|
_handle_data(void *data, const char *content, int length)
|
||||||
{
|
{
|
||||||
ParseState *state = data;
|
ParseState *state = data;
|
||||||
|
|
||||||
@@ -324,20 +337,14 @@ handle_data(void *data, const char *content, int length)
|
|||||||
g_string_append_len(state->curr_stanza->content, content, length);
|
g_string_append_len(state->curr_stanza->content, content, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
XMPPStanza *
|
static void
|
||||||
stanza_parse(char *stanza_text)
|
_attrs_free(XMPPAttr *attr)
|
||||||
{
|
{
|
||||||
ParseState *state = malloc(sizeof(ParseState));
|
if (!attr) {
|
||||||
state->depth = 0;
|
return;
|
||||||
state->curr_stanza = NULL;
|
}
|
||||||
|
|
||||||
XML_Parser parser = XML_ParserCreate(NULL);
|
free(attr->name);
|
||||||
XML_SetElementHandler(parser, start_element, end_element);
|
free(attr->value);
|
||||||
XML_SetCharacterDataHandler(parser, handle_data);
|
free(attr);
|
||||||
XML_SetUserData(parser, state);
|
|
||||||
|
|
||||||
XML_Parse(parser, stanza_text, strlen(stanza_text), 0);
|
|
||||||
XML_ParserFree(parser);
|
|
||||||
|
|
||||||
return state->curr_stanza;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@
|
|||||||
pthread_mutex_t stanzas_lock;
|
pthread_mutex_t stanzas_lock;
|
||||||
static GList *stanzas;
|
static GList *stanzas;
|
||||||
|
|
||||||
|
static int _xmpp_attr_equal(XMPPAttr *attr1, XMPPAttr *attr2);
|
||||||
|
static int _stanzas_equal(XMPPStanza *first, XMPPStanza *second);
|
||||||
|
|
||||||
int
|
int
|
||||||
stanzas_contains_id(char *id)
|
stanzas_contains_id(char *id)
|
||||||
{
|
{
|
||||||
@@ -63,6 +66,64 @@ stanzas_add(XMPPStanza *stanza)
|
|||||||
pthread_mutex_unlock(&stanzas_lock);
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
stanzas_verify_any(XMPPStanza *stanza)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&stanzas_lock);
|
||||||
|
if (!stanzas) {
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *curr = g_list_last(stanzas);
|
||||||
|
while (curr) {
|
||||||
|
XMPPStanza *curr_stanza = curr->data;
|
||||||
|
if (_stanzas_equal(stanza, curr_stanza) == 0) {
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr = g_list_previous(curr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
stanzas_verify_last(XMPPStanza *stanza)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&stanzas_lock);
|
||||||
|
if (!stanzas) {
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *last = g_list_last(stanzas);
|
||||||
|
if (!last) {
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMPPStanza *last_stanza = (XMPPStanza *)last->data;
|
||||||
|
int res = _stanzas_equal(stanza, last_stanza);
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
if (res == 0) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
stanzas_free_all(void)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&stanzas_lock);
|
||||||
|
g_list_free_full(stanzas, (GDestroyNotify)stanza_free);
|
||||||
|
stanzas = NULL;
|
||||||
|
pthread_mutex_unlock(&stanzas_lock);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_xmpp_attr_equal(XMPPAttr *attr1, XMPPAttr *attr2)
|
_xmpp_attr_equal(XMPPAttr *attr1, XMPPAttr *attr2)
|
||||||
{
|
{
|
||||||
@@ -148,61 +209,3 @@ _stanzas_equal(XMPPStanza *first, XMPPStanza *second)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
stanzas_verify_any(XMPPStanza *stanza)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&stanzas_lock);
|
|
||||||
if (!stanzas) {
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GList *curr = g_list_last(stanzas);
|
|
||||||
while (curr) {
|
|
||||||
XMPPStanza *curr_stanza = curr->data;
|
|
||||||
if (_stanzas_equal(stanza, curr_stanza) == 0) {
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr = g_list_previous(curr);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
stanzas_verify_last(XMPPStanza *stanza)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&stanzas_lock);
|
|
||||||
if (!stanzas) {
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
GList *last = g_list_last(stanzas);
|
|
||||||
if (!last) {
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
XMPPStanza *last_stanza = (XMPPStanza *)last->data;
|
|
||||||
int res = _stanzas_equal(stanza, last_stanza);
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
if (res == 0) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
stanzas_free_all(void)
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&stanzas_lock);
|
|
||||||
g_list_free_full(stanzas, (GDestroyNotify)stanza_free);
|
|
||||||
stanzas = NULL;
|
|
||||||
pthread_mutex_unlock(&stanzas_lock);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -42,8 +42,59 @@ static auth_func auth_cb = NULL;
|
|||||||
static id_func id_cb = NULL;
|
static id_func id_cb = NULL;
|
||||||
static query_func query_cb = NULL;
|
static query_func query_cb = NULL;
|
||||||
|
|
||||||
|
static void _start_element(void *data, const char *element, const char **attributes);
|
||||||
|
static void _end_element(void *data, const char *element);
|
||||||
|
static void _handle_data(void *data, const char *content, int length);
|
||||||
|
|
||||||
|
void
|
||||||
|
parser_init(stream_start_func startcb, auth_func authcb, id_func idcb, query_func querycb)
|
||||||
|
{
|
||||||
|
if (curr_string) {
|
||||||
|
g_string_free(curr_string, TRUE);
|
||||||
|
}
|
||||||
|
curr_string = g_string_new("");
|
||||||
|
|
||||||
|
stream_start_cb = startcb;
|
||||||
|
auth_cb = authcb;
|
||||||
|
id_cb = idcb;
|
||||||
|
query_cb = querycb;
|
||||||
|
|
||||||
|
parser = XML_ParserCreate(NULL);
|
||||||
|
XML_SetElementHandler(parser, _start_element, _end_element);
|
||||||
|
XML_SetCharacterDataHandler(parser, _handle_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parser_feed(char *chunk, int len)
|
||||||
|
{
|
||||||
|
g_string_append_len(curr_string, chunk, len);
|
||||||
|
int res = XML_Parse(parser, chunk, len, 0);
|
||||||
|
parser_reset();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parser_close(void)
|
||||||
|
{
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
parser = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
parser_reset(void)
|
||||||
|
{
|
||||||
|
if (do_reset != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parser_close();
|
||||||
|
parser_init(stream_start_cb, auth_cb, id_cb, query_cb);
|
||||||
|
do_reset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_element(void *data, const char *element, const char **attributes)
|
_start_element(void *data, const char *element, const char **attributes)
|
||||||
{
|
{
|
||||||
if (g_strcmp0(element, "stream:stream") == 0) {
|
if (g_strcmp0(element, "stream:stream") == 0) {
|
||||||
log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str);
|
log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str);
|
||||||
@@ -66,35 +117,35 @@ start_element(void *data, const char *element, const char **attributes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
end_element(void *data, const char *element)
|
_end_element(void *data, const char *element)
|
||||||
{
|
{
|
||||||
depth--;
|
depth--;
|
||||||
|
|
||||||
if (depth > 0) {
|
if (depth > 0) {
|
||||||
stanza_add_child(curr_stanza->parent, curr_stanza);
|
stanza_add_child(curr_stanza->parent, curr_stanza);
|
||||||
curr_stanza = curr_stanza->parent;
|
curr_stanza = curr_stanza->parent;
|
||||||
} else {
|
return;
|
||||||
log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str);
|
|
||||||
stanzas_add(curr_stanza);
|
|
||||||
if (stanza_get_child_by_ns(curr_stanza, "jabber:iq:auth")) {
|
|
||||||
auth_cb(curr_stanza);
|
|
||||||
} else {
|
|
||||||
const char *id = stanza_get_id(curr_stanza);
|
|
||||||
if (id) {
|
|
||||||
id_cb(id);
|
|
||||||
}
|
|
||||||
const char *query = stanza_get_query_request(curr_stanza);
|
|
||||||
if (query) {
|
|
||||||
query_cb(query, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_reset = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_println(STBBR_LOGINFO, "RECV: %s", curr_string->str);
|
||||||
|
stanzas_add(curr_stanza);
|
||||||
|
if (stanza_get_child_by_ns(curr_stanza, "jabber:iq:auth")) {
|
||||||
|
auth_cb(curr_stanza);
|
||||||
|
} else {
|
||||||
|
const char *id = stanza_get_id(curr_stanza);
|
||||||
|
if (id) {
|
||||||
|
id_cb(id);
|
||||||
|
}
|
||||||
|
const char *query = stanza_get_query_request(curr_stanza);
|
||||||
|
if (query) {
|
||||||
|
query_cb(query, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_reset = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_data(void *data, const char *content, int length)
|
_handle_data(void *data, const char *content, int length)
|
||||||
{
|
{
|
||||||
if (!curr_stanza->content) {
|
if (!curr_stanza->content) {
|
||||||
curr_stanza->content = g_string_new("");
|
curr_stanza->content = g_string_new("");
|
||||||
@@ -102,47 +153,3 @@ handle_data(void *data, const char *content, int length)
|
|||||||
|
|
||||||
g_string_append_len(curr_stanza->content, content, length);
|
g_string_append_len(curr_stanza->content, content, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
parser_init(stream_start_func startcb, auth_func authcb, id_func idcb, query_func querycb)
|
|
||||||
{
|
|
||||||
if (curr_string) {
|
|
||||||
g_string_free(curr_string, TRUE);
|
|
||||||
}
|
|
||||||
curr_string = g_string_new("");
|
|
||||||
|
|
||||||
stream_start_cb = startcb;
|
|
||||||
auth_cb = authcb;
|
|
||||||
id_cb = idcb;
|
|
||||||
query_cb = querycb;
|
|
||||||
|
|
||||||
parser = XML_ParserCreate(NULL);
|
|
||||||
XML_SetElementHandler(parser, start_element, end_element);
|
|
||||||
XML_SetCharacterDataHandler(parser, handle_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
parser_feed(char *chunk, int len)
|
|
||||||
{
|
|
||||||
g_string_append_len(curr_string, chunk, len);
|
|
||||||
int res = XML_Parse(parser, chunk, len, 0);
|
|
||||||
parser_reset();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
parser_close(void)
|
|
||||||
{
|
|
||||||
XML_ParserFree(parser);
|
|
||||||
parser = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
parser_reset(void)
|
|
||||||
{
|
|
||||||
if (do_reset == 1) {
|
|
||||||
parser_close();
|
|
||||||
parser_init(stream_start_cb, auth_cb, id_cb, query_cb);
|
|
||||||
do_reset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -48,16 +48,18 @@ xmppclient_new(struct sockaddr_in client_addr, int socket)
|
|||||||
void
|
void
|
||||||
xmppclient_end_session(XMPPClient *client)
|
xmppclient_end_session(XMPPClient *client)
|
||||||
{
|
{
|
||||||
if (client) {
|
if (!client) {
|
||||||
if (client->sock) {
|
return;
|
||||||
shutdown(client->sock, 2);
|
|
||||||
while (recv(client->sock, NULL, 1, 0) > 0) {}
|
|
||||||
close(client->sock);
|
|
||||||
}
|
|
||||||
free(client->ip);
|
|
||||||
free(client->username);
|
|
||||||
free(client->password);
|
|
||||||
free(client->resource);
|
|
||||||
free(client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client->sock) {
|
||||||
|
shutdown(client->sock, 2);
|
||||||
|
while (recv(client->sock, NULL, 1, 0) > 0) {}
|
||||||
|
close(client->sock);
|
||||||
|
}
|
||||||
|
free(client->ip);
|
||||||
|
free(client->username);
|
||||||
|
free(client->password);
|
||||||
|
free(client->resource);
|
||||||
|
free(client);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user