/** * Operator: Finalize */ ngemResult_t ngrcOperatorFinalize( ngrcOperator_t*op) { globus_result_t gResult; ngLog_t *log; ngemResult_t ret = NGEM_SUCCESS; NGEM_FNAME(ngrcOperatorFinalize); log = ngemLogGetDefault(); NGEM_ASSERT(op != NULL); op->ngo_handle = NULL; op->ngo_canceled = false; gResult = globus_mutex_destroy(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_destroy", gResult); ret = NGEM_FAILED; } gResult = globus_cond_destroy(&op->ngo_cond); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_destroy", gResult); ret = NGEM_FAILED; } return ret; }
/** * Socket(Listener only): Get contact string. */ char * ngrcSocketGetContactString( ngrcSocket_t *sock) { ngLog_t *log; struct sockaddr_in addr; char *ret = NULL; int result; ngiSockLen_t addr_len = sizeof(addr); NGEM_FNAME(ngrcSocketGetContactString); NGEM_ASSERT(sock != NULL); log = ngemLogGetDefault(); /* TODO: Local socket */ result = getsockname(sock->ngs_fd, (struct sockaddr *)&addr, &addr_len); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "getsockname: %s\n", strerror(errno)); return NULL; } NGEM_ASSERT(addr.sin_family == AF_INET); /* Remote Communication Proxy uses local address only. */ ret = ngemStrdupPrintf("ng_tcp://localhost:%d/", ntohs(addr.sin_port)); if (ret == NULL) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't create address string.\n"); return NULL; } return ret; }
/** * Socket: Read * if nread == 0, EOF or Canceled. */ ngemResult_t ngrcSocketRead( ngrcSocket_t *sock, void *buf, size_t size, size_t *nread) { fd_set rfds; int result; ngLog_t *log; int fdmax; ssize_t nr = -1; NGEM_FNAME(ngrcSocketRead); NGEM_ASSERT(sock != NULL); NGEM_ASSERT(buf != NULL); NGEM_ASSERT(size > 0); NGEM_ASSERT(nread != NULL); *nread = 0; log = ngemLogGetDefault(); while (nr < 0) { FD_ZERO(&rfds); FD_SET(sock->ngs_fd, &rfds); FD_SET(NGEM_PIPE_IN(sock->ngs_pipe), &rfds); fdmax = NGEM_MAX(sock->ngs_fd, NGEM_PIPE_IN(sock->ngs_pipe)) + 1; result = select(fdmax, &rfds, NULL, NULL, NULL); if (result < 0) { if (errno == EINTR) { continue; } ngLogError(log, NGRC_LOGCAT_GT, fName, "select: %s\n", strerror(errno)); return NGEM_FAILED; } if (FD_ISSET(NGEM_PIPE_IN(sock->ngs_pipe), &rfds)) { /* Not continue */ return NGEM_SUCCESS; } if (FD_ISSET(sock->ngs_fd, &rfds)) { nr = read(sock->ngs_fd, buf, size); if (nr < 0) { if (errno == EAGAIN) {continue;} ngLogError(log, NGRC_LOGCAT_GT, fName, "read: %s\n", strerror(errno)); return NGEM_SUCCESS; } } } *nread = nr; return NGEM_SUCCESS; }
/* * Callback function for reading and writing */ static void ngrclGlobusCallback( globus_xio_handle_t handle, globus_result_t cResult, globus_byte_t *buffer, globus_size_t len, globus_size_t nbytes, globus_xio_data_descriptor_t dataDesc, void *userArg) { ngrclOperatorCallbackArg_t *arg = userArg; ngrcOperator_t *op = arg->ngoca_operator; globus_result_t gResult; bool locked = false; ngLog_t *log = NULL; NGEM_FNAME(ngrclGlobusCallback); log = ngemLogGetDefault(); ngLogDebug(log, NGRC_LOGCAT_GT, fName, "Called\n"); ngLogDebug(log, NGRC_LOGCAT_GT, fName, "user_data = %p.\n", arg); gResult = globus_mutex_lock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_lock", gResult); } else { locked = true; } ngLogDebug(log, NGRC_LOGCAT_GT, fName, "nBytes = %lu.\n", (unsigned long)nbytes); arg->ngoca_done = true; arg->ngoca_result = cResult; arg->ngoca_bytes = nbytes; gResult = globus_cond_broadcast(&op->ngo_cond); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_broadcast", gResult); } if (locked) { gResult = globus_mutex_unlock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_unlock", gResult); } locked = false; } return; }
/** * Socket: Destroy */ ngemResult_t ngrcSocketDestroy( ngrcSocket_t *sock) { ngemResult_t ret = NGEM_SUCCESS; int result; ngLog_t *log = NULL; NGEM_FNAME(ngrcSocketDestroy); log = ngemLogGetDefault(); if (sock == NULL) { return NGEM_SUCCESS; } if (sock->ngs_fd >= 0) { result = close(sock->ngs_fd); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); ret = NGEM_FAILED; } sock->ngs_fd = -1; } if (sock->ngs_pipe[0] >= 0) { result = close(sock->ngs_pipe[0]); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); ret = NGEM_FAILED; } sock->ngs_pipe[0] = -1; } if (sock->ngs_pipe[1] >= 0) { result = close(sock->ngs_pipe[1]); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); ret = NGEM_FAILED; } sock->ngs_pipe[1] = -1; } NGI_DEALLOCATE(ngrcSocket_t, sock, log, NULL); return ret; }
/** * Operator: cancel. */ ngemResult_t ngrcOperatorCancel( ngrcOperator_t *op) { ngLog_t *log; globus_result_t gResult; ngemResult_t ret = NGEM_SUCCESS; bool locked = false; NGEM_FNAME(ngrcOperatorCancel); log = ngemLogGetDefault(); gResult = globus_mutex_lock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_lock", gResult); ret = NGEM_FAILED; } else { locked = true; } op->ngo_canceled = true; gResult = globus_cond_broadcast(&op->ngo_cond); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_broadcast", gResult); ret = NGEM_FAILED; } if (locked) { gResult = globus_mutex_unlock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_unlock", gResult); ret = NGEM_FAILED; } locked = false; } gResult = globus_xio_handle_cancel_operations( op->ngo_handle, GLOBUS_XIO_CANCEL_OPEN | GLOBUS_XIO_CANCEL_READ | GLOBUS_XIO_CANCEL_WRITE); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_xio_handle_cancel_operations", gResult); ret = NGEM_FAILED; } return ret; }
/* * Socket: Create(common) */ static ngrcSocket_t * ngrclSocketCreate(int fd) { ngLog_t *log; ngemResult_t nResult; ngrcSocket_t *sock = NULL; NGEM_FNAME(ngrclSocketCreate); log = ngemLogGetDefault(); sock = NGI_ALLOCATE(ngrcSocket_t, log, NULL); if (sock == NULL) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't allocate the storage for socket.\n."); goto error; } sock->ngs_fd = fd; sock->ngs_pipe[0] = -1; sock->ngs_pipe[1] = -1; nResult = ngemFDsetNonblockFlag(sock->ngs_fd); if (nResult != NGEM_SUCCESS) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't set non-block flag to fd.\n"); goto error; } nResult = ngemNonblockingPipe(sock->ngs_pipe); if (nResult != NGEM_SUCCESS) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't create the pipe.\n"); goto error; } return sock; error: nResult = ngrcSocketDestroy(sock); if (nResult != NGEM_SUCCESS) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't destroy the socket.\n"); } sock = NULL; return NULL; }
/** * Operator: Initialize */ ngemResult_t ngrcOperatorInitialize( ngrcOperator_t *op, globus_xio_handle_t handle) { globus_result_t gResult; ngLog_t *log; bool mutexInitialized = false; NGEM_FNAME(ngrcOperatorInitialize); log = ngemLogGetDefault(); NGEM_ASSERT(op != NULL); NGEM_ASSERT(handle != NULL); op->ngo_handle = handle; op->ngo_canceled = false; gResult = globus_mutex_init(&op->ngo_mutex, NULL); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_init", gResult); goto error; } mutexInitialized = true; globus_cond_init(&op->ngo_cond, NULL); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_init", gResult); goto error; } return NGEM_SUCCESS; error: if (mutexInitialized) { gResult = globus_mutex_destroy(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_destroy", gResult); } } return NGEM_FAILED; }
/** * Socket: Cancels operation(read and write). */ ngemResult_t ngrcSocketCancel( ngrcSocket_t *sock) { int result; ngLog_t *log = NULL; NGEM_FNAME(ngrcSocketCancel); log = ngemLogGetDefault(); result = write(NGEM_PIPE_OUT(sock->ngs_pipe), "C", 1); if (result <= 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "write: %s\n", strerror(errno)); return NGEM_FAILED; } return NGEM_SUCCESS; }
/** * Socket: duplicate */ ngrcSocket_t * ngrcSocketDup( ngrcSocket_t *src) { ngLog_t *log; ngrcSocket_t *sock = NULL; int fd = -1; int result; NGEM_FNAME(ngrcSocketDup); log = ngemLogGetDefault(); fd = dup(src->ngs_fd); if (fd < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "dup: %s.\n", strerror(errno)); goto error; } sock = ngrclSocketCreate(fd); if (sock == NULL) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't create socket.\n"); goto error; } return sock; error: if (fd >= 0) { result = close(fd); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); } } return NULL; }
/** * Socket: Create listener. */ ngrcSocket_t * ngrcSocketCreateListener( bool tcpNodelay) { ngLog_t *log; int result; int fd = -1; struct sockaddr_in addr; ngrcSocket_t *sock = NULL; int nodelay; NGEM_FNAME(ngrcSocketCreateListener); log = ngemLogGetDefault(); /* TODO: Local socket */ fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "socket: %s.\n", strerror(errno)); goto error; } memset(&addr, '\0', sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(0); /* any */ result = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "bind: %s.\n", strerror(errno)); goto error; } if (tcpNodelay) { nodelay = 1; result = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "setsockopt(TCP_NODELAY): %s.\n", strerror(errno)); goto error; } } /* backlog is 1 because Remote Communication Proxy handles * a connection only.*/ result = listen(fd, 1); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "listen: %s.\n", strerror(errno)); goto error; } sock = ngrclSocketCreate(fd); if (sock == NULL) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't create socket.\n"); goto error; } return sock; error: if (fd >= 0) { result = close(fd); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); } } return NULL; }
/** * Socket:Write * if nwrite < size, Canceled. */ ngemResult_t ngrcSocketWrite( ngrcSocket_t *sock, void *buf, size_t size, size_t *nwrite) { fd_set rfds; fd_set wfds; int result; ngLog_t *log; int fdmax; ssize_t nw = 0; size_t sum = 0; NGEM_FNAME(ngrcSocketWrite); NGEM_ASSERT(sock != NULL); NGEM_ASSERT(buf != NULL); NGEM_ASSERT(size > 0); NGEM_ASSERT(nwrite != NULL); *nwrite = 0; log = ngemLogGetDefault(); while (sum < size) { FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(sock->ngs_fd, &wfds); FD_SET(NGEM_PIPE_IN(sock->ngs_pipe), &rfds); fdmax = NGEM_MAX(sock->ngs_fd, NGEM_PIPE_IN(sock->ngs_pipe)) + 1; result = select(fdmax, &rfds, &wfds, NULL, NULL); if (result < 0) { if (errno == EINTR) { continue; } ngLogError(log, NGRC_LOGCAT_GT, fName, "select: %s\n", strerror(errno)); return NGEM_FAILED; } if (FD_ISSET(NGEM_PIPE_IN(sock->ngs_pipe), &rfds)) { /* Not continue */ *nwrite = sum; return NGEM_SUCCESS; } if (FD_ISSET(sock->ngs_fd, &wfds)) { nw = write(sock->ngs_fd, ((char *)buf)+sum, size-sum); if (nw < 0) { if (errno == EAGAIN) {continue;} ngLogError(log, NGRC_LOGCAT_GT, fName, "write: %s\n", strerror(errno)); return NGEM_FAILED; } sum += nw; NGEM_ASSERT(sum <= size); } } *nwrite = sum; return NGEM_SUCCESS; }
/** * Socket: accept */ ngrcSocket_t * ngrcSocketAccept( ngrcSocket_t *listener, bool *canceled) { ngrcSocket_t *sock = NULL; int fd = -1; fd_set rfds; int result; ngLog_t *log; int fdmax; struct sockaddr_in addr; ngiSockLen_t addr_len = sizeof(addr); NGEM_FNAME(ngrcSocketAccept); NGEM_ASSERT(listener != NULL); NGEM_ASSERT(canceled != NULL); *canceled = false; log = ngemLogGetDefault(); while (fd < 0) { FD_ZERO(&rfds); FD_SET(listener->ngs_fd, &rfds); FD_SET(NGEM_PIPE_IN(listener->ngs_pipe), &rfds); fdmax = NGEM_MAX(listener->ngs_fd, NGEM_PIPE_IN(listener->ngs_pipe)) + 1; result = select(fdmax, &rfds, NULL, NULL, NULL); if (result < 0) { if (errno == EINTR) { continue; } ngLogError(log, NGRC_LOGCAT_GT, fName, "select: %s\n", strerror(errno)); goto error; } if (FD_ISSET(NGEM_PIPE_IN(listener->ngs_pipe), &rfds)) { /* Not continue */ *canceled = true; return NULL; } if (FD_ISSET(listener->ngs_fd, &rfds)) { fd = accept(listener->ngs_fd, (struct sockaddr *)&addr, &addr_len); if (result < 0) { if (errno == EAGAIN) {continue;} ngLogError(log, NGRC_LOGCAT_GT, fName, "accept: %s\n", strerror(errno)); if (errno == EBADF) { return NULL; } continue; } } } sock = ngrclSocketCreate(fd); if (sock == NULL) { ngLogError(log, NGRC_LOGCAT_GT, fName, "Can't create socket.\n"); goto error; } return sock; error: if (fd >= 0) { result = close(fd); if (result < 0) { ngLogError(log, NGRC_LOGCAT_GT, fName, "close: %s.\n", strerror(errno)); } } return NULL; }
/** * Operator: write */ ngemResult_t ngrcOperatorWrite( ngrcOperator_t *op, void *buf, size_t size, size_t *nWrite, bool *canceled) { globus_result_t gResult; ngemResult_t ret = NGEM_FAILED; bool locked = false; ngLog_t *log = NULL; ngrclOperatorCallbackArg_t arg; NGEM_FNAME(ngrcOperatorWrite); log = ngemLogGetDefault(); NGEM_ASSERT(op != NULL); NGEM_ASSERT(size >= 0); NGEM_ASSERT(nWrite != NULL); NGEM_ASSERT(canceled != NULL); *canceled = false; gResult = globus_mutex_lock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_lock", gResult); goto finalize; } locked = true; ngrclOperatorCallbackArgInitialize(&arg, op); if (op->ngo_canceled) { *canceled = true; } else { ngLogDebug(log, NGRC_LOGCAT_GT, fName, "user_data = %p.\n", &arg); gResult = globus_xio_register_write( op->ngo_handle, buf, size, size, NULL, ngrclGlobusCallback, &arg); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_xio_register_write", gResult); goto finalize; } while (arg.ngoca_done == false) { gResult = globus_cond_wait(&op->ngo_cond, &op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_wait", gResult); } } if (arg.ngoca_result != GLOBUS_SUCCESS) { if (globus_xio_error_is_canceled(arg.ngoca_result) == GLOBUS_FALSE) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "Callback function for writing", arg.ngoca_result); goto finalize; } *canceled = true; } else { ngLogDebug(log, NGRC_LOGCAT_GT, fName, "Writes %lu bytes\n", (unsigned long)arg.ngoca_bytes); *nWrite = arg.ngoca_bytes; } } ret = NGEM_SUCCESS; finalize: ngrclOperatorCallbackArgFinalize(&arg); if (locked) { gResult = globus_mutex_unlock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_unlock", gResult); ret = NGEM_FAILED; } locked = false; } return ret; }
/** * Operator: read */ ngemResult_t ngrcOperatorRead( ngrcOperator_t *op, void *buf, size_t size, size_t *nRead, bool *canceled) { ngemResult_t ret = NGEM_FAILED; globus_result_t gResult; ngLog_t *log = NULL; bool locked = false; ngrclOperatorCallbackArg_t arg; NGEM_FNAME(ngrcOperatorRead); log = ngemLogGetDefault(); NGEM_ASSERT(op != NULL); NGEM_ASSERT(size >= 0); NGEM_ASSERT(nRead != NULL); NGEM_ASSERT(canceled != NULL); *canceled = false; gResult = globus_mutex_lock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_lock", gResult); goto finalize; } locked = true; ngrclOperatorCallbackArgInitialize(&arg, op); if (op->ngo_canceled) { *canceled = true; ret = NGEM_SUCCESS; goto finalize; } gResult = globus_xio_register_read( op->ngo_handle, buf, size, 1, NULL, ngrclGlobusCallback, &arg); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_xio_register_read", gResult); goto finalize; } while (arg.ngoca_done == false) { gResult = globus_cond_wait(&op->ngo_cond, &op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_cond_wait", gResult); } } if (arg.ngoca_result != GLOBUS_SUCCESS) { if (globus_xio_error_is_canceled(arg.ngoca_result) == GLOBUS_TRUE) { *canceled = true; } else if (globus_xio_error_is_eof(arg.ngoca_result) == GLOBUS_TRUE) { *nRead = 0; } else { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "Callback function for reading", arg.ngoca_result); goto finalize; } } else { *nRead = arg.ngoca_bytes; NGEM_ASSERT(*nRead > 0); } ret = NGEM_SUCCESS; finalize: ngrclOperatorCallbackArgFinalize(&arg); if (locked) { gResult = globus_mutex_unlock(&op->ngo_mutex); if (gResult != GLOBUS_SUCCESS) { ngcpLogGlobusError(log, NGRC_LOGCAT_GT, fName, "globus_mutex_unlock", gResult); ret = NGEM_FAILED; } locked = false; } return ret; }