/* non-blocking, returns socket descriptor or -1 if none available * NOTE: This function assumes that the cursor of all buf's is zero, * and it can call buf_reset(source, tag). */ int MPINU_rank_of_msg_avail_in_cache(int source, int tag) { if (source != MPI_ANY_SOURCE) { if (tag == MPI_ANY_TAG) { if (buf_avail(source, sizeof(struct msg_hdr))) return source; } else while (buf_avail(source, sizeof(struct msg_hdr))) { struct msg_hdr *hdr = buf_peek(source, sizeof(struct msg_hdr)); if ( ntohl( hdr->tag ) == tag ) { buf_reset(source, tag); /* clean up for next caller */ return source; } else { /* Else skip header and body */ buf_skip( source, sizeof(struct msg_hdr) + ntohl(hdr->size) ); } } buf_reset(source, tag); /* clean up for next caller */ } else /* else source == MPI_ANY_SOURCE */ for (source = 0; source < MPINU_num_slaves; source++) { int rank = MPINU_rank_of_msg_avail_in_cache(source, tag); if (rank != -1) return rank; } /* if no source had buf_avail, then no msg avail */ return -1; }
int isns_authblock_decode(buf_t *bp, struct isns_authblk *auth) { unsigned int avail = buf_avail(bp); if (!buf_get32(bp, &auth->iab_bsd) || !buf_get32(bp, &auth->iab_length) || !buf_get64(bp, &auth->iab_timestamp) || !buf_get32(bp, &auth->iab_spi_len)) return 0; /* Make sure the length specified by the auth block * is reasonable. */ if (auth->iab_length < ISNS_AUTHBLK_SIZE || auth->iab_length > avail) return 0; /* This chops off any data trailing the auth block. * It also makes sure that we detect if iab_length * exceeds the amount of available data. */ if (!buf_truncate(bp, auth->iab_length - ISNS_AUTHBLK_SIZE)) return 0; auth->iab_spi = buf_head(bp); if (!buf_pull(bp, auth->iab_spi_len)) return 0; auth->iab_sig = buf_head(bp); auth->iab_sig_len = buf_avail(bp); return 1; }
ssize_t MPINU_recv_msg_body_with_cache(int source, void *buf, size_t len) { if ( buf_avail(source, len) ) { buf_dequeue(source, buf, len, 0); /* flags = 0: Never peek for body */ return len; } else { /* Body cannot be split between buf and network; * If len bytes weren't available in buf, then expect 0 bytes in buf */ assert( !buf_avail(source, 1) ); /* flags = 0: Never peek for body */ len = MPINU_recvall(MPINU_pg_array[source].sd, buf, len, 0); return len; } }
/* Account for "n" bytes being added in the buffer. */ static void buf_more(struct buf *buf, size_t n) { assert(n <= buf_avail(buf)); buf->in += n; }
/* On receiving a msg_hdr, we first do buf_reset(source, tag), * but _not_ on receiving a msg_body */ ssize_t MPINU_recv_msg_hdr_with_cache(int s, int tag, void *buf, size_t len, int flags) { int msg_found = 0; int source = MPINU_rank_from_socket(s); buf_reset(source, tag); while ( !msg_found && buf_avail(source, len) ) { if ( ntohl( ((struct msg_hdr *)buf_peek(source, len))->tag ) == tag || tag == MPI_ANY_TAG ) { buf_dequeue(source, buf, len, flags & MSG_PEEK); msg_found = 1; } else { int body_len; buf_skip(source, len); /* Skip header */ body_len = ntohl( ((struct msg_hdr *)buf)->size ); buf_skip(source, body_len); /* Skip body */ } } if ( !msg_found ) assert( !buf_avail(source, len) ); while ( !msg_found ) { len = MPINU_recvall(MPINU_pg_array[source].sd, buf, len, flags); assert( len == sizeof(struct msg_hdr) ); if ( ntohl( ((struct msg_hdr *)buf)->tag ) == tag || tag == MPI_ANY_TAG ) msg_found = 1; else if ( ! (flags & MSG_PEEK) ) { # define STATIC_SIZE 1000 static char body_buf_array[STATIC_SIZE]; void *body_buf; int body_len; buf_enqueue(source, buf, len); /* Store header */ /* After storing the header, we have to store the corresponding body */ body_len = ntohl( ((struct msg_hdr *)buf)->size ); if (body_len > STATIC_SIZE) body_buf = malloc(body_len); else body_buf = body_buf_array; body_len = MPINU_recvall(MPINU_pg_array[source].sd, body_buf, body_len, flags); buf_enqueue(source, body_buf, body_len); /* Store body */ if (body_len > STATIC_SIZE) free(body_buf); } } return len; }
/* Make more room in the buffer if needed. */ static void buf_prewrite(struct buf *buf) { if (buf_count(buf) == buf_size(buf)) buf_grow(buf, 0); if (buf_count(buf) > 0 && buf_avail(buf) == 0) { memmove(buf->buf, buf->buf + buf->off, buf_count(buf)); buf->off = 0; } }
/* * DSA signature generation and verification */ static void isns_message_digest(EVP_MD_CTX *md, const buf_t *pdu, const struct isns_authblk *blk) { uint64_t stamp; EVP_DigestUpdate(md, buf_head(pdu), buf_avail(pdu)); /* The RFC doesn't say which pieces of the * message should be hashed. * We make an educated guess. */ stamp = htonll(blk->iab_timestamp); EVP_DigestUpdate(md, &stamp, sizeof(stamp)); }
int buf_drain(buf_t *bp) { int n; if (!bp->write_mode || bp->fd < 0) return 0; n = write(bp->fd, bp->base + bp->head, buf_avail(bp)); if (n < 0) { warn("write error"); return 0; } bp->head += n; return n; }
if (new_base == NULL) return 0; bp->base = new_base; bp->size = new_size; bp->allocated = 1; return new_size; } buf_t * buf_split(buf_t **to_split, size_t size) { buf_t *old = *to_split, *new; size_t avail; avail = buf_avail(old); if (size > avail) return NULL; if (size == avail) { *to_split = NULL; return old; } new = buf_alloc(size); buf_put(new, buf_head(old), size); buf_pull(old, size); return new; }