int libxenvchan_write(struct libxenvchan *ctrl, const void *data, size_t size) { int avail; if (!libxenvchan_is_open(ctrl)) return -1; if (ctrl->blocking) { size_t pos = 0; while (1) { avail = fast_get_buffer_space(ctrl, size - pos); if (pos + avail > size) avail = size - pos; if (avail) pos += do_send(ctrl, data + pos, avail); if (pos == size) return pos; if (libxenvchan_wait(ctrl)) return -1; if (!libxenvchan_is_open(ctrl)) return -1; } } else { avail = fast_get_buffer_space(ctrl, size); if (size > avail) size = avail; if (size == 0) return 0; return do_send(ctrl, data, size); } }
int libvchan_wait(libvchan_t *ctrl) { int ret = -2; /* invalid, so can be distinguished from real libxenvchan_wait return code */ struct xs_handle *xs; if (ctrl->xenvchan->is_server && libxenvchan_is_open(ctrl->xenvchan) == 2) { /* In case of vchan server waiting for a client, we'll not receive any * notification if the remote domain dies before connecting. Because of * that, check periodically if remote domain is still alive while * waiting for a connection. Actually this doesn't cover all the cases * - if remote domain is still alive, but remote process dies before * connecting, we'll also not receive any notification. But this, in * most cases, can be solved by application using libvchan. * * During normal operation this shouldn't be long - in most cases vchan * client will connect almost instantly. So this sleep(10) loop will * not hurt. Alternativelly it could be implemented with * xs_watch("@releaseDomain"), but such approach will slow down most * common execution path (xs_open+xs_watch even if client connects * right away). */ while (ret == -2 && libxenvchan_is_open(ctrl->xenvchan) == 2) { fd_set rd_set; struct timeval tv = { 10, 0 }; int vchan_fd = libxenvchan_fd_for_select(ctrl->xenvchan); FD_ZERO(&rd_set); FD_SET(vchan_fd, &rd_set); switch (select(vchan_fd+1, &rd_set, NULL, NULL, &tv)) { case 0: if (!libvchan__check_domain_alive(ctrl->xc_handle, ctrl->remote_domain)) return -1; break; case 1: /* break the loop */ ret = -1; break; default: if (errno == EINTR) break; perror("select"); return -1; } } } ret = libxenvchan_wait(ctrl->xenvchan); if (ctrl->xs_path) { /* remove xenstore entry at first client connection */ xs = xs_open(0); if (xs) { /* if xenstore connection failed just do not remove entries, but do * not abort whole function, especially still free the memory */ xs_rm(xs, 0, ctrl->xs_path); xs_close(xs); } free(ctrl->xs_path); ctrl->xs_path = NULL; } return ret; }
void receiveForever(struct libxenvchan *chan){ int size; char * msg; int i = 0; while(1){ libxenvchan_wait(chan); msg = vchan_receive(chan,&size); printf("Received: "); for(i = 0; i< size; i++){ printf("%c",msg[i]); } printf("\n"); } }
int libxenvchan_read(struct libxenvchan *ctrl, void *data, size_t size) { while (1) { int avail = fast_get_data_ready(ctrl, size); if (avail && size > avail) size = avail; if (avail) return do_recv(ctrl, data, size); if (!libxenvchan_is_open(ctrl)) return -1; if (!ctrl->blocking) return 0; if (libxenvchan_wait(ctrl)) return -1; } }
/** * returns 0 if no buffer space is available, -1 on error, or size on success */ int libxenvchan_send(struct libxenvchan *ctrl, const void *data, size_t size) { int avail; while (1) { if (!libxenvchan_is_open(ctrl)) return -1; avail = fast_get_buffer_space(ctrl, size); if (size <= avail) return do_send(ctrl, data, size); if (!ctrl->blocking) return 0; if (size > wr_ring_size(ctrl)) return -1; if (libxenvchan_wait(ctrl)) return -1; } }
int main(int argc, char *argv[]) { //Vchan Prep struct libxenvchan *chan = 0; int selfId; // domainID of this node; int otherId; int client= 0; xentoollog_logger_stdiostream * xc_logger; xc_logger = createDebugLogger(); selfId =getDomId(); fprintf(stdout,"Client: Domain Id: %d\n", selfId); if(argc != 3){ fprintf(stderr,"Error: Usage ./Client [server-0, client-1] [other domId]\n"); exit(1); } sscanf(argv[1],"%d",&client); sscanf(argv[2],"%d",&otherId); if (!client){ chan = vchan_server_init((xentoollog_logger *) xc_logger,otherId); }else{ chan = vchan_client_init((xentoollog_logger *)xc_logger, otherId); } //Sockets Prep int listenfd = 0, connfd = 0; struct sockaddr_in serv_addr; char recvBuff[1024]; int n = 0; char sendBuff[1024]; time_t ticks; listenfd = socket(AF_INET, SOCK_STREAM, 0); memset(&serv_addr, '0', sizeof(serv_addr)); memset(sendBuff, '0', sizeof(sendBuff)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(5000); bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); printf("\n Waiting for a client...\n"); listen(listenfd, 10); printf("\n 1\n"); while(1) { printf("\n 2\n"); connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); printf("\n 3\n"); ticks = time(NULL); while(1) { //GET REQUEST printf("Waiting for request from Attester\n"); int size; char * msg; int i = 0; libxenvchan_wait(chan); msg = vchan_receive(chan,&size); printf("Received: "); for(i = 0; i< size; i++){ printf("%c",msg[i]); } printf("\n"); //ISSUE REQUEST printf("Sending request message to Measurer\nsent: "); memset(sendBuff, 0, sizeof(sendBuff)); snprintf(sendBuff, sizeof(sendBuff), msg); if(fputs(sendBuff, stdout) == EOF) { printf("\n Error : Fputs error\n"); } write(connfd, sendBuff, sizeof(sendBuff)); //GET RESPONSE printf("Waiting for response from Measurer\n"); n = read(connfd, recvBuff, sizeof(recvBuff)); recvBuff[n] = 0; if(fputs(recvBuff, stdout) == EOF) { printf("\n Error : Fputs error\n"); } if(n < 0) { printf("\n Read error \n"); } //SEND RESPONSE TO ATTESTER printf("Sending response to Attester\n"); //char * tmp = (char *) malloc(256 * sizeof(char)); //printf("Enter text to send:\n"); //fgets(tmp, 256, stdin); vchan_send(chan,recvBuff, strlen(recvBuff)); } close(connfd); sleep(1); } }