/* destroy a pending request */ static int nbt_name_request_destructor(struct nbt_name_request *req) { if (req->state == NBT_REQUEST_SEND) { DLIST_REMOVE(req->nbtsock->send_queue, req); } if (req->state == NBT_REQUEST_WAIT) { req->nbtsock->num_pending--; } if (req->name_trn_id != 0 && !req->is_reply) { idr_remove(req->nbtsock->idr, req->name_trn_id); req->name_trn_id = 0; } if (req->te) { req->te = NULL; } if (req->nbtsock->send_queue == NULL) { EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde); } if (req->nbtsock->num_pending == 0 && req->nbtsock->incoming.handler == NULL) { EVENT_FD_NOT_READABLE(req->nbtsock->fde); } /* once this has been called for this req, don't call again */ talloc_set_destructor(req, NULL); return 0; }
/* handle send events on a nbt dgram socket */ static void dgm_socket_send(struct nbt_dgram_socket *dgmsock) { struct nbt_dgram_request *req; NTSTATUS status; while ((req = dgmsock->send_queue)) { size_t len; len = req->encoded.length; status = socket_sendto(dgmsock->sock, &req->encoded, &len, req->dest); if (NT_STATUS_IS_ERR(status)) { DEBUG(3,("Failed to send datagram of length %u to %s:%d: %s\n", (unsigned)req->encoded.length, req->dest->addr, req->dest->port, nt_errstr(status))); DLIST_REMOVE(dgmsock->send_queue, req); talloc_free(req); continue; } if (!NT_STATUS_IS_OK(status)) return; DLIST_REMOVE(dgmsock->send_queue, req); talloc_free(req); } EVENT_FD_NOT_WRITEABLE(dgmsock->fde); return; }
/* handle send events on a nbt name socket */ static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) { struct nbt_name_request *req = nbtsock->send_queue; TALLOC_CTX *tmp_ctx = talloc_new(nbtsock); NTSTATUS status; while ((req = nbtsock->send_queue)) { size_t len; len = req->encoded.length; status = socket_sendto(nbtsock->sock, &req->encoded, &len, req->dest); if (NT_STATUS_IS_ERR(status)) goto failed; if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); return; } DLIST_REMOVE(nbtsock->send_queue, req); req->state = NBT_REQUEST_WAIT; if (req->is_reply) { talloc_free(req); } else { EVENT_FD_READABLE(nbtsock->fde); nbtsock->num_pending++; } } EVENT_FD_NOT_WRITEABLE(nbtsock->fde); talloc_free(tmp_ctx); return; failed: DLIST_REMOVE(nbtsock->send_queue, req); nbt_name_request_destructor(req); req->status = status; req->state = NBT_REQUEST_ERROR; talloc_free(tmp_ctx); if (req->async.fn) { req->async.fn(req); } return; }
/* called when an incoming connection is writeable */ static void queue_io_write(struct ctdb_queue *queue) { while (queue->out_queue) { struct ctdb_queue_pkt *pkt = queue->out_queue; ssize_t n; if (queue->ctdb->flags & CTDB_FLAG_TORTURE) { n = write(queue->fd, pkt->data, 1); } else { n = write(queue->fd, pkt->data, pkt->length); } if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { if (pkt->length != pkt->full_length) { /* partial packet sent - we have to drop it */ DLIST_REMOVE(queue->out_queue, pkt); queue->out_queue_length--; talloc_free(pkt); } talloc_free(queue->fde); queue->fde = NULL; queue->fd = -1; tevent_schedule_immediate(queue->im, queue->ctdb->ev, queue_dead, queue); return; } if (n <= 0) return; if (n != pkt->length) { pkt->length -= n; pkt->data += n; return; } DLIST_REMOVE(queue->out_queue, pkt); queue->out_queue_length--; talloc_free(pkt); } EVENT_FD_NOT_WRITEABLE(queue->fde); }
/* handle fd send events on a KDC socket */ static void kdc_send_handler(struct kdc_socket *kdc_socket) { while (kdc_socket->send_queue) { struct kdc_reply *rep = kdc_socket->send_queue; NTSTATUS status; size_t sendlen; status = socket_sendto(kdc_socket->sock, &rep->packet, &sendlen, rep->dest); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { break; } if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_BUFFER_SIZE)) { /* Replace with a krb err, response to big */ } DLIST_REMOVE(kdc_socket->send_queue, rep); talloc_free(rep); } if (kdc_socket->send_queue == NULL) { EVENT_FD_NOT_WRITEABLE(kdc_socket->fde); } }