void t_subscription_dialog::recvd_request(t_request *r, t_tuid tuid, t_tid tid) { t_response *resp; t_abstract_dialog::recvd_request(r, tuid, tid); // Check cseq // RFC 3261 12.2.2 if (remote_seqnr_set && r->hdr_cseq.seqnr <= remote_seqnr) { // Request received out of order. log_file->write_header("t_subscription_dialog::recvd_request", LOG_NORMAL, LOG_WARNING); log_file->write_raw("CSeq seqnr is out of sequence.\n"); log_file->write_raw("Reveived seqnr: "); log_file->write_raw(r->hdr_cseq.seqnr); log_file->write_endl(); log_file->write_raw("Remote seqnr: "); log_file->write_raw(remote_seqnr); log_file->write_endl(); log_file->write_footer(); resp = r->create_response(R_500_INTERNAL_SERVER_ERROR, "Request received out of order"); phone->send_response(resp, tuid, tid); MEMMAN_DELETE(resp); delete resp; return; } remote_seqnr = r->hdr_cseq.seqnr; remote_seqnr_set = true; switch (r->method) { case SUBSCRIBE: process_subscribe(r, tuid, tid); break; case NOTIFY: process_notify(r, tuid, tid); break; default: // Other requests are not supported in a subscription dialog. resp = r->create_response(R_500_INTERNAL_SERVER_ERROR); phone->send_response(resp, tuid, tid); MEMMAN_DELETE(resp); delete resp; break; } }
/** * We are ready to transmit (or got a timeout). * * @param cls our connection handle * @param tc task context describing why we are here */ static void transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_CONNECTION_Handle *connection = cls; GNUNET_CONNECTION_TransmitReadyNotify notify; ssize_t ret; size_t have; LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection); GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != connection->write_task); connection->write_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { if (NULL != connection->sock) goto SCHEDULE_WRITE; /* ignore shutdown, go again immediately */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmit to `%s' fails, shutdown happened (%p).\n", GNUNET_a2s (connection->addr, connection->addrlen), connection); notify = connection->nth.notify_ready; if (NULL != notify) { connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); } return; } if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmit to `%s' fails, time out reached (%p).\n", GNUNET_a2s (connection->addr, connection->addrlen), connection); notify = connection->nth.notify_ready; GNUNET_assert (NULL != notify); connection->nth.notify_ready = NULL; notify (connection->nth.notify_ready_cls, 0, NULL); return; } GNUNET_assert (NULL != connection->sock); if (NULL == tc->write_ready) { /* special circumstances (in particular, PREREQ_DONE after * connect): not yet ready to write, but no "fatal" error either. * Hence retry. */ goto SCHEDULE_WRITE; } if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock)) { GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task); /* special circumstances (in particular, shutdown): not yet ready * to write, but no "fatal" error either. Hence retry. */ goto SCHEDULE_WRITE; } GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos); if ((NULL != connection->nth.notify_ready) && (connection->write_buffer_size < connection->nth.notify_size)) { connection->write_buffer = GNUNET_realloc (connection->write_buffer, connection->nth.notify_size); connection->write_buffer_size = connection->nth.notify_size; } process_notify (connection); have = connection->write_buffer_off - connection->write_buffer_pos; if (0 == have) { /* no data ready for writing, terminate write loop */ return; } GNUNET_assert (have <= connection->write_buffer_size); GNUNET_assert (have + connection->write_buffer_pos <= connection->write_buffer_size); GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size); RETRY: ret = GNUNET_NETWORK_socket_send (connection->sock, &connection->write_buffer[connection->write_buffer_pos], have); if (-1 == ret) { if (EINTR == errno) goto RETRY; if (GNUNET_SCHEDULER_NO_TASK != connection->write_task) { GNUNET_SCHEDULER_cancel (connection->write_task); connection->write_task = GNUNET_SCHEDULER_NO_TASK; } signal_transmit_error (connection, errno); return; } LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection transmitted %u/%u bytes to `%s' (%p)\n", (unsigned int) ret, have, GNUNET_a2s (connection->addr, connection->addrlen), connection); connection->write_buffer_pos += ret; if (connection->write_buffer_pos == connection->write_buffer_off) { /* transmitted all pending data */ connection->write_buffer_pos = 0; connection->write_buffer_off = 0; } if ((0 == connection->write_buffer_off) && (NULL == connection->nth.notify_ready)) return; /* all data sent! */ /* not done writing, schedule more */ SCHEDULE_WRITE: LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-scheduling transmit_ready (more to do) (%p).\n", connection); have = connection->write_buffer_off - connection->write_buffer_pos; GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0)); if (GNUNET_SCHEDULER_NO_TASK == connection->write_task) connection->write_task = GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready == NULL) ? GNUNET_TIME_UNIT_FOREVER_REL : GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout), connection->sock, &transmit_ready, connection); }
static bool can_read_data(struct io *io, void *user_data) { struct mgmt *mgmt = user_data; struct mgmt_hdr *hdr; struct mgmt_ev_cmd_complete *cc; struct mgmt_ev_cmd_status *cs; ssize_t bytes_read; uint16_t opcode, event, index, length; bytes_read = read(mgmt->fd, mgmt->buf, mgmt->len); if (bytes_read < 0) return false; util_hexdump('>', mgmt->buf, bytes_read, mgmt->debug_callback, mgmt->debug_data); if (bytes_read < MGMT_HDR_SIZE) return true; hdr = mgmt->buf; event = btohs(hdr->opcode); index = btohs(hdr->index); length = btohs(hdr->len); if (bytes_read < length + MGMT_HDR_SIZE) return true; switch (event) { case MGMT_EV_CMD_COMPLETE: cc = mgmt->buf + MGMT_HDR_SIZE; opcode = btohs(cc->opcode); util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%04x complete: 0x%02x", index, opcode, cc->status); request_complete(mgmt, cc->status, opcode, index, length - 3, mgmt->buf + MGMT_HDR_SIZE + 3); break; case MGMT_EV_CMD_STATUS: cs = mgmt->buf + MGMT_HDR_SIZE; opcode = btohs(cs->opcode); util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%02x status: 0x%02x", index, opcode, cs->status); request_complete(mgmt, cs->status, opcode, index, 0, NULL); break; default: util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] event 0x%04x", index, event); process_notify(mgmt, event, index, length, mgmt->buf + MGMT_HDR_SIZE); break; } if (mgmt->destroyed) return false; return true; }
static gboolean received_data(GIOChannel *channel, GIOCondition cond, gpointer user_data) { struct mgmt *mgmt = user_data; struct mgmt_hdr *hdr; struct mgmt_ev_cmd_complete *cc; struct mgmt_ev_cmd_status *cs; ssize_t bytes_read; uint16_t opcode, event, index, length; if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) return FALSE; bytes_read = read(mgmt->fd, mgmt->buf, mgmt->len); if (bytes_read < 0) return TRUE; util_hexdump('>', mgmt->buf, bytes_read, mgmt->debug_callback, mgmt->debug_data); if (bytes_read < MGMT_HDR_SIZE) return TRUE; hdr = mgmt->buf; event = btohs(hdr->opcode); index = btohs(hdr->index); length = btohs(hdr->len); if (bytes_read < length + MGMT_HDR_SIZE) return TRUE; switch (event) { case MGMT_EV_CMD_COMPLETE: cc = mgmt->buf + MGMT_HDR_SIZE; opcode = btohs(cc->opcode); util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%04x complete: 0x%02x", index, opcode, cc->status); request_complete(mgmt, cc->status, opcode, index, length - 3, mgmt->buf + MGMT_HDR_SIZE + 3); break; case MGMT_EV_CMD_STATUS: cs = mgmt->buf + MGMT_HDR_SIZE; opcode = btohs(cs->opcode); util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%02x status: 0x%02x", index, opcode, cs->status); request_complete(mgmt, cs->status, opcode, index, 0, NULL); break; default: util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] event 0x%04x", index, event); process_notify(mgmt, event, index, length, mgmt->buf + MGMT_HDR_SIZE); break; } if (mgmt->destroyed) return FALSE; return TRUE; }