introduced callback_job:
simple asynchronous method invocation use daemons thread pool for all threads proper cancellation and cleanups cancellation mechanism to dynamically unload multithreaded code unified event_queue and scheduler => scheduler unified job_queue and thread_pool => processor removed job_type_t, not really needed fixes here, there and everywhere
This commit is contained in:
@@ -24,10 +24,24 @@
|
||||
|
||||
#include "xml_interface.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include <libxml/xmlwriter.h>
|
||||
|
||||
#include <library.h>
|
||||
#include <daemon.h>
|
||||
|
||||
|
||||
static struct sockaddr_un socket_addr = { AF_UNIX, "/var/run/charon.xml"};
|
||||
|
||||
|
||||
typedef struct private_xml_interface_t private_xml_interface_t;
|
||||
|
||||
/**
|
||||
@@ -39,14 +53,171 @@ struct private_xml_interface_t {
|
||||
* Public part of xml_t object.
|
||||
*/
|
||||
xml_interface_t public;
|
||||
|
||||
/**
|
||||
* XML unix socket fd
|
||||
*/
|
||||
int socket;
|
||||
|
||||
/**
|
||||
* thread receiving messages
|
||||
*/
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
static void get(private_xml_interface_t *this,
|
||||
xmlTextReaderPtr reader, xmlTextWriterPtr writer)
|
||||
{
|
||||
|
||||
if (/* <GetResponse> */
|
||||
xmlTextWriterStartElement(writer, "GetResponse") < 0 ||
|
||||
/* <Status Code="200"><Message/></Status> */
|
||||
xmlTextWriterStartElement(writer, "Status") < 0 ||
|
||||
xmlTextWriterWriteAttribute(writer, "Code", "200") < 0 ||
|
||||
xmlTextWriterStartElement(writer, "Message") < 0 ||
|
||||
xmlTextWriterEndElement(writer) < 0 ||
|
||||
xmlTextWriterEndElement(writer) < 0 ||
|
||||
/* <ConnectionList/> */
|
||||
xmlTextWriterStartElement(writer, "ConnectionList") < 0 ||
|
||||
xmlTextWriterEndElement(writer) < 0 ||
|
||||
/* </GetResponse> */
|
||||
xmlTextWriterEndElement(writer) < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "error writing XML document (GetResponse)");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
DBG1(DBG_CFG, "%d %d %s %d %d %s",
|
||||
xmlTextReaderDepth(reader),
|
||||
,
|
||||
xmlTextReaderConstName(reader),
|
||||
xmlTextReaderIsEmptyElement(reader),
|
||||
xmlTextReaderHasValue(reader),
|
||||
xmlTextReaderConstValue(reader));
|
||||
*/
|
||||
}
|
||||
|
||||
static void receive(private_xml_interface_t *this)
|
||||
{
|
||||
charon->drop_capabilities(charon, TRUE);
|
||||
|
||||
/* disable cancellation by default */
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
struct sockaddr_un strokeaddr;
|
||||
int strokeaddrlen = sizeof(strokeaddr);
|
||||
int oldstate;
|
||||
int fd;
|
||||
char buffer[4096];
|
||||
size_t len;
|
||||
|
||||
/* wait for connections, but allow thread to terminate */
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
||||
fd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
|
||||
pthread_setcancelstate(oldstate, NULL);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "accepting SMP XML socket failed: %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
DBG2(DBG_CFG, "SMP XML connection opened");
|
||||
while (TRUE)
|
||||
{
|
||||
xmlTextReaderPtr reader;
|
||||
xmlTextWriterPtr writer;
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
||||
len = read(fd, buffer, sizeof(buffer));
|
||||
pthread_setcancelstate(oldstate, NULL);
|
||||
if (len <= 0)
|
||||
{
|
||||
close(fd);
|
||||
DBG2(DBG_CFG, "SMP XML connection closed");
|
||||
break;
|
||||
}
|
||||
|
||||
reader = xmlReaderForMemory(buffer, len, NULL, NULL, 0);
|
||||
if (reader == NULL)
|
||||
{
|
||||
DBG1(DBG_CFG, "opening SMP XML reader failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
writer = xmlNewTextWriter(xmlOutputBufferCreateFd(fd, NULL));
|
||||
if (writer == NULL)
|
||||
{
|
||||
xmlFreeTextReader(reader);
|
||||
DBG1(DBG_CFG, "opening SMP XML writer failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* create the standard message parts */
|
||||
if (xmlTextWriterStartDocument(writer, NULL, NULL, NULL) < 0 ||
|
||||
/* <SMPMessage xmlns="http://www.strongswan.org/smp/1.0"> */
|
||||
xmlTextWriterStartElement(writer, "SMPMessage") < 0 ||
|
||||
xmlTextWriterWriteAttribute(writer, "xmlns",
|
||||
"http://www.strongswan.org/smp/1.0") < 0 ||
|
||||
/* <Body> */
|
||||
xmlTextWriterStartElement(writer, "Body") < 0)
|
||||
{
|
||||
xmlFreeTextReader(reader);
|
||||
xmlFreeTextWriter(writer);
|
||||
DBG1(DBG_CFG, "creating SMP XML message failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
switch (xmlTextReaderRead(reader))
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (xmlTextReaderNodeType(reader) ==
|
||||
XML_READER_TYPE_ELEMENT)
|
||||
{
|
||||
if (streq(xmlTextReaderConstName(reader), "GetRequest"))
|
||||
{
|
||||
get(this, reader, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case 0:
|
||||
/* end of XML */
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_CFG, "parsing SMP XML message failed");
|
||||
break;
|
||||
}
|
||||
xmlFreeTextReader(reader);
|
||||
break;
|
||||
}
|
||||
/* write </Body></SMPMessage> and close document */
|
||||
if (xmlTextWriterEndDocument(writer) < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "completing SMP XML message failed");
|
||||
}
|
||||
xmlFreeTextWriter(writer);
|
||||
/* write a newline to indicate end of xml */
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of itnerface_t.destroy.
|
||||
*/
|
||||
static void destroy(private_xml_interface_t *this)
|
||||
{
|
||||
pthread_cancel(this->thread);
|
||||
pthread_join(this->thread, NULL);
|
||||
close(this->socket);
|
||||
unlink(socket_addr.sun_path);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -56,8 +227,46 @@ static void destroy(private_xml_interface_t *this)
|
||||
interface_t *interface_create()
|
||||
{
|
||||
private_xml_interface_t *this = malloc_thing(private_xml_interface_t);
|
||||
mode_t old;
|
||||
|
||||
this->public.interface.destroy = (void (*)(xml_interface_t*))destroy;
|
||||
this->public.interface.destroy = (void (*)(interface_t*))destroy;
|
||||
|
||||
/* set up unix socket */
|
||||
this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (this->socket == -1)
|
||||
{
|
||||
DBG1(DBG_CFG, "could not create XML socket");
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
old = umask(~S_IRWXU);
|
||||
if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "could not bind XML socket: %s", strerror(errno));
|
||||
close(this->socket);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
umask(old);
|
||||
|
||||
if (listen(this->socket, 0) < 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "could not listen on XML socket: %s", strerror(errno));
|
||||
close(this->socket);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pthread_create(&this->thread, NULL, (void*(*)(void*))receive, this) != 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "could not create XML socket thread: %s", strerror(errno));
|
||||
close(this->socket);
|
||||
unlink(socket_addr.sun_path);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public.interface;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user