/* Called by: zxcot_main */ static int zxid_addmd(zxid_conf* cf, char* mdurl, int dry_run, const char* dcot) { int got; fdtype fd; char* p; zxid_entity* ent; struct zx_str* ss; if (mdurl) { ent = zxid_get_meta(cf, mdurl); } else { read_all_fd(fdstdin, buf, sizeof(buf)-1, &got); buf[got] = 0; p = buf; ent = zxid_parse_meta(cf, &p, buf+got); } if (!ent) { ERR("***** Parsing metadata failed %d", 0); return 1; } for (; ent; ent = ent->n) { ss = zx_easy_enc_elem_opt(cf, &ent->ed->gg); if (!ss) return 2; if (dry_run) { write_all_fd(fdstdout, ss->s, ss->len); zx_str_free(cf->ctx, ss); if (verbose>1) printf("\n\nDry run ent(%s) to %s%s\n", ent->eid, dcot, ent->sha1_name); continue; } if (verbose) printf("Writing ent(%s) to %s%s\n", ent->eid, dcot, ent->sha1_name); fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -a", 1, "%s%s", dcot, ent->sha1_name); if (fd == BADFD) { perror("open metadata for writing metadata to cache"); ERR("Failed to open file for writing: sha1_name(%s) to metadata cache", ent->sha1_name); zx_str_free(cf->ctx, ss); return 1; } write_all_fd(fd, ss->s, ss->len); zx_str_free(cf->ctx, ss); close_file(fd, (const char*)__FUNCTION__); } return 0; }
/* Called by: */ size_t zxid_curl_write_data(void *buffer, size_t size, size_t nmemb, void *userp) { int len = size * nmemb; #if 1 struct zxid_curl_ctx* rc = (struct zxid_curl_ctx*)userp; int old_len, new_len, in_buf = rc->p - rc->buf; if (rc->p + len > rc->lim) { old_len = rc->lim-rc->buf; new_len = MIN(MAX(old_len + old_len, in_buf + len), ZXID_MAX_CURL_BUF); if (new_len == ZXID_MAX_CURL_BUF) { ERR("Too large HTTP response. Response length at least %d. Maximum allowed length (ZXID_MAX_CURL_BUF): %d", in_buf + len, ZXID_MAX_CURL_BUF); return -1; /* Signal error */ } D("Reallocating curl buffer from %d to %d in_buf=%d len=%d", old_len, new_len, in_buf, len); REALLOCN(rc->buf, new_len+1); rc->p = rc->buf + in_buf; rc->lim = rc->buf + new_len; } memcpy(rc->p, buffer, len); rc->p += len; if (errmac_debug & CURL_INOUT) { INFO("RECV(%.*s) %d chars", len, (char*)buffer, len); D_XML_BLOB(0, "RECV", len, (char*)buffer); } #else int fd = (int)userp; write_all_fd(fd, buffer, len); #endif return len; }
void fable_release_read_buf_shmem_pipe(void* handle, struct fable_buf* fbuf) { struct shmem_pipe_handle_conn *sp = (struct shmem_pipe_handle_conn*)handle; struct shmem_pipe_buf* buf = (struct shmem_pipe_buf*)fbuf; assert(buf->base.nbufs == 1 && buf->base.bufs == &buf->iov); struct extent *inc = (struct extent*)(sp->incoming + sp->incoming_bytes_consumed); assert(((char*)sp->ring) + inc->base == fbuf->bufs[0].iov_base); struct extent tosend; // Was the extent fully consumed by this read? if(fbuf->bufs[0].iov_len == inc->size) { tosend = *inc; // Dismiss this incoming extent sp->incoming_bytes_consumed += sizeof(struct extent); if(sp->incoming_bytes_consumed - sp->incoming_bytes < sizeof(struct extent)) { memmove(sp->incoming, sp->incoming + sp->incoming_bytes_consumed, sp->incoming_bytes - sp->incoming_bytes_consumed); sp->incoming_bytes -= sp->incoming_bytes_consumed; sp->incoming_bytes_consumed = 0; } } // Otherwise, divide the extent in two; queue one and keep the other. else { tosend.base = inc->base; tosend.size = fbuf->bufs[0].iov_len; inc->base += fbuf->bufs[0].iov_len; inc->size -= fbuf->bufs[0].iov_len; } // Queue it for transmission back to the writer struct extent *out; out = &sp->outgoing_extents[sp->nr_outgoing_extents-1]; /* Try to reuse previous outgoing extent */ if (sp->nr_outgoing_extents != 0 && out->base + out->size == tosend.base) { out->size += tosend.size; } else { sp->outgoing_extents[sp->nr_outgoing_extents] = tosend; // Struct copy sp->nr_outgoing_extents++; } sp->outgoing_extent_bytes += tosend.size; // Send the queued extents, if the queue is big enough // TODO: blocking operations regardless of nonblocking status. if (sp->outgoing_extent_bytes > ring_size / 8) { write_all_fd(sp->base.fd, (char*)sp->outgoing_extents, sp->nr_outgoing_extents * sizeof(struct extent), 1 /* Allow writing to closed socket */); sp->nr_outgoing_extents = 0; sp->outgoing_extent_bytes = 0; } free(fbuf); }
int fable_release_write_buf_shmem_pipe(void* handle, struct fable_buf* fbuf) { struct shmem_pipe_handle_conn *sp = (struct shmem_pipe_handle_conn*)handle; struct shmem_pipe_buf *buf = (struct shmem_pipe_buf*)fbuf; struct extent ext; assert(fbuf->nbufs == 1 && fbuf->bufs == &buf->iov); unsigned long offset = ((char*)fbuf->bufs[0].iov_base) - ((char*)sp->ring); ext.base = offset; ext.size = fbuf->bufs[0].iov_len; // TODO: Blocking ops in nonblocking context write_all_fd(sp->base.fd, (char*)&ext, sizeof(ext), 1 /* Allow writing to closed socket */); assert(sp->nr_alloc_nodes <= 3); return 1; }
/* Called by: zxcot_main */ static int zxid_reg_svc(zxid_conf* cf, int bs_reg, int dry_run, const char* ddimd, const char* duid) { char sha1_name[28]; char path[ZXID_MAX_BUF]; int got; fdtype fd; struct zx_root_s* r; zxid_epr* epr; struct zx_str* ss; struct zx_str* tt; read_all_fd(fdstdin, buf, sizeof(buf)-1, &got); /* Read EPR */ buf[got] = 0; r = zx_dec_zx_root(cf->ctx, got, buf, "cot reg_svc"); if (!r || !r->EndpointReference) { ERR("Failed to parse <EndpointReference> buf(%.*s)", got, buf); return 1; } epr = r->EndpointReference; if (!ZX_SIMPLE_ELEM_CHK(epr->Address)) { ERR("<EndpointReference> MUST have <Address> element buf(%.*s)", got, buf); return 1; } if (!epr->Metadata) { ERR("<EndpointReference> MUST have <Metadata> element buf(%.*s)", got, buf); return 1; } if (!ZX_SIMPLE_ELEM_CHK(epr->Metadata->ProviderID)) { ERR("<EndpointReference> MUST have <Metadata> with <ProviderID> element buf(%.*s)", got, buf); return 1; } if (!epr->Metadata->ServiceType) { ERR("<EndpointReference> MUST have <ServiceType> element buf(%.*s)", got, buf); return 1; } /* *** possibly add something here and double check the required fields are available. */ ss = zx_easy_enc_elem_opt(cf, &epr->gg); if (!ss) return 2; #if 0 // *** wrong tt = ZX_GET_CONTENT(epr->Metadata->ProviderID); #else tt = ZX_GET_CONTENT(epr->Metadata->ServiceType); #endif got = MIN(tt->len, sizeof(path)-1); memcpy(path, tt?tt->s:"", got); path[got] = 0; zxid_fold_svc(path, got); sha1_safe_base64(sha1_name, ss->len, ss->s); sha1_name[27] = 0; if (verbose) fprintf(stderr, "Registering metadata in %s%s,%s\n", ddimd, path, sha1_name); if (dry_run) { if (verbose) fprintf(stderr, "Register EPR dry run. Would have written to path(%s%s,%s). " "You may also want to\n" " touch %s.all/.bs/%s,%s\n\n", ddimd, path, sha1_name, uiddir, path, sha1_name); fflush(stdin); write_all_fd(fdstdout, ss->s, ss->len); zx_str_free(cf->ctx, ss); return 0; } D("Register EPR path(%s%s,%s) in discovery metadata.", ddimd, path, sha1_name); fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -b", 1, "%s%s,%s", ddimd, path, sha1_name); if (fd == BADFD) { perror("open epr for registering"); ERR("Failed to open file for writing: sha1_name(%s,%s) to service registration", path, sha1_name); zx_str_free(cf->ctx, ss); return 1; } write_all_fd(fd, ss->s, ss->len); zx_str_free(cf->ctx, ss); close_file(fd, (const char*)__FUNCTION__); if (bs_reg) { if (verbose) fprintf(stderr, "Activating bootstrap %s.all/.bs/%s,%s", duid, path, sha1_name); if (!dryrun) { fd = open_fd_from_path(O_CREAT | O_WRONLY | O_TRUNC, 0666, "zxcot -bs", 1, "%s.all/.bs/%s,%s", duid, path, sha1_name); if (fd == BADFD) { perror("open epr for bootstrap activation"); ERR("Failed to open file for writing: sha1_name(%s,%s) to bootstrap activation", path, sha1_name); return 1; } write_all_fd(fd, "", 0); close_file(fd, (const char*)__FUNCTION__); } } else { D("You may also want to activate bootstrap by\n touch %s.all/.bs/%s,%s", duid, path, sha1_name); } return 0; }
void* fable_connect_shmem_pipe(const char* name, int direction) { // As the connection initiator, it's our responsibility to supply shared memory. char random_name[22]; int ring_pages = pow(2, ring_order); int shm_fd = -1; errno = EEXIST; for(int i = 0; i < 100 && shm_fd == -1 && errno == EEXIST; ++i) { strcpy(random_name, "/fable_segment_XXXXXX"); if(!mktemp(random_name)) break; shm_fd = shm_open(random_name, O_RDWR|O_CREAT|O_EXCL, 0600); } if(shm_fd == -1) return 0; shm_unlink(random_name); if (ftruncate(shm_fd, PAGE_SIZE * ring_pages) < 0) { close(shm_fd); return 0; } void* ring_addr = mmap(NULL, PAGE_SIZE * ring_pages, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0); void* unix_handle = fable_connect_unixdomain(name, FABLE_DIRECTION_DUPLEX); if(!unix_handle) return 0; int unix_fd = *((int*)unix_handle); free(unix_handle); // OK, send our partner the FD and the appropriate size to mmap. int send_ret = unix_send_fd(unix_fd, shm_fd); close(shm_fd); if(send_ret <= 0) { munmap(ring_addr, PAGE_SIZE * ring_pages); close(unix_fd); return 0; } write_all_fd(unix_fd, (const char*)&ring_pages, sizeof(int)); struct shmem_pipe_handle_conn* conn_handle = (struct shmem_pipe_handle_conn*)malloc(sizeof(struct shmem_pipe_handle_conn)); memset(conn_handle, 0, sizeof(struct shmem_pipe_handle_conn)); conn_handle->base.fd = unix_fd; conn_handle->base.type = SHMEMPIPE_HANDLE_CONN; conn_handle->ring = ring_addr; conn_handle->ring_pages = ring_pages; conn_handle->direction = direction; if(direction == FABLE_DIRECTION_SEND) shmem_pipe_init_send(conn_handle); // Otherwise memset-0 is enough return conn_handle; }