From fb6432cb3de7fc8dde366805b5cb9f4a82b85660 Mon Sep 17 00:00:00 2001 From: sr Date: Wed, 19 Dec 2012 19:35:32 +0100 Subject: [SERVER] Refactor code [SERVER] Return List of Alt Servers on RPC_IMG_LIST --- src/server/ipc.c | 821 ------------------------------------------------------- 1 file changed, 821 deletions(-) delete mode 100644 src/server/ipc.c (limited to 'src/server/ipc.c') diff --git a/src/server/ipc.c b/src/server/ipc.c deleted file mode 100644 index a345794..0000000 --- a/src/server/ipc.c +++ /dev/null @@ -1,821 +0,0 @@ -/* - * This file is part of the Distributed Network Block Device 3 - * - * Copyright(c) 2011-2012 Johann Latocha - * - * This file may be licensed under the terms of of the - * GNU General Public License Version 2 (the ``GPL''). - * - * Software distributed under the License is distributed - * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See the GPL for the specific language - * governing rights and limitations. - * - * You should have received a copy of the GPL along with this - * program. If not, go to http://www.gnu.org/licenses/gpl.html - * or write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "ipc.h" -#include "../config.h" -#include "server.h" -#include "saveload.h" -#include "memlog.h" -#include "helper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "xmlutil.h" - -#define IPC_PORT (PORT+1) - -static int server_sock = -1; -static volatile int keep_running = 1; -static char *payload = NULL; - -#define char_repeat_br(_c, _times) do { \ - int _makro_i_ = (_times); \ - while (--_makro_i_ >= 0) putchar(_c); \ - putchar('\n'); \ -} while (0) - -static int ipc_receive(int client_sock); -static int get_highest_fd(GSList *sockets); -static int is_password_correct(xmlDocPtr doc); -static int get_terminal_width(); -static int ipc_send_reply(int sock, dnbd3_ipc_t* header, int result_code, xmlDocPtr payload); - -static int get_highest_fd(GSList *sockets) -{ - GSList *iterator; - int max = server_sock; - - for (iterator = sockets; iterator; iterator = iterator->next) - { - const int fd = (int)(size_t)iterator->data; - if (fd > max) - max = fd; - } - //printf("Max fd: %d\n", max); - return max; -} - -void *dnbd3_ipc_mainloop() -{ - - // Check version and initialize - LIBXML_TEST_VERSION - - payload = malloc(MAX_IPC_PAYLOAD); - if (payload == NULL) - { - memlogf("[CRITICAL] Couldn't allocate IPC payload buffer. IPC disabled."); - pthread_exit((void *)0); - return NULL; - } - - struct sockaddr_in server, client; - socklen_t len = sizeof(client); - - // Create socket - if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - { - perror("ERROR: IPC socket"); - exit(EXIT_FAILURE); - } - - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; // IPv4 - server.sin_addr.s_addr = INADDR_ANY; - server.sin_port = htons(IPC_PORT); // set port number - - const int optval = 1; - setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - - // Bind to socket - if (bind(server_sock, (struct sockaddr *)&server, sizeof(server)) < 0) - { - perror("ERROR: IPC bind"); - exit(EXIT_FAILURE); - } - - // Listen on socket - if (listen(server_sock, 5) < 0) - { - perror("ERROR: IPC listen"); - exit(EXIT_FAILURE); - } - - // Run connection-accepting loop - - fd_set all_sockets, readset, exceptset; - - GSList *sockets = NULL, *iterator; - - int client_sock, ret, flags; - int maxfd = server_sock + 1; - int error_count = 0; - - struct timeval client_timeout, select_timeout; - client_timeout.tv_sec = 0; - client_timeout.tv_usec = 500 * 1000; - - FD_ZERO(&all_sockets); - FD_SET(server_sock, &all_sockets); - - // Make listening socket non-blocking - flags = fcntl(server_sock, F_GETFL, 0); - if (flags == -1) - flags = 0; - fcntl(server_sock, F_SETFL, flags | O_NONBLOCK); - - while (keep_running) - { - readset = exceptset = all_sockets; - select_timeout.tv_sec = 4; - select_timeout.tv_usec = 0; - ret = select(maxfd, &readset, NULL, &exceptset, &select_timeout); - while (ret > 0) - { - --ret; - if (FD_ISSET(server_sock, &readset)) - { - // Accept connection - if ((client_sock = accept(server_sock, &client, &len)) < 0) - { - if (errno != EAGAIN) - { - memlogf("[ERROR] Error accepting an IPC connection"); - if (++error_count > 10) - goto end_loop; - } - continue; - } - error_count = 0; - // Apply read/write timeout - setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &client_timeout, sizeof(client_timeout)); - setsockopt(client_sock, SOL_SOCKET, SO_SNDTIMEO, &client_timeout, sizeof(client_timeout)); - // Make new connection blocking - flags = fcntl(client_sock, F_GETFL, 0); - if (flags == -1) - flags = 0; - fcntl(client_sock, F_SETFL, flags & ~(int)O_NONBLOCK); - sockets = g_slist_prepend(sockets, (void *)(size_t)client_sock); - if (client_sock >= maxfd) - maxfd = client_sock + 1; - //printf("Max fd: %d\n", (maxfd-1)); - FD_SET(client_sock, &all_sockets); - } - else if (FD_ISSET(server_sock, &exceptset)) - { - memlogf("[ERROR] An exception occurred on the IPC listening socket."); - if (++error_count > 10) - goto end_loop; - } - else - { - // Must be an active IPC connection - int del = -1; - for (iterator = sockets; iterator; iterator = iterator->next) - { - if (del != -1) - { - // Delete a previously closed connection from list (delayed, otherwise list might get messed up) - sockets = g_slist_remove(sockets, (void *)(size_t)del); - del = -1; - maxfd = get_highest_fd(sockets) + 1; - } - client_sock = (int)(size_t)iterator->data; - if (FD_ISSET(client_sock, &readset)) - { - // Client sending data - if (!ipc_receive(client_sock)) - { - // Connection has been closed - close(client_sock); - del = client_sock; - FD_CLR(client_sock, &all_sockets); - } - } - else if (FD_ISSET(client_sock, &exceptset)) - { - // Something unexpected happened, just close connection - close(client_sock); - del = client_sock; - FD_CLR(client_sock, &all_sockets); - } - } - if (del != -1) - { - // In case last socket was closed during iteration - sockets = g_slist_remove(sockets, (void *)(size_t)del); - maxfd = get_highest_fd(sockets) + 1; - } - } - } // End select loop - } // End mainloop - -end_loop: - memlogf("[INFO] Shutting down IPC interface."); - if (server_sock != -1) - { - close(server_sock); - server_sock = -1; - } - - free(payload); - xmlCleanupParser(); - pthread_exit((void *)0); - return NULL; -} - -void dnbd3_ipc_shutdown() -{ - keep_running = 0; - if (server_sock == -1) - return; - close(server_sock); - server_sock = -1; -} - -/** - * Returns !=0 if send/recv successful, 0 on any kind of network failure - */ -static int ipc_receive(int client_sock) -{ - GSList *iterator, *iterator2; - -#define STRBUFLEN 100 - char strbuffer[STRBUFLEN]; - - dnbd3_ipc_t header; - - uint32_t cmd; - - int ret, locked = 0; - int return_value = 0; - xmlDocPtr docReply = NULL, docRequest = NULL; - xmlNodePtr root_node, parent_node, tmp_node, log_parent_node, log_node, server_node; - - ret = recv(client_sock, &header, sizeof(header), MSG_WAITALL); - if (ret != sizeof(header)) - return ((ret < 0 && errno == EAGAIN) ? 1 : 0); - cmd = ntohl(header.cmd); // Leave header.cmd in network byte order for reply - header.size = ntohl(header.size); - - int rpc_error = ERROR_UNSPECIFIED_ERROR; // Default value of error, so remember to set it for the reply if call succeeded - - if (header.size != 0) - { - // Message has payload, receive it - if (header.size > MAX_IPC_PAYLOAD) - { - memlogf("[WARNING] IPC command with payload of %u bytes ignored.", (unsigned int)header.size); - return 0; - } - if (!recv_data(client_sock, payload, header.size)) - return 0; - - docRequest = xmlReadMemory(payload, header.size, "noname.xml", NULL, 0); - } - - switch (cmd) - { - case IPC_EXIT: - memlogf("[INFO] Server shutdown by IPC request"); - header.size = ntohl(0); - return_value = send_data(client_sock, &header, sizeof(header)); - dnbd3_cleanup(); - break; - - case IPC_IMG_LIST: - if (!createXmlDoc(&docReply, &root_node, "data")) - goto case_end; - - xmlNewTextChild(root_node, NULL, BAD_CAST "defaultns", BAD_CAST _local_namespace); - - // Images - parent_node = xmlNewNode(NULL, BAD_CAST "images"); - if (parent_node == NULL) - goto case_end; - xmlAddChild(root_node, parent_node); - locked = 1; - pthread_spin_lock(&_spinlock); - for (iterator = _dnbd3_images; iterator; iterator = iterator->next) - { - const dnbd3_image_t *image = iterator->data; - tmp_node = xmlNewNode(NULL, BAD_CAST "image"); - if (tmp_node == NULL) - goto case_end; - xmlNewProp(tmp_node, BAD_CAST "name", BAD_CAST image->config_group); - sprintf(strbuffer, "%u", (unsigned int)image->atime); - xmlNewProp(tmp_node, BAD_CAST "atime", BAD_CAST strbuffer); - sprintf(strbuffer, "%d", image->rid); - xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST strbuffer); - sprintf(strbuffer, "%llu", (unsigned long long)image->filesize); - xmlNewProp(tmp_node, BAD_CAST "size", BAD_CAST strbuffer); - if (image->file) - xmlNewProp(tmp_node, BAD_CAST "file", BAD_CAST image->file); - xmlNewProp(tmp_node, BAD_CAST "servers", BAD_CAST "???"); // TODO - if (image->cache_file && image->cache_map) - { - xmlNewProp(tmp_node, BAD_CAST "cachefile", BAD_CAST image->cache_file); - int i, complete = 0, size = IMGSIZE_TO_MAPBYTES(image->filesize); - for (i = 0; i < size; ++i) - if (image->cache_map[i]) - complete += 100; - sprintf(strbuffer, "%d", complete / size); - xmlNewProp(tmp_node, BAD_CAST "cachefill", BAD_CAST strbuffer); - } - xmlAddChild(parent_node, tmp_node); - } - pthread_spin_unlock(&_spinlock); - locked = 0; - - // Dump and send - rpc_error = 0; - break; - - case IPC_CLIENT_LIST: - if (!createXmlDoc(&docReply, &root_node, "data")) - goto case_end; - - // Clients - parent_node = xmlNewNode(NULL, BAD_CAST "clients"); - if (parent_node == NULL) - goto case_end; - xmlAddChild(root_node, parent_node); - locked = 1; - pthread_spin_lock(&_spinlock); - for (iterator = _dnbd3_clients; iterator; iterator = iterator->next) - { - dnbd3_client_t *client = iterator->data; - if (client->image) - { - tmp_node = xmlNewNode(NULL, BAD_CAST "client"); - if (tmp_node == NULL) - goto case_end; - *strbuffer = '\0'; - host_to_string(&client->host, strbuffer, STRBUFLEN); - xmlNewProp(tmp_node, BAD_CAST "address", BAD_CAST strbuffer); - xmlNewProp(tmp_node, BAD_CAST "image", BAD_CAST client->image->config_group); - sprintf(strbuffer, "%d", client->image->rid); - xmlNewProp(tmp_node, BAD_CAST "rid", BAD_CAST strbuffer); - xmlAddChild(parent_node, tmp_node); - } - } - pthread_spin_unlock(&_spinlock); - locked = 0; - - // Dump and send - rpc_error = 0; - break; - - case IPC_TRUSTED_LIST: - if (!createXmlDoc(&docReply, &root_node, "data")) - goto case_end; - - // Trusted servers - parent_node = xmlNewNode(NULL, BAD_CAST "trusted"); - if (parent_node == NULL) - goto case_end; - xmlAddChild(root_node, parent_node); - locked = 1; - pthread_spin_lock(&_spinlock); - for (iterator = _trusted_servers; iterator; iterator = iterator->next) - { - dnbd3_trusted_server_t *server = iterator->data; - if (server->host.type != 0) - { - tmp_node = xmlNewNode(NULL, BAD_CAST "server"); - if (tmp_node == NULL) - goto case_end; - xmlNodePtr namespace_root = xmlNewNode(NULL, BAD_CAST "namespaces"); - if (namespace_root == NULL) - goto case_end; - host_to_string(&server->host, strbuffer, STRBUFLEN); - xmlNewProp(tmp_node, BAD_CAST "address", BAD_CAST strbuffer); - if (server->comment) - xmlNewProp(tmp_node, BAD_CAST "comment", BAD_CAST server->comment); - for (iterator2 = server->namespaces; iterator2; iterator2 = iterator2->next) - { - const dnbd3_namespace_t *ns = iterator2->data; - server_node = xmlNewNode(NULL, BAD_CAST "namespace"); - if (server_node == NULL) - goto case_end; - xmlAddChild(namespace_root, server_node); - xmlNewProp(server_node, BAD_CAST "name", BAD_CAST ns->name); - if (ns->auto_replicate) - xmlNewProp(server_node, BAD_CAST "replicate", BAD_CAST "1"); - if (ns->recursive) - xmlNewProp(server_node, BAD_CAST "recursive", BAD_CAST "1"); - } - xmlAddChild(parent_node, tmp_node); - xmlAddChild(tmp_node, namespace_root); - } - } - pthread_spin_unlock(&_spinlock); - locked = 0; - - // Dump and send - rpc_error = 0; - break; - - case IPC_GET_LOG: - if (!createXmlDoc(&docReply, &root_node, "data")) - goto case_end; - - // Log - log_parent_node = xmlNewChild(root_node, NULL, BAD_CAST "log", NULL); - if (log_parent_node == NULL) - goto case_end; - char *log = fetchlog(0); - if (log == NULL) - log = strdup("LOG IS NULL"); - log_node = xmlNewCDataBlock(docReply, BAD_CAST log, strlen(log)); - free(log); - if (log_node == NULL) - goto case_end; - xmlAddChild(log_parent_node, log_node); - - // Dump and send - rpc_error = 0; - break; - - case IPC_ADD_IMG: - case IPC_DEL_IMG: - if (docRequest) - { - if (!is_password_correct(docRequest)) - { - rpc_error = ERROR_WRONG_PASSWORD; - break; - } - - xmlNodePtr cur = NULL; - int count = 0; - - FOR_EACH_NODE(docRequest, "/data/images/image", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - NEW_POINTERLIST; - ++count; - dnbd3_image_t image; - memset(&image, 0, sizeof(dnbd3_image_t)); - image.config_group = (char *)XML_GETPROP(cur, "name"); - char *rid_str = (char *)XML_GETPROP(cur, "rid"); - image.file = (char *)XML_GETPROP(cur, "file"); - image.cache_file = (char *)XML_GETPROP(cur, "cache"); - if (image.file && !file_exists(image.file)) - { - rpc_error = ERROR_FILE_NOT_FOUND; - } - else if (image.cache_file && !file_writable(image.cache_file)) - { - rpc_error = ERROR_NOT_WRITABLE; - } - else - { - if (image.config_group && rid_str) - { - image.rid = atoi(rid_str); - if (cmd == IPC_ADD_IMG) - rpc_error = dnbd3_add_image(&image); - else - rpc_error = dnbd3_del_image(&image); - } - else - rpc_error = ERROR_MISSING_ARGUMENT; - } - FREE_POINTERLIST; - } END_FOR_EACH; - if (count == 0) - rpc_error = ERROR_MISSING_ARGUMENT; - } - else - rpc_error = ERROR_INVALID_XML; - - break; - - case IPC_ADD_NS: - case IPC_DEL_NS: - if (docRequest) - { - if (!is_password_correct(docRequest)) - { - rpc_error = ERROR_WRONG_PASSWORD; - break; - } - - xmlNodePtr cur = NULL; - - FOR_EACH_NODE(docRequest, "/data/namespaces/namespace", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - NEW_POINTERLIST; - char *host = (char *)XML_GETPROP(cur, "address"); - char *ns = (char *)XML_GETPROP(cur, "name"); - char *flags = (char *)XML_GETPROP(cur, "flags"); - char *comment = (char *)XML_GETPROP(cur, "comment"); - pthread_spin_lock(&_spinlock); - if (host && ns) - { - if (cmd == IPC_ADD_NS) - { - dnbd3_trusted_server_t *server = dnbd3_get_trusted_server(host, TRUE, comment); - if (server) - dnbd3_add_trusted_namespace(server, ns, flags); - } - else - { - dnbd3_trusted_server_t *server = dnbd3_get_trusted_server(host, FALSE, comment); - if (server) - dnbd3_del_trusted_namespace(server, ns); - } - } - pthread_spin_unlock(&_spinlock); - FREE_POINTERLIST; - } END_FOR_EACH; - - } - else - rpc_error = ERROR_INVALID_XML; - - break; - - default: - memlogf("[ERROR] Unknown IPC command: %u", (unsigned int)header.cmd); - rpc_error = htonl(ERROR_UNKNOWN_COMMAND); - break; - - } -case_end: - - if (locked) - pthread_spin_unlock(&_spinlock); - // Send reply - return_value = ipc_send_reply(client_sock, &header, rpc_error, docReply); - - xmlFreeDoc(docReply); - xmlFreeDoc(docRequest); - - return return_value; -} - -void dnbd3_ipc_send(int cmd) -{ - int client_sock, size; - - // Check version and initialize - LIBXML_TEST_VERSION - - struct sockaddr_in server; - struct timeval client_timeout; - - // Create socket - if ((client_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - { - perror("ERROR: IPC socket"); - exit(EXIT_FAILURE); - } - - client_timeout.tv_sec = 4; - client_timeout.tv_usec = 0; - setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &client_timeout, sizeof(client_timeout)); - setsockopt(client_sock, SOL_SOCKET, SO_SNDTIMEO, &client_timeout, sizeof(client_timeout)); - - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; // IPv4 - server.sin_addr.s_addr = inet_addr("127.0.0.1"); - server.sin_port = htons(IPC_PORT); // set port number - - // Connect to server - if (connect(client_sock, (struct sockaddr *)&server, sizeof(server)) < 0) - { - perror("ERROR: IPC connect"); - exit(EXIT_FAILURE); - } - - // Send message - dnbd3_ipc_t header; - header.cmd = htonl(cmd); - header.size = 0; - send(client_sock, (char *)&header, sizeof(header), MSG_WAITALL); - recv(client_sock, &header, sizeof(header), MSG_WAITALL); - header.cmd = ntohl(header.cmd); - header.size = ntohl(header.size); - - if (cmd == IPC_IMG_LIST && header.size > 0) - { - char *buf = malloc(header.size + 1); - size = recv(client_sock, buf, header.size, MSG_WAITALL); - printf("\n%s\n\n", buf); - xmlDocPtr doc = xmlReadMemory(buf, size, "noname.xml", NULL, 0); - buf[header.size] = 0; - - if (doc) - { - int count; - int term_width = get_terminal_width(); - xmlNodePtr cur, childit; - - // Print log - char *log = getTextFromPath(doc, "/data/log"); - if (log) - { - printf("--- Last log lines ----\n%s\n\n", log); - xmlFree(log); - } - - int watime = 17, wname = 0, wrid = 5; - FOR_EACH_NODE(doc, "/data/images/image", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - NEW_POINTERLIST; // This macro defines an array of pointers - char *vid = XML_GETPROP(cur, "name"); // XML_GETPROP is a macro wrapping xmlGetNoNsProp() - char *rid = XML_GETPROP(cur, "rid"); // Each of these calls allocates memory for the string - wname = MAX(wname, strlen(vid)); - wrid = MAX(wrid, strlen(rid)); - FREE_POINTERLIST; // This macro simply frees all pointers in the above array - } END_FOR_EACH; - - char format[100], strbuffer[STRBUFLEN]; - snprintf(format, 100, - "%%-%ds %%-%ds %%%ds %%s\n", watime, wname, wrid); - - // Print images - printf("Exported images\n"); - printf(format, "atime", "name", "rid", "file"); - char_repeat_br('=', term_width); - count = 0; - FOR_EACH_NODE(doc, "/data/images/image", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - NEW_POINTERLIST; - ++count; - char *numatime = XML_GETPROP(cur, "atime"); - char *vid = XML_GETPROP(cur, "name"); - char *rid = XML_GETPROP(cur, "rid"); - char *file = XML_GETPROP(cur, "file"); - time_t at = (time_t)atol(numatime); - struct tm *timeinfo = localtime(&at); - strftime(strbuffer, STRBUFLEN, "%d.%m.%y %H:%M:%S", timeinfo); - printf(format, strbuffer, vid, rid, file); - FREE_POINTERLIST; - } END_FOR_EACH; - char_repeat_br('=', term_width); - printf("\nNumber of images: %d\n\n", count); - - // Print clients - printf("Connected clients (ip, file):\n"); - char_repeat_br('=', term_width); - count = 0; - FOR_EACH_NODE(doc, "/data/clients/client", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - ++count; - xmlChar *ip = xmlGetNoNsProp(cur, BAD_CAST "ip"); - xmlChar *file = xmlGetNoNsProp(cur, BAD_CAST "file"); - printf("%-40s %s\n", ip, file); - // Too lazy to free vars, client will exit anyways - } END_FOR_EACH; - char_repeat_br('=', term_width); - printf("\nNumber clients: %d\n\n", count); - - // Print trusted servers - printf("Trusted servers:\n"); - char_repeat_br('=', term_width); - count = 0; - FOR_EACH_NODE(doc, "/data/trusted/server", cur) - { - if (cur->type != XML_ELEMENT_NODE) - continue; - NEW_POINTERLIST; - ++count; - char *address = XML_GETPROP(cur, "address"); - char *comment = XML_GETPROP(cur, "comment"); - if (comment) - printf("%-30s (%s)\n", address, comment); - else - printf("%-30s\n", address); - for (childit = cur->children; childit; childit = childit->next) - { - if (childit->type != XML_ELEMENT_NODE || childit->name == NULL || strcmp((const char*)childit->name, "namespace") != 0) - continue; - NEW_POINTERLIST; - char *name = XML_GETPROP(childit, "name"); - char *replicate = XML_GETPROP(childit, "replicate"); - char *recursive = XML_GETPROP(childit, "recursive"); - printf(" %-40s ", name); - if (replicate && *replicate != '0') - printf(" replicate"); - if (recursive && *recursive != '0') - printf(" recursive"); - putchar('\n'); - FREE_POINTERLIST; - } - FREE_POINTERLIST; - } END_FOR_EACH; - char_repeat_br('=', term_width); - printf("\nNumber servers: %d\n\n", count); - - // Cleanup - xmlFreeDoc(doc); - xmlCleanupParser(); - -// xmlDocDump(stdout, doc); - - } - else - { - printf("ERROR: Failed to parse reply\n-----------\n%s\n-------------\n", buf); - } - - } - - close(client_sock); -} - -/** - * Check if the correct server password is present in xpath /data/password - * return !=0 if correct, 0 otherwise - */ -static int is_password_correct(xmlDocPtr doc) -{ - if (_ipc_password == NULL) - { - memlogf("[WARNING] IPC access granted as no password is set!"); - return 1; - } - char *pass = getTextFromPath(doc, "/data/password"); - if (pass == NULL) - return 0; - if (strcmp(pass, _ipc_password) == 0) - { - xmlFree(pass); - return 1; - } - xmlFree(pass); - return 0; -} - -static int get_terminal_width() -{ - struct winsize w; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0) - return 80; - return w.ws_col; -} - -#define RETBUFLEN 8000 -static char returnbuffer[RETBUFLEN]; -static int ipc_send_reply(int sock, dnbd3_ipc_t* header, int result_code, xmlDocPtr payload) -{ - if (result_code == 0 && payload != NULL) - { - // No error - xmlChar *xmlbuff = NULL; - int buffersize; - xmlDocDumpFormatMemory(payload, &xmlbuff, &buffersize, 1); - header->size = htonl(buffersize); - if (!send_data(sock, header, sizeof(*header))) - return FALSE; - if (xmlbuff) - return send_data(sock, xmlbuff, buffersize); - return TRUE; - } - // Error code, build xml struct (lazy shortcut) - int len = snprintf(returnbuffer, RETBUFLEN, "\n" - "\n" - "\n" - "", result_code, "TODO"); - if (len >= RETBUFLEN) - len = 10; - header->size = htonl(len); - header->cmd = htonl(IPC_ERROR); - if (!send_data(sock, header, sizeof(*header))) - return FALSE; - return send_data(sock, returnbuffer, len); -} -- cgit v1.2.3-55-g7522