/* Return 0 if we sent something, non-0 otherwise. If 0 is returned, the caller should delay waiting for a response. Otherwise, the caller should immediately move on to process the next connection. */ static int maybe_send(krb5_context context, struct conn_state *conn, struct select_state *selstate, struct sendto_callback_info *callback_info) { sg_buf *sg; ssize_t ret; dprint("maybe_send(@%p) state=%s type=%s\n", conn, state_strings[conn->state], conn->is_udp ? "udp" : "tcp"); if (conn->state == INITIALIZING) return start_connection(context, conn, selstate, callback_info); /* Did we already shut down this channel? */ if (conn->state == FAILED) { dprint("connection already closed\n"); return -1; } if (conn->socktype == SOCK_STREAM) { dprint("skipping stream socket\n"); /* The select callback will handle flushing any data we haven't written yet, and we only write it once. */ return -1; } /* UDP - retransmit after a previous attempt timed out. */ sg = &conn->x.out.sgbuf[0]; TRACE_SENDTO_KDC_UDP_SEND_RETRY(context, conn); dprint("sending %d bytes on fd %d\n", SG_LEN(sg), conn->fd); ret = send(conn->fd, SG_BUF(sg), SG_LEN(sg), 0); if (ret < 0 || (size_t) ret != SG_LEN(sg)) { TRACE_SENDTO_KDC_UDP_ERROR_SEND_RETRY(context, conn, SOCKET_ERRNO); dperror("send"); /* Keep connection alive, we'll try again next pass. Is this likely to catch any errors we didn't get from the select callbacks? */ return -1; } /* Yay, it worked. */ return 0; }
/* Return 0 if we sent something, non-0 otherwise. If 0 is returned, the caller should delay waiting for a response. Otherwise, the caller should immediately move on to process the next connection. */ static int maybe_send(krb5_context context, struct conn_state *conn, const krb5_data *message, struct select_state *selstate, const krb5_data *realm, struct sendto_callback_info *callback_info) { sg_buf *sg; ssize_t ret; if (conn->state == INITIALIZING) { return start_connection(context, conn, message, selstate, realm, callback_info); } /* Did we already shut down this channel? */ if (conn->state == FAILED) { return -1; } if (conn->addr.transport != UDP) { /* The select callback will handle flushing any data we haven't written yet, and we only write it once. */ return -1; } /* UDP - retransmit after a previous attempt timed out. */ sg = &conn->out.sgbuf[0]; TRACE_SENDTO_KDC_UDP_SEND_RETRY(context, &conn->addr); ret = send(conn->fd, SG_BUF(sg), SG_LEN(sg), 0); if (ret < 0 || (size_t) ret != SG_LEN(sg)) { TRACE_SENDTO_KDC_UDP_ERROR_SEND_RETRY(context, &conn->addr, SOCKET_ERRNO); /* Keep connection alive, we'll try again next pass. Is this likely to catch any errors we didn't get from the select callbacks? */ return -1; } /* Yay, it worked. */ return 0; }