void rpc_destroy_context(struct rpc_context *rpc) { struct rpc_pdu *pdu; unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); /* If we are a server context, free all registered endpoints. */ while (rpc->endpoints != NULL) { struct rpc_endpoint *next = rpc->endpoints->next; free(rpc->endpoints); rpc->endpoints = next; } while((pdu = rpc->outqueue.head) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu); rpc_free_pdu(rpc, pdu); } for (i = 0; i < HASHES; i++) { struct rpc_queue *q = &rpc->waitpdu[i]; while((pdu = q->head) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); LIBNFS_LIST_REMOVE(&q->head, pdu); rpc_free_pdu(rpc, pdu); } } rpc_free_all_fragments(rpc); if (rpc->auth) { auth_destroy(rpc->auth); rpc->auth =NULL; } if (rpc->fd != -1) { close(rpc->fd); } if (rpc->error_string != NULL) { free(rpc->error_string); rpc->error_string = NULL; } rpc->magic = 0; free(rpc); }
void rpc_destroy_context(struct rpc_context *rpc) { struct rpc_pdu *pdu; unsigned int i; assert(rpc->magic == RPC_CONTEXT_MAGIC); while((pdu = rpc->outqueue.head) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); LIBNFS_LIST_REMOVE(&rpc->outqueue.head, pdu); rpc_free_pdu(rpc, pdu); } for (i = 0; i < HASHES; i++) { struct rpc_queue *q = &rpc->waitpdu[i]; while((pdu = q->head) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); LIBNFS_LIST_REMOVE(&q->head, pdu); rpc_free_pdu(rpc, pdu); } } rpc_free_all_fragments(rpc); auth_destroy(rpc->auth); rpc->auth =NULL; if (rpc->fd != -1) { close(rpc->fd); } if (rpc->encodebuf != NULL) { free(rpc->encodebuf); rpc->encodebuf = NULL; } if (rpc->error_string != NULL) { free(rpc->error_string); rpc->error_string = NULL; } if (rpc->udp_dest != NULL) { free(rpc->udp_dest); rpc->udp_dest = NULL; } rpc->magic = 0; free(rpc); }
void rpc_destroy_context(struct rpc_context *rpc) { struct rpc_pdu *pdu; assert(rpc->magic == RPC_CONTEXT_MAGIC); while((pdu = rpc->outqueue) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); SLIST_REMOVE(&rpc->outqueue, pdu); rpc_free_pdu(rpc, pdu); } while((pdu = rpc->waitpdu) != NULL) { pdu->cb(rpc, RPC_STATUS_CANCEL, NULL, pdu->private_data); SLIST_REMOVE(&rpc->waitpdu, pdu); rpc_free_pdu(rpc, pdu); } rpc_free_all_fragments(rpc); auth_destroy(rpc->auth); rpc->auth =NULL; if (rpc->fd != -1) { #if defined(WIN32) closesocket(rpc->fd); #else close(rpc->fd); #endif } if (rpc->encodebuf != NULL) { free(rpc->encodebuf); rpc->encodebuf = NULL; } if (rpc->error_string != NULL) { free(rpc->error_string); rpc->error_string = NULL; } if (rpc->udp_dest != NULL) { free(rpc->udp_dest); rpc->udp_dest = NULL; } rpc->magic = 0; free(rpc); }
int rpc_process_pdu(struct rpc_context *rpc, char *buf, int size) { struct rpc_pdu *pdu, *prev_pdu; struct rpc_queue *q; ZDR zdr; int pos, recordmarker = 0; unsigned int hash; uint32_t xid; char *reasbuf = NULL; assert(rpc->magic == RPC_CONTEXT_MAGIC); memset(&zdr, 0, sizeof(ZDR)); zdrmem_create(&zdr, buf, size, ZDR_DECODE); if (rpc->is_udp == 0) { if (zdr_int(&zdr, &recordmarker) == 0) { rpc_set_error(rpc, "zdr_int reading recordmarker failed"); zdr_destroy(&zdr); return -1; } if (!(recordmarker&0x80000000)) { zdr_destroy(&zdr); if (rpc_add_fragment(rpc, buf+4, size-4) != 0) { rpc_set_error(rpc, "Failed to queue fragment for reassembly."); return -1; } return 0; } } /* reassembly */ if (recordmarker != 0 && rpc->fragments != NULL) { struct rpc_fragment *fragment; uint32_t total = size - 4; char *ptr; zdr_destroy(&zdr); for (fragment = rpc->fragments; fragment; fragment = fragment->next) { total += fragment->size; if (total < fragment->size) { rpc_set_error(rpc, "Fragments too large"); rpc_free_all_fragments(rpc); return -1; } } reasbuf = malloc(total); if (reasbuf == NULL) { rpc_set_error(rpc, "Failed to reassemble PDU"); rpc_free_all_fragments(rpc); return -1; } ptr = reasbuf; for (fragment = rpc->fragments; fragment; fragment = fragment->next) { memcpy(ptr, fragment->data, fragment->size); ptr += fragment->size; } memcpy(ptr, buf + 4, size - 4); zdrmem_create(&zdr, reasbuf, total, ZDR_DECODE); rpc_free_all_fragments(rpc); } if (rpc->is_server_context) { int ret; ret = rpc_process_call(rpc, &zdr); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return ret; } pos = zdr_getpos(&zdr); if (zdr_int(&zdr, (int *)&xid) == 0) { rpc_set_error(rpc, "zdr_int reading xid failed"); zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return -1; } zdr_setpos(&zdr, pos); /* Look up the transaction in a hash table of our requests */ hash = rpc_hash_xid(xid); q = &rpc->waitpdu[hash]; /* Follow the hash chain. Linear traverse singly-linked list, * but track previous entry for optimised removal */ prev_pdu = NULL; for (pdu=q->head; pdu; pdu=pdu->next) { if (pdu->xid != xid) { prev_pdu = pdu; continue; } if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { /* Singly-linked but we track head and tail */ if (pdu == q->head) q->head = pdu->next; if (pdu == q->tail) q->tail = prev_pdu; if (prev_pdu != NULL) prev_pdu->next = pdu->next; rpc->waitpdu_len--; } if (rpc_process_reply(rpc, pdu, &zdr) != 0) { rpc_set_error(rpc, "rpc_procdess_reply failed"); } zdr_destroy(&zdr); if (rpc->is_udp == 0 || rpc->is_broadcast == 0) { rpc_free_pdu(rpc, pdu); } if (reasbuf != NULL) { free(reasbuf); } return 0; } zdr_destroy(&zdr); if (reasbuf != NULL) { free(reasbuf); } return 0; }