/** * Parse the "X-Gnutella-Alternate-Location" header if present to learn * about other sources for this file. * * Also knows about "Alternate-Location", "Alt-Location", "X-Alt" and "X-Falt". * * @param sha1 the SHA1 for which we're parsing alt-locs * @param header the headers supplied by the remote host * @param origin if non-NULL, this is the host supplying the alt-locs */ void huge_collect_locations(const sha1_t *sha1, const header_t *header, const gnet_host_t * origin) { char *alt; size_t len; g_return_if_fail(sha1); g_return_if_fail(header); alt = header_get(header, "X-Gnutella-Alternate-Location"); /* * Unfortunately, clueless people broke the HUGE specs and made up their * own headers. They should learn about header continuations, and * that "X-Gnutella-Alternate-Location" does not need to be repeated. */ if (alt == NULL) alt = header_get(header, "Alternate-Location"); if (alt == NULL) alt = header_get(header, "Alt-Location"); if (alt != NULL) { dmesh_collect_locations(sha1, alt, origin); return; } alt = header_get_extended(header, "X-Alt", &len); if (alt != NULL) { /* * Wonderful Shareaza now uses X-Alt but does not pass compact * locations. In essence, they renamed Alt-Location to X-Alt * without changing the format of the value. Great job. * --RAM, 2010-02-22 */ if (huge_is_pure_xalt(alt, len)) dmesh_collect_compact_locations(sha1, alt, origin); else dmesh_collect_locations(sha1, alt, origin); } /* * Firewalled locations. */ alt = header_get(header, "X-Falt"); if (alt != NULL) { dmesh_collect_fw_hosts(sha1, alt); } }
/* * Print text file with substitutions for %x */ int print_file_subst(FILE *in, FILE *out, Message *msg, char *rfc_to, Textlist *body) { int c; char *hg; while((c = getc(in)) != EOF) { if(c == '%') { c = getc(in); switch(c) { case 'F': /* From node */ fputs( znfp1(&msg->node_from), out); break; case 'T': /* To node */ fputs( znfp1(&msg->node_to), out); break; case 'O': /* Orig node */ fputs( znfp1(&msg->node_orig), out); break; case 'd': /* Date */ fputs( date(NULL, &msg->date), out); break; case 't': /* To name */ fputs( msg->name_to, out); break; case 'f': /* From name */ fputs( msg->name_from, out); break; case 's': /* Subject */ fputs( msg->subject, out); break; case 'R': /* RFC To: */ fputs( rfc_to, out); break; case 'M': /* Message */ tl_print(body, out); break; case 'A': /* RFC From: */ if((hg = s_header_getcomplete("From"))) fputs( hg, out); break; case 'D': /* RFC Date: */ if((hg = header_get("Date"))) fputs( hg, out); break; case 'N': /* RFC Newsgroups: */ if((hg = header_get("Newsgroups"))) fputs( hg, out); break; case 'S': /* RFC Subject: */ if((hg = header_get("Subject"))) fputs( hg, out); break; } } else putc(c, out); } return ferror(in); }
unsigned long get_first_msgwait(struct servants_list_item *servants) { unsigned long msgwait = 0; struct servants_list_item *s = servants; for (s = servants; s; s = s->next) { struct sbd_context *st; struct sector_header_s *s_header; st = open_device(s->devname, LOG_WARNING); if (!st) { continue; } s_header = header_get(st); if (s_header != NULL) { msgwait = (unsigned long)s_header->timeout_msgwait; close_device(st); return msgwait; } close_device(st); } return msgwait; }
static int header_dump(struct sbd_context *st) { struct sector_header_s *s_header; char uuid[37]; s_header = header_get(st); if (s_header == NULL) return -1; printf("Header version : %u.%u\n", s_header->version, s_header->minor_version); if (s_header->minor_version > 0) { uuid_unparse_lower(s_header->uuid, uuid); printf("UUID : %s\n", uuid); } printf("Number of slots : %u\n", s_header->slots); printf("Sector size : %lu\n", (unsigned long)s_header->sector_size); printf("Timeout (watchdog) : %lu\n", (unsigned long)s_header->timeout_watchdog); printf("Timeout (allocate) : %lu\n", (unsigned long)s_header->timeout_allocate); printf("Timeout (loop) : %lu\n", (unsigned long)s_header->timeout_loop); printf("Timeout (msgwait) : %lu\n", (unsigned long)s_header->timeout_msgwait); return 0; }
static int slot_allocate(struct sbd_context *st, const char *name) { struct sector_header_s *s_header = NULL; struct sector_node_s *s_node = NULL; struct sector_mbox_s *s_mbox = NULL; int i; int rc = 0; if (!name) { cl_log(LOG_ERR, "slot_allocate(): No name specified.\n"); fprintf(stderr, "slot_allocate(): No name specified.\n"); rc = -1; goto out; } s_header = header_get(st); if (!s_header) { rc = -1; goto out; } s_node = sector_alloc(); s_mbox = sector_alloc(); while (1) { i = slot_lookup(st, s_header, name); if ((i >= 0) || (i == -2)) { /* -1 is "no slot found", in which case we * proceed to allocate a new one. * -2 is "read error during lookup", in which * case we error out too * >= 0 is "slot already allocated" */ rc = i; goto out; } i = slot_unused(st, s_header); if (i >= 0) { cl_log(LOG_INFO, "slot %d is unused - trying to own", i); fprintf(stdout, "slot %d is unused - trying to own\n", i); memset(s_node, 0, sizeof(*s_node)); s_node->in_use = 1; strncpy(s_node->name, name, sizeof(s_node->name)); if (slot_write(st, i, s_node) < 0) { rc = -1; goto out; } sleep(timeout_allocate); } else { cl_log(LOG_ERR, "No more free slots."); fprintf(stderr, "No more free slots.\n"); rc = -1; goto out; } } out: free(s_node); free(s_header); free(s_mbox); return(rc); }
void open_any_device(struct servants_list_item *servants) { struct sector_header_s *hdr_cur = NULL; struct timespec t_0; int t_wait = 0; clock_gettime(CLOCK_MONOTONIC, &t_0); while (!hdr_cur && t_wait < timeout_startup) { struct timespec t_now; struct servants_list_item* s; for (s = servants; s; s = s->next) { struct sbd_context *st = open_device(s->devname, LOG_DEBUG); if (!st) continue; hdr_cur = header_get(st); close_device(st); if (hdr_cur) break; } clock_gettime(CLOCK_MONOTONIC, &t_now); t_wait = t_now.tv_sec - t_0.tv_sec; if (!hdr_cur) { sleep(timeout_loop); } } if (hdr_cur) { timeout_watchdog = hdr_cur->timeout_watchdog; timeout_allocate = hdr_cur->timeout_allocate; timeout_loop = hdr_cur->timeout_loop; timeout_msgwait = hdr_cur->timeout_msgwait; } else { cl_log(LOG_ERR, "No devices were available at start-up within %i seconds.", timeout_startup); exit(1); } free(hdr_cur); return; }
static int slot_list(struct sbd_context *st) { struct sector_header_s *s_header = NULL; struct sector_node_s *s_node = NULL; struct sector_mbox_s *s_mbox = NULL; int i; int rc = 0; s_header = header_get(st); if (!s_header) { rc = -1; goto out; } s_node = sector_alloc(); s_mbox = sector_alloc(); for (i=0; i < s_header->slots; i++) { if (slot_read(st, i, s_node) < 0) { rc = -1; goto out; } if (s_node->in_use > 0) { if (mbox_read(st, i, s_mbox) < 0) { rc = -1; goto out; } printf("%d\t%s\t%s\t%s\n", i, s_node->name, char2cmd(s_mbox->cmd), s_mbox->from); } } out: free(s_node); free(s_header); free(s_mbox); return rc; }
/** * \brief Slave driver main state machine * For UML graph, please refer to SDK documentation */ static void spi_slave_event_handle(spi_slave_evt_t event) { static uint32_t err_code = NRF_SUCCESS; static uint16_t packetLength; switch (m_trans_state) { case SPI_RAW_STATE_SETUP_HEADER: m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); break; case SPI_RAW_STATE_RX_HEADER: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_RX_XFER_DONE(event.rx_amount); spi_slave_raw_assert(event.rx_amount == SER_PHY_HEADER_SIZE); packetLength = uint16_decode(m_header_rx_buffer); if (packetLength != 0 ) { m_trans_state = SPI_RAW_STATE_MEM_REQUESTED; m_buffer_reqested_flag = true; m_rx_packet_length = packetLength; callback_memory_request(packetLength); } else { if (m_p_tx_buffer) { clear_request_line(); m_trans_state = SPI_RAW_STATE_TX_HEADER; err_code = header_send(m_tx_packet_length); } else { //there is nothing to send - zero response facilitates pooling - but perhaps, it should be assert err_code = header_send(0); } } } break; case SPI_RAW_STATE_MEM_REQUESTED: if (event.evt_type == SPI_SLAVE_EVT_TYPE_MAX) //This is API dummy event { m_buffer_reqested_flag = false; m_trans_state = SPI_RAW_STATE_RX_PAYLOAD; m_accumulated_rx_packet_length = 0; err_code = frame_get(); } break; case SPI_RAW_STATE_RX_PAYLOAD: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_RX_XFER_DONE(event.rx_amount); spi_slave_raw_assert(event.rx_amount == m_current_rx_frame_length); m_accumulated_rx_packet_length += m_current_rx_frame_length; if (m_accumulated_rx_packet_length < m_rx_packet_length ) { err_code = frame_get(); } else { spi_slave_raw_assert(m_accumulated_rx_packet_length == m_rx_packet_length); m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); if (!m_trash_payload_flag) { callback_packet_received(m_p_rx_buffer, m_accumulated_rx_packet_length); } else { callback_packet_dropped(); } } } break; case SPI_RAW_STATE_TX_HEADER: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_TX_XFER_DONE(event.tx_amount); spi_slave_raw_assert(event.tx_amount == SER_PHY_HEADER_SIZE + 1); m_trans_state = SPI_RAW_STATE_TX_PAYLOAD; m_accumulated_tx_packet_length = 0; err_code = frame_send(); } break; case SPI_RAW_STATE_TX_PAYLOAD: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_TX_XFER_DONE(event.tx_amount); spi_slave_raw_assert(event.tx_amount == m_current_tx_frame_length + 1); m_accumulated_tx_packet_length += m_current_tx_frame_length; if ( m_accumulated_tx_packet_length < m_tx_packet_length ) { err_code = frame_send(); } else { spi_slave_raw_assert(m_accumulated_tx_packet_length == m_tx_packet_length); //clear pointer before callback m_p_tx_buffer = NULL; callback_packet_transmitted(); //spi slave TX transfer is possible only when RX is ready, so return to waiting for a header m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); } } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } APP_ERROR_CHECK(err_code); }
/** * Retrieves the major and minor version from a feature in the X-Features * header, if no support was found both major and minor are 0 and FALSE * is returned. */ bool header_get_feature(const char *name, const header_t *header, uint *major, uint *minor) { static const char x_features[] = "X-Features"; char *buf, *start; if (major) *major = 0; if (minor) *minor = 0; buf = header_get(header, x_features); /* * We could also try to scan for the header: name, so this would * make this function even more generic. But I would suggest another * function for this though. */ if (buf == NULL) { /* * Actually the 'specs' say we should assume it is supported if the * X-Features header is not there. But I wouldn't count on it, and * it was only for "legacy" attributes in the HTTP file exchange. * * Also, for optimization purposes, the X-Features line will be sent * once per persistent HTTP connection, as the client is expected to * cache the supported features. */ return FALSE; } /* * We must locate the name exactly, and not a subpart of another * feature. If we look for "bar", then we must not match on "foobar". */ start = buf; for (;;) { int pc; /* Previous char */ buf = ascii_strcasestr(buf, name); if (buf == NULL) return FALSE; if (buf == start) break; /* * Since we're looking for whole words separated by a space or the * regular header punctuation, the next match can't occur before * the end of the current string we matched... */ pc = *(buf - 1); buf += strlen(name); if (*buf != '/') continue; /* Matched "barcode" when looking for "bar" */ if (is_ascii_space(pc) || pc == ',' || pc == ';') break; /* Found it! */ } buf++; if (*buf == '\0') return FALSE; return 0 == parse_major_minor(buf, NULL, major, minor); }
/** * \brief Master driver main state machine * Executed only in the context of PendSV_Handler() * For UML graph, please refer to SDK documentation */ static void ser_phy_switch_state(ser_phy_event_source_t evt_src) { uint32_t err_code = NRF_SUCCESS; static bool m_wait_for_ready_flag = false; //local scheduling flag to defer RDY events switch (m_spi_master_state) { case SER_PHY_STATE_IDLE: if (evt_src == SER_PHY_EVT_GPIO_REQ) { m_wait_for_ready_flag = false; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else if (evt_src == SER_PHY_EVT_TX_API_CALL) { spi_master_raw_assert(mp_tx_buffer != NULL); //api event with tx_buffer == NULL has no sense m_wait_for_ready_flag = false; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_HEADER; err_code = header_send(m_tx_buf_len); } else { m_spi_master_state = SER_PHY_STATE_TX_WAIT_FOR_RDY; } } break; case SER_PHY_STATE_TX_WAIT_FOR_RDY: if (evt_src == SER_PHY_EVT_GPIO_RDY) { m_spi_master_state = SER_PHY_STATE_TX_HEADER; err_code = header_send(m_tx_buf_len); } break; case SER_PHY_STATE_RX_WAIT_FOR_RDY: if (evt_src == SER_PHY_EVT_GPIO_RDY) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } break; case SER_PHY_STATE_TX_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_tx_packet_length = m_tx_buf_len; m_accumulated_tx_packet_length = 0; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_PAYLOAD; err_code = frame_send(); } else { m_wait_for_ready_flag = true; } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_TX_PAYLOAD; err_code = frame_send(); } break; case SER_PHY_STATE_TX_PAYLOAD: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { if (m_accumulated_tx_packet_length < m_tx_packet_length) { if (m_slave_ready_flag) { err_code = frame_send(); } else { m_wait_for_ready_flag = true; } } else { spi_master_raw_assert(m_accumulated_tx_packet_length == m_tx_packet_length); buffer_release(&mp_tx_buffer, &m_tx_buf_len); callback_packet_sent(); if ( m_slave_request_flag) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else { m_spi_master_state = SER_PHY_STATE_IDLE; //m_Tx_buffer is NULL - have to wait for API event } } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag ) { m_wait_for_ready_flag = false; err_code = frame_send(); } break; case SER_PHY_STATE_TX_ZERO_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_RX_HEADER; err_code = header_get(); } else { m_wait_for_ready_flag = true; } } else if ( (evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_RX_HEADER; err_code = header_get(); } break; case SER_PHY_STATE_RX_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_spi_master_state = SER_PHY_STATE_MEMORY_REQUEST; m_rx_buf_len = uint16_decode(m_header_buffer); m_rx_packet_length = m_rx_buf_len; callback_mem_request(); } break; case SER_PHY_STATE_MEMORY_REQUEST: if (evt_src == SER_PHY_EVT_RX_API_CALL) { m_accumulated_rx_packet_length = 0; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_RX_PAYLOAD; err_code = frame_get(); } else { m_wait_for_ready_flag = true; } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_RX_PAYLOAD; err_code = frame_get(); } break; case SER_PHY_STATE_RX_PAYLOAD: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_accumulated_rx_packet_length += m_current_rx_packet_length; if (m_accumulated_rx_packet_length < m_rx_packet_length) { if (m_slave_ready_flag) { err_code = frame_get(); } else { m_wait_for_ready_flag = true; } } else { spi_master_raw_assert(m_accumulated_rx_packet_length == m_rx_packet_length); if (mp_rx_buffer == NULL) { callback_packet_dropped(); } else { callback_packet_received(); } buffer_release(&mp_rx_buffer, &m_rx_buf_len); if (mp_tx_buffer != NULL) //mp_tx_buffer !=NULL, this means that API_EVT was scheduled { if (m_slave_ready_flag ) { err_code = header_send(m_tx_buf_len); m_spi_master_state = SER_PHY_STATE_TX_HEADER; } else { m_spi_master_state = SER_PHY_STATE_TX_WAIT_FOR_RDY; } } else if (m_slave_request_flag) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else { m_spi_master_state = SER_PHY_STATE_IDLE; } } } else if ( evt_src == SER_PHY_EVT_GPIO_RDY && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; err_code = frame_get(); } break; default: break; } if (err_code != NRF_SUCCESS) { (void)err_code; } }
/** * HTTP async callback, invoked when all the headers have been read. * * @return TRUE if we can continue with the request. */ static gboolean soap_header_ind(http_async_t *ha, header_t *header, int code, const char *message) { soap_rpc_t *sr = http_async_get_opaque(ha); const char *buf; soap_rpc_check(sr); g_assert(ha == sr->ha); if (GNET_PROPERTY(soap_debug) > 2) { g_debug("SOAP \"%s\" at \"%s\": got HTTP %d %s", sr->action, sr->url, code, message); } /* * Grab local socket address if they are interested. */ if (sr->options & SOAP_RPC_O_LOCAL_ADDR) sr->got_local_addr = http_async_get_local_addr(ha, &sr->local_addr); /* * If we sent a non-mandatory request and get a 405 "Method not allowed" * error, retry with M-POST. Likewise, a 510 "Not extended" reply is an * invitation to use the HTTP Extension Framework (RFC 2774). */ if ( (405 == code || 510 == code) && !sr->mandatory && !sr->retry && (sr->options & SOAP_RPC_O_MAN_RETRY) ) { if (GNET_PROPERTY(soap_debug) > 1) { g_message("SOAP \"%s\" at \"%s\": will be retrying with M-POST", sr->action, sr->url); } sr->retry = TRUE; /* Signal we should retry */ http_async_cancel(ha); return FALSE; } /* * If we sent a mandatory request, there needs to be an "Ext:" header * in the reply to show that the mandatory request was understood as such. */ if (sr->mandatory && 200 == code) { const char *ext = header_get(header, "Ext"); if (NULL == ext) { if (GNET_PROPERTY(soap_debug)) { g_warning("SOAP \"%s\" at \"%s\": M-POST not understood", sr->action, sr->url); } http_async_error(ha, HTTP_ASYNC_MAN_FAILURE); return FALSE; } } /* * Save the HTTP headers and code to be able to analyze the reply payload. * * Since the option HTTP_O_READ_REPLY is used, we'll get the reply data * from the server even if the status code is not 200 and we need to be * able to differentiate between a success report and an error. */ sr->header = header_refcnt_inc(header); sr->http_code = code; /* * See whether they advertise a Content-Length, which may not be the * case if chunked transfer encoding is used for the reply. In that * case, we shall dynamically adjust the reception buffer size. */ buf = header_get(header, "Content-Length"); if (buf != NULL) { guint32 len; int error; len = parse_uint32(buf, NULL, 10, &error); if (error) { if (GNET_PROPERTY(soap_debug)) { g_warning("SOAP \"%s\" at \"%s\": " "cannot parse Content-Length header: " "value is \"%s\", error is %s", sr->action, sr->url, buf, g_strerror(error)); } http_async_error(ha, HTTP_ASYNC_BAD_HEADER); return FALSE; } if (len > sr->maxlen) { http_async_error(ha, HTTP_ASYNC_DATA2BIG); return FALSE; } sr->content_len = len; } /* * Allocate data buffer: either they advertised content length, or 1/16th * of the maximum data length we accept to grab from the server. */ sr->reply_size = (buf != NULL) ? sr->content_len : (sr->maxlen >> 4); sr->reply_data = halloc(sr->reply_size); return TRUE; /* OK, go on */ }
/** * Process the SOAP reply from the server. */ static void soap_process_reply(soap_rpc_t *sr) { const char *buf; vxml_parser_t *vp; vxml_error_t e; xnode_t *root = NULL; xnode_t *xn = NULL; const char *charset; soap_rpc_check(sr); if (sr->reply_len != 0 && (GNET_PROPERTY(soap_trace) & SOCK_TRACE_IN)) { g_debug("----Got SOAP HTTP reply data from %s:", sr->url); if (log_printable(LOG_STDERR)) { fwrite(sr->reply_data, sr->reply_len, 1, stderr); fputs("----End SOAP HTTP reply\n", stderr); } } if (GNET_PROPERTY(soap_debug) > 2) { g_debug("SOAP \"%s\" at \"%s\": processing reply (%lu byte%s) HTTP %d", sr->action, sr->url, (unsigned long) sr->reply_len, 1 == sr->reply_len ? "" : "s", sr->http_code); } /* * If we got a 2xx reply, we need to parse up to the <Body> element * and then pass up the remaining to the user for parsing specific * elemnts accordingly. * * Other reply codes indicate an error. On 4xx replies we may not * have any XML to parse. On 5xx replies, we should usually have * a <Fault> indication under the <Body>. * * The strategy used here is to parse the XML reply into a tree and then * analyse the tree, ignoring the HTTP status code which is redundant. */ buf = header_get(sr->header, "Content-Type"); if (NULL == buf) goto no_xml; /* * MIME type and subtypes are case-insensitive (see RFC 2616, section 3.7). */ if ( !http_field_starts_with(buf, SOAP_TEXT_REPLY, FALSE) && !http_field_starts_with(buf, SOAP_APPLICATION_REPLY, FALSE) ) { if (GNET_PROPERTY(soap_debug)) { g_debug("SOAP \"%s\" at \"%s\": got unexpected Content-Type: %s", sr->action, sr->url, buf); } goto no_xml; } /* * Extract charset if given. */ charset = http_parameter_get(buf, "charset"); /* * Parse the SOAP envelope. */ vp = vxml_parser_make(sr->action, VXML_O_STRIP_BLANKS); vxml_parser_add_data(vp, sr->reply_data, sr->reply_len); if (!vxml_parser_set_charset(vp, charset)) { g_warning("SOAP \"%s\" at \"%s\": ignoring unknown charset \"%s\"", sr->action, sr->url, charset); } e = vxml_parse_tree(vp, &root); vxml_parser_free(vp); if (e != VXML_E_OK) { if (GNET_PROPERTY(soap_debug)) { g_debug("SOAP \"%s\" at \"%s\": cannot parse XML reply: %s", sr->action, sr->url, vxml_strerror(e)); } goto bad_xml; } g_assert(root != NULL); /* * Make sure we got a SOAP reply. */ if (!xnode_is_element_named(root, SOAP_NAMESPACE, SOAP_X_ENVELOPE)) goto not_soap; /* * Look for the <SOAP:Body> element. */ for (xn = xnode_first_child(root); TRUE; xn = xnode_next_sibling(xn)) { if (NULL == xn || !xnode_within_namespace(xn, SOAP_NAMESPACE)) goto bad_soap; if (0 == strcmp(SOAP_X_BODY, xnode_element_name(xn))) break; } /* * Inspect the first child of the <SOAP:Body> element. * * If it's a <SOAP:Fault>, go process it and return an error. * If it's another SOAP tag, we have an unknown structure. * Otherwise it's the reply, for user code to handle. */ xn = xnode_first_child(xn); if (NULL == xn) goto bad_soap; if (xnode_is_element_named(xn, SOAP_NAMESPACE, SOAP_X_FAULT)) { xnode_detach(xn); soap_fault(sr, xn); } else if (xnode_within_namespace(xn, SOAP_NAMESPACE)) { goto bad_soap; } else { xnode_detach(xn); soap_reply(sr, xn); } xnode_tree_free(root); return; not_soap: if (GNET_PROPERTY(soap_debug)) { g_debug("SOAP \"%s\" at \"%s\": unexpected root XML " "element <%s:%s>", sr->action, sr->url, EMPTY_STRING(xnode_element_ns(root)), xnode_element_name(root)); } xnode_tree_free(root); /* FALL THROUGH */ no_xml: soap_error(sr, SOAP_E_PROTOCOL); return; bad_soap: if (GNET_PROPERTY(soap_debug)) { g_debug("SOAP \"%s\" at \"%s\": unexpected XML structure", sr->action, sr->url); } if (GNET_PROPERTY(soap_debug) > 1) { g_debug("SOAP current node is %s", xnode_to_string(xn)); } if (GNET_PROPERTY(soap_debug) > 2) xfmt_tree_dump(root, stderr); xnode_tree_free(root); /* FALL THROUGH */ bad_xml: soap_error(sr, SOAP_E_PROCESSING); return; }
static int slot_ping(struct sbd_context *st, const char *name) { struct sector_header_s *s_header = NULL; struct sector_mbox_s *s_mbox = NULL; int mbox; int waited = 0; int rc = 0; if (!name) { cl_log(LOG_ERR, "slot_ping(): No recipient specified.\n"); rc = -1; goto out; } s_header = header_get(st); if (!s_header) { rc = -1; goto out; } if (strcmp(name, "LOCAL") == 0) { name = local_uname; } mbox = slot_lookup(st, s_header, name); if (mbox < 0) { cl_log(LOG_ERR, "slot_msg(): No slot found for %s.", name); rc = -1; goto out; } s_mbox = sector_alloc(); s_mbox->cmd = SBD_MSG_TEST; strncpy(s_mbox->from, local_uname, sizeof(s_mbox->from)-1); DBGLOG(LOG_DEBUG, "Pinging node %s", name); if (mbox_write(st, mbox, s_mbox) < -1) { rc = -1; goto out; } rc = -1; while (waited <= timeout_msgwait) { if (mbox_read(st, mbox, s_mbox) < 0) break; if (s_mbox->cmd != SBD_MSG_TEST) { rc = 0; break; } sleep(1); waited++; } if (rc == 0) { cl_log(LOG_DEBUG, "%s successfully pinged.", name); } else { cl_log(LOG_ERR, "%s failed to ping.", name); } out: free(s_mbox); free(s_header); return rc; }
static int slot_msg(struct sbd_context *st, const char *name, const char *cmd) { struct sector_header_s *s_header = NULL; struct sector_mbox_s *s_mbox = NULL; int mbox; int rc = 0; char uuid[37]; if (!name || !cmd) { cl_log(LOG_ERR, "slot_msg(): No recipient / cmd specified.\n"); rc = -1; goto out; } s_header = header_get(st); if (!s_header) { rc = -1; goto out; } if (strcmp(name, "LOCAL") == 0) { name = local_uname; } if (s_header->minor_version > 0) { uuid_unparse_lower(s_header->uuid, uuid); cl_log(LOG_INFO, "Device UUID: %s", uuid); } mbox = slot_lookup(st, s_header, name); if (mbox < 0) { cl_log(LOG_ERR, "slot_msg(): No slot found for %s.", name); rc = -1; goto out; } s_mbox = sector_alloc(); s_mbox->cmd = cmd2char(cmd); if (s_mbox->cmd < 0) { cl_log(LOG_ERR, "slot_msg(): Invalid command %s.", cmd); rc = -1; goto out; } strncpy(s_mbox->from, local_uname, sizeof(s_mbox->from)-1); cl_log(LOG_INFO, "Writing %s to node slot %s", cmd, name); if (mbox_write_verify(st, mbox, s_mbox) < -1) { rc = -1; goto out; } if (strcasecmp(cmd, "exit") != 0) { cl_log(LOG_INFO, "Messaging delay: %d", (int)timeout_msgwait); sleep(timeout_msgwait); } cl_log(LOG_INFO, "%s successfully delivered to %s", cmd, name); out: free(s_mbox); free(s_header); return rc; }
int servant(const char *diskname, int mode, const void* argp) { struct sector_mbox_s *s_mbox = NULL; struct sector_node_s *s_node = NULL; struct sector_header_s *s_header = NULL; int mbox; int rc = 0; time_t t0, t1, latency; union sigval signal_value; sigset_t servant_masks; struct sbd_context *st; pid_t ppid; char uuid[37]; const struct servants_list_item *s = argp; if (!diskname) { cl_log(LOG_ERR, "Empty disk name %s.", diskname); return -1; } cl_log(LOG_INFO, "Servant starting for device %s", diskname); /* Block most of the signals */ sigfillset(&servant_masks); sigdelset(&servant_masks, SIGKILL); sigdelset(&servant_masks, SIGFPE); sigdelset(&servant_masks, SIGILL); sigdelset(&servant_masks, SIGSEGV); sigdelset(&servant_masks, SIGBUS); sigdelset(&servant_masks, SIGALRM); /* FIXME: check error */ sigprocmask(SIG_SETMASK, &servant_masks, NULL); atexit(servant_exit); servant_inform_parent = 1; st = open_device(diskname, LOG_WARNING); if (!st) { return -1; } s_header = header_get(st); if (!s_header) { cl_log(LOG_ERR, "Not a valid header on %s", diskname); return -1; } if (servant_check_timeout_inconsistent(s_header) < 0) { cl_log(LOG_ERR, "Timeouts on %s do not match first device", diskname); return -1; } if (s_header->minor_version > 0) { uuid_unparse_lower(s_header->uuid, uuid); cl_log(LOG_INFO, "Device %s uuid: %s", diskname, uuid); } mbox = slot_allocate(st, local_uname); if (mbox < 0) { cl_log(LOG_ERR, "No slot allocated, and automatic allocation failed for disk %s.", diskname); rc = -1; goto out; } s_node = sector_alloc(); if (slot_read(st, mbox, s_node) < 0) { cl_log(LOG_ERR, "Unable to read node entry on %s", diskname); exit(1); } DBGLOG(LOG_INFO, "Monitoring slot %d on disk %s", mbox, diskname); if (s_header->minor_version == 0) { set_proc_title("sbd: watcher: %s - slot: %d", diskname, mbox); } else { set_proc_title("sbd: watcher: %s - slot: %d - uuid: %s", diskname, mbox, uuid); } s_mbox = sector_alloc(); if (s->first_start) { if (mode > 0) { if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed during start-up in servant."); rc = -1; goto out; } if (s_mbox->cmd != SBD_MSG_EXIT && s_mbox->cmd != SBD_MSG_EMPTY) { /* Not a clean stop. Abort start-up */ cl_log(LOG_WARNING, "Found fencing message - aborting start-up. Manual intervention required!"); ppid = getppid(); sigqueue(ppid, SIG_EXITREQ, signal_value); rc = 0; goto out; } } DBGLOG(LOG_INFO, "First servant start - zeroing inbox"); memset(s_mbox, 0, sizeof(*s_mbox)); if (mbox_write(st, mbox, s_mbox) < 0) { rc = -1; goto out; } } memset(&signal_value, 0, sizeof(signal_value)); while (1) { struct sector_header_s *s_header_retry = NULL; struct sector_node_s *s_node_retry = NULL; t0 = time(NULL); sleep(timeout_loop); ppid = getppid(); if (ppid == 1) { /* Our parent died unexpectedly. Triggering * self-fence. */ do_reset(); } /* These attempts are, by definition, somewhat racy. If * the device is wiped out or corrupted between here and * us reading our mbox, there is nothing we can do about * that. But at least we tried. */ s_header_retry = header_get(st); if (!s_header_retry) { cl_log(LOG_ERR, "No longer found a valid header on %s", diskname); exit(1); } if (memcmp(s_header, s_header_retry, sizeof(*s_header)) != 0) { cl_log(LOG_ERR, "Header on %s changed since start-up!", diskname); exit(1); } free(s_header_retry); s_node_retry = sector_alloc(); if (slot_read(st, mbox, s_node_retry) < 0) { cl_log(LOG_ERR, "slot read failed in servant."); exit(1); } if (memcmp(s_node, s_node_retry, sizeof(*s_node)) != 0) { cl_log(LOG_ERR, "Node entry on %s changed since start-up!", diskname); exit(1); } free(s_node_retry); if (mbox_read(st, mbox, s_mbox) < 0) { cl_log(LOG_ERR, "mbox read failed in servant."); exit(1); } if (s_mbox->cmd > 0) { cl_log(LOG_INFO, "Received command %s from %s on disk %s", char2cmd(s_mbox->cmd), s_mbox->from, diskname); switch (s_mbox->cmd) { case SBD_MSG_TEST: memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); sigqueue(ppid, SIG_TEST, signal_value); break; case SBD_MSG_RESET: do_reset(); break; case SBD_MSG_OFF: do_off(); break; case SBD_MSG_EXIT: sigqueue(ppid, SIG_EXITREQ, signal_value); break; case SBD_MSG_CRASHDUMP: do_crashdump(); break; default: /* FIXME: An "unknown" message might result from a partial write. log it and clear the slot. */ cl_log(LOG_ERR, "Unknown message on disk %s", diskname); memset(s_mbox, 0, sizeof(*s_mbox)); mbox_write(st, mbox, s_mbox); break; } } sigqueue(ppid, SIG_LIVENESS, signal_value); t1 = time(NULL); latency = t1 - t0; if (timeout_watchdog_warn && (latency > timeout_watchdog_warn)) { cl_log(LOG_WARNING, "Latency: %d exceeded threshold %d on disk %s", (int)latency, (int)timeout_watchdog_warn, diskname); } else if (debug) { DBGLOG(LOG_INFO, "Latency: %d on disk %s", (int)latency, diskname); } } out: free(s_mbox); close_device(st); if (rc == 0) { servant_inform_parent = 0; } return rc; }
int voice_put_message(char *message) { vaheader_t header; long int compression; char line_i[MODEM_BUFFER_LEN + 1]; char line_o[MODEM_BUFFER_LEN + MODEM_BUFFER_LEN + 1]; int fd; int i; int byte_i; int byte_o; int written; int havedle; time_t timebeg; time_t timeend; int bytetotal; int secstotal; log(L_INFO, "Playing \"%s\"...\n", message); if ((fd = open(message, O_RDONLY)) == -1) { log(L_ERROR, "Can't open \"%s\".\n", message); return(VOICE_ACTION_ERROR); } if (!header_get(fd, &header)) { log(L_ERROR, "Can't read vbox audio header from message.\n"); voice_close_or_unlink(fd, NULL); return(VOICE_ACTION_ERROR); } compression = ntohl(header.compression); if (!voice_set_compression(compression)) { log(L_ERROR, "Can't set voice audio compression or line mode.\n"); voice_close_or_unlink(fd, NULL); return(VOICE_ACTION_ERROR); } if (modem_get_nocarrier_state()) { voice_close_or_unlink(fd, NULL); return(VOICE_ACTION_REMOTEHANGUP); } if (modem_command("AT+VTX", "CONNECT") == 0) { log(L_ERROR, "Can't start voice play mode.\n"); voice_close_or_unlink(fd, NULL); return(VOICE_ACTION_ERROR); } voicestatus = VOICE_ACTION_OK; sequencestatus = ST_NO_INPUT; havedle = FALSE; bytetotal = 0; timebeg = time(NULL); while (voicestatus == VOICE_ACTION_OK) { if ((byte_i = read(fd, line_i, MODEM_BUFFER_LEN)) <= 0) { if (byte_i == 0) log(L_DEBUG, "End of audio data\n"); else log(L_DEBUG, "End of audio data with error (%s)\n", strerror(errno)); break; } byte_o = 0; for (i = 0; i < byte_i; i++) { line_o[byte_o] = line_i[i]; if (line_o[byte_o++] == DLE) line_o[byte_o++] = DLE; } bytetotal += byte_o; log(L_JUNK, "Play: <DATA %d incoming; %d outgoing>\n", byte_i, byte_o); if (!modem_get_nocarrier_state()) { written = 0; errno = 0; while (written != byte_o) { written += modem_raw_write(&line_o[written], (byte_o - written)); if (errno != 0) break; } if ((written != byte_o) || (errno != 0)) { log(L_ERROR, "Could only write %d of %d bytes (%s).\n", written, byte_o, strerror(errno)); voicestatus = VOICE_ACTION_ERROR; } } else voicestatus = VOICE_ACTION_REMOTEHANGUP; while ((modem_check_input()) && (voicestatus == VOICE_ACTION_OK)) { log(L_JUNK, "Have input...\n"); if (modem_raw_read(line_i, 1) == 1) { if (havedle) { switch (*line_i) { case ETX: case 'b': case 'c': case 'e': case 'd': case 'q': case 's': log_line(L_DEBUG, "Found sequence \"<DLE>"); log_char(L_DEBUG, *line_i); log_text(L_DEBUG, "\" (ignored)...\n"); break; case DC4: log(L_DEBUG, "Found sequence \"<DLE><DC4>\" (remote hangup)...\n"); voicestatus = VOICE_ACTION_REMOTEHANGUP; break; default: voice_handle_touchtone_dle(*line_i); break; } havedle = FALSE; } else { if (*line_i != DLE) { log_line(L_DEBUG, "Got unneeded character \""); log_char(L_DEBUG, *line_i); log_text(L_DEBUG, "\" (need a \"<DLE>\").\n"); } else havedle = TRUE; } if (voicestatus == VOICE_ACTION_OK) { if ((index(touchtones, '#')) && (index(touchtones, '*'))) { log(L_DEBUG, "Touchtone sequence \"%s\" found.\n", touchtones); if (breaklist_search(touchtones)) { log(L_INFO, "Sequence \"%s\" found in breaklist...\n", touchtones); voicestatus = VOICE_ACTION_TOUCHTONES; } else { log(L_DEBUG, "Sequence \"%s\" not in breaklist (ignored)...\n", touchtones); *touchtones = '\0'; } } } } else log(L_ERROR, "Can't read input from modem.\n"); } if (ctrl_ishere(setup.spool, CTRL_NAME_SUSPEND)) { log(L_INFO, "Control file \"%s\" exists - suspending call...\n", CTRL_NAME_SUSPEND); if (!ctrl_remove(setup.spool, CTRL_NAME_SUSPEND)) { log(L_WARN, "Can't remove control file \"%s\"!\n", CTRL_NAME_SUSPEND); } log(L_JUNK, "Sending \"<DLE><ETX>\"...\n"); printstring(line_o, "%c%c", DLE, ETX); modem_raw_write(line_o, strlen(line_o)); if (modem_command("", "VCON")>0) { #ifdef VBOX_SUSPEND_VALUE printstring(line_o, "AT+S%d", VBOX_SUSPEND_VALUE); #else printstring(line_o, "AT+S"); #endif if (modem_command(line_o, "OK") <= 0) { log(L_WARN, "Can't suspend call\n"); } else { log(L_INFO, "Call suspended\n"); voicestatus = VOICE_ACTION_REMOTEHANGUP; } } } } timeend = time(NULL); if (timeend >= timebeg) { secstotal = (timeend - timebeg); bytetotal = get_message_ptime(compression, bytetotal); log(L_JUNK, "Function play %d secs (kernel needs %d secs)...\n", secstotal, bytetotal); if (secstotal < bytetotal) { log(L_JUNK, "Waiting %d secs to complete playing...\n", (bytetotal - secstotal)); xpause((bytetotal - secstotal) * 1000); } } else log(L_WARN, "Oops - can't calculate time to wait!\n"); voice_close_or_unlink(fd, NULL); if ((voicestatus == VOICE_ACTION_REMOTEHANGUP) || (modem_get_nocarrier_state())) { /* * Remote hangup: We have got the sequence <DLE><DC4> in the * modem stream... */ modem_command("", "NO CARRIER"); } else { /* * Local hangup: Send <DLE><ETX> to the modem and wait for the * result VCON... */ log(L_JUNK, "Sending \"<DLE><ETX>\"...\n"); printstring(line_o, "%c%c", DLE, ETX); modem_raw_write(line_o, strlen(line_o)); modem_command("", "VCON"); } if (modem_get_nocarrier_state()) voicestatus = VOICE_ACTION_REMOTEHANGUP; return(voicestatus); }