root/src/noit_capabilities_listener.c

Revision d074a94dcf46254414d8693352e7b8d537f6d082, 2.7 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

expose version string - untested and unused for now, refs #115

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7 #include "eventer/eventer.h"
8 #include "noit_listener.h"
9 #include "utils/noit_hash.h"
10 #include "utils/noit_log.h"
11 #include "utils/noit_sem.h"
12 #include "noit_capabilities_listener.h"
13 #include "noit_module.h"
14 #include "noit_check.h"
15
16 #include <unistd.h>
17 #include <sys/ioctl.h>
18 #include <errno.h>
19
20 #include <libxml/tree.h>
21
22 typedef struct noit_capsvc_closure {
23   char *buff;
24   size_t written;
25   size_t towrite;
26 } noit_capsvc_closure_t;
27
28 void
29 noit_capabilities_listener_init() {
30   eventer_name_callback("capabilities_transit", noit_capabilities_handler);
31   noit_control_dispatch_delegate(noit_control_dispatch,
32                                  NOIT_CAPABILITIES_SERVICE,
33                                  noit_capabilities_handler);
34 }
35
36 int
37 noit_capabilities_handler(eventer_t e, int mask, void *closure,
38                           struct timeval *now) {
39   int newmask = EVENTER_WRITE | EVENTER_EXCEPTION;
40   acceptor_closure_t *ac = closure;
41   noit_capsvc_closure_t *cl = ac->service_ctx;
42
43   if(mask & EVENTER_EXCEPTION) {
44 socket_error:
45     /* Exceptions cause us to simply snip the connection */
46 cleanup_shutdown:
47     eventer_remove_fd(e->fd);
48     e->opset->close(e->fd, &newmask, e);
49     if(cl) {
50       if(cl->buff) free(cl->buff);
51       free(cl);
52     }
53     if(ac) acceptor_closure_free(ac);
54     return 0;
55   }
56
57   if(!ac->service_ctx) {
58     char vbuff[128];
59     xmlDocPtr xmldoc;
60     xmlNodePtr head;
61     xmlOutputBufferPtr out;
62     xmlBufferPtr xmlbuffer;
63
64     cl = ac->service_ctx = calloc(1, sizeof(*cl));
65     /* fill out capabilities */
66     noit_build_version(vbuff, sizeof(vbuff));
67
68     /* Create an XML Document */
69     xmldoc = xmlNewDoc((xmlChar *)"1.0");
70     head = xmlNewDocNode(xmldoc, NULL, (xmlChar *)"noitd_capabilities", NULL);
71
72     /* Fill in the document */
73     xmlNewTextChild(head, NULL, (xmlChar *)"version", (xmlChar *)vbuff);
74
75     /* Write it out to a buffer and copy it for writing */
76     xmlbuffer = xmlBufferCreate();
77     out = xmlOutputBufferCreateBuffer(xmlbuffer, NULL);
78     xmlOutputBufferFlush(out);
79     xmlOutputBufferClose(out);
80     cl->buff = strdup((const char *)xmlBufferContent(xmlbuffer));
81     cl->towrite = xmlBufferLength(xmlbuffer);
82
83     /* Clean up after ourselves */
84     xmlBufferFree(xmlbuffer);
85     xmlFreeDoc(xmldoc);
86   }
87
88   while(cl->towrite > cl->written) {
89     int len;
90     while((len = e->opset->write(e->fd, cl->buff + cl->written,
91                                  cl->towrite - cl->written,
92                                  &newmask, e)) == -1 && errno == EINTR);
93     if(len < 0) {
94       if(errno == EAGAIN) return newmask | EVENTER_EXCEPTION;
95       goto socket_error;
96     }
97     cl->written += len;
98   }
99   goto cleanup_shutdown;
100
101   return 0;
102 }
Note: See TracBrowser for help on using the browser.