📄 tcpio.c
字号:
continue; } GNUNET_mutex_lock (sock->destroylock); if (sock->sock != NULL) { GNUNET_free (host); GNUNET_mutex_unlock (sock->destroylock); GNUNET_free (soaddr); return GNUNET_OK; } if (sock->dead == GNUNET_YES) { GNUNET_free (host); GNUNET_mutex_unlock (sock->destroylock); GNUNET_free (soaddr); return GNUNET_SYSERR; } if (soaddr->sa_family == AF_INET) { ((struct sockaddr_in *) soaddr)->sin_port = htons (port); osock = SOCKET (PF_INET, SOCK_STREAM, 0); } else {#ifdef PF_INET6 ((struct sockaddr_in6 *) soaddr)->sin6_port = htons (port); osock = SOCKET (PF_INET6, SOCK_STREAM, 0);#else osock = -1; errno = EAFNOSUPPORT;#endif } if (osock == -1) { GNUNET_GE_LOG_STRERROR (sock->ectx, GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "socket"); GNUNET_mutex_unlock (sock->destroylock); GNUNET_free (soaddr); ADVANCE (); continue; } sock->sock = GNUNET_socket_create (sock->ectx, NULL, osock); GNUNET_socket_set_blocking (sock->sock, GNUNET_NO); ret = CONNECT (osock, soaddr, socklen); GNUNET_free (soaddr); if ((ret != 0) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { GNUNET_GE_LOG (sock->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, _("Cannot connect to %s:%u: %s\n"), host, port, STRERROR (errno)); GNUNET_socket_destroy (sock->sock); sock->sock = NULL; GNUNET_mutex_unlock (sock->destroylock); if (errno == ECONNREFUSED) RETRY (); /* gnunetd may just be restarting */ else ADVANCE (); continue; } /* we call select() first with a timeout of WAIT_SECONDS to avoid blocking on a later write indefinitely; Important if a local firewall decides to just drop the TCP handshake... */ FD_ZERO (&rset); FD_ZERO (&wset); FD_ZERO (&eset); FD_SET (osock, &wset); FD_SET (osock, &eset); timeout.tv_sec = 0; timeout.tv_usec = DELAY_PER_RETRY * TRIES_PER_AF * 1000; errno = 0; select_start = GNUNET_get_time (); ret = SELECT (osock + 1, &rset, &wset, &eset, &timeout); if (ret == -1) { if (errno != EINTR) GNUNET_GE_LOG_STRERROR (sock->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "select"); GNUNET_socket_destroy (sock->sock); sock->sock = NULL; GNUNET_mutex_unlock (sock->destroylock); if ((GNUNET_get_time () - select_start > TRIES_PER_AF * DELAY_PER_RETRY) || (errno != EINTR)) ADVANCE (); /* spend enough time trying here */ else RETRY (); continue; } if ((FD_ISSET (osock, &eset)) || (!FD_ISSET (osock, &wset))) { GNUNET_socket_destroy (sock->sock); sock->sock = NULL; GNUNET_mutex_unlock (sock->destroylock); if (GNUNET_get_time () - select_start > TRIES_PER_AF * DELAY_PER_RETRY) ADVANCE (); /* spend enough time trying here */ else RETRY (); continue; } soerr = 0; soerrlen = sizeof (soerr); ret = GETSOCKOPT (osock, SOL_SOCKET, SO_ERROR, &soerr, &soerrlen); if (ret != 0) GNUNET_GE_LOG_STRERROR (sock->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "getsockopt"); if ((soerr != 0) || (ret != 0 && (errno == ENOTSOCK || errno == EBADF))) { GNUNET_socket_destroy (sock->sock); sock->sock = NULL; GNUNET_mutex_unlock (sock->destroylock); if (GNUNET_get_time () - select_start > TRIES_PER_AF * DELAY_PER_RETRY) ADVANCE (); /* spend enough time trying here */ else RETRY (); continue; } /* yayh! connected! */ break; } GNUNET_free (host); GNUNET_socket_set_blocking (sock->sock, GNUNET_YES); GNUNET_mutex_unlock (sock->destroylock);#undef ADVANCE#undef RETRY#undef TRIES_PER_AF#undef DELAY_PER_RETRY return GNUNET_OK;}/** * Write to a GNUnet TCP socket. Will also potentially complete the * sending of a previous non-blocking GNUNET_client_connection_write call. * * @param sock the socket to write to * @param buffer the buffer to write * @return GNUNET_OK if the write was sucessful, otherwise GNUNET_SYSERR. */intGNUNET_client_connection_write (struct GNUNET_ClientServerConnection *sock, const GNUNET_MessageHeader * buffer){ size_t size; size_t sent; int res; GNUNET_mutex_lock (sock->destroylock); GNUNET_mutex_lock (sock->writelock); if (GNUNET_SYSERR == GNUNET_client_connection_ensure_connected (sock)) { GNUNET_mutex_unlock (sock->writelock); GNUNET_mutex_unlock (sock->destroylock); return GNUNET_SYSERR; } GNUNET_mutex_unlock (sock->destroylock); GNUNET_GE_ASSERT (NULL, sock->sock != NULL); size = ntohs (buffer->size); res = GNUNET_socket_send (sock->sock, GNUNET_NC_COMPLETE_TRANSFER, buffer, size, &sent); if ((res != GNUNET_YES) || (sent != size)) { GNUNET_mutex_unlock (sock->writelock); GNUNET_client_connection_close_temporarily (sock); return GNUNET_SYSERR; } GNUNET_mutex_unlock (sock->writelock); return GNUNET_OK;}intGNUNET_client_connection_read (struct GNUNET_ClientServerConnection *sock, GNUNET_MessageHeader ** buffer){ int res; size_t pos; char *buf; unsigned short size; GNUNET_MessageReturnErrorMessage *rem; GNUNET_mutex_lock (sock->destroylock); GNUNET_mutex_lock (sock->readlock); if (GNUNET_OK != GNUNET_client_connection_ensure_connected (sock)) { GNUNET_mutex_unlock (sock->readlock); GNUNET_mutex_unlock (sock->destroylock); return GNUNET_SYSERR; } GNUNET_mutex_unlock (sock->destroylock); GNUNET_GE_ASSERT (NULL, sock->sock != NULL); while (1) { pos = 0; res = 0; if ((GNUNET_OK != GNUNET_socket_recv (sock->sock, GNUNET_NC_COMPLETE_TRANSFER, &size, sizeof (unsigned short), &pos)) || (pos != sizeof (unsigned short))) { GNUNET_mutex_unlock (sock->readlock); GNUNET_client_connection_close_temporarily (sock); return GNUNET_SYSERR; } size = ntohs (size); if (size < sizeof (GNUNET_MessageHeader)) { GNUNET_GE_BREAK (sock->ectx, 0); GNUNET_mutex_unlock (sock->readlock); GNUNET_client_connection_close_temporarily (sock); return GNUNET_SYSERR; /* invalid header */ } buf = GNUNET_malloc (size); if ((GNUNET_OK != GNUNET_socket_recv (sock->sock, GNUNET_NC_COMPLETE_TRANSFER, &buf[pos], size - pos, &pos)) || (pos + sizeof (unsigned short) != size)) { GNUNET_free (buf); GNUNET_mutex_unlock (sock->readlock); GNUNET_client_connection_close_temporarily (sock); return GNUNET_SYSERR; }#if DEBUG_TCPIO GNUNET_GE_LOG (sock->ectx, GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER, "Successfully received %d bytes from TCP socket.\n", size);#endif *buffer = (GNUNET_MessageHeader *) buf; (*buffer)->size = htons (size); if (ntohs ((*buffer)->type) != GNUNET_CS_PROTO_RETURN_ERROR) break; /* got actual message! */ rem = (GNUNET_MessageReturnErrorMessage *) * buffer; if (ntohs (rem->header.size) < sizeof (GNUNET_MessageReturnErrorMessage)) { GNUNET_GE_BREAK (sock->ectx, 0); GNUNET_mutex_unlock (sock->readlock); GNUNET_client_connection_close_temporarily (sock); GNUNET_free (buf); return GNUNET_SYSERR; } size = ntohs (rem->header.size) - sizeof (GNUNET_MessageReturnErrorMessage); GNUNET_GE_LOG (sock->ectx, ntohl (rem->kind), "%.*s", (int) size, &rem[1]); GNUNET_free (rem); } /* while (1) */ GNUNET_mutex_unlock (sock->readlock); return GNUNET_OK; /* success */}/** * Obtain a return value from a remote call from TCP. * * @param sock the TCP socket * @param ret the return value from TCP * @return GNUNET_SYSERR on error, GNUNET_OK if the return value was read * successfully */intGNUNET_client_connection_read_result (struct GNUNET_ClientServerConnection *sock, int *ret){ GNUNET_MessageReturnValue *rv; rv = NULL; if (GNUNET_SYSERR == GNUNET_client_connection_read (sock, (GNUNET_MessageHeader **) & rv)) return GNUNET_SYSERR; if ((ntohs (rv->header.size) != sizeof (GNUNET_MessageReturnValue)) || (ntohs (rv->header.type) != GNUNET_CS_PROTO_RETURN_VALUE)) { GNUNET_GE_LOG (sock->ectx, GNUNET_GE_WARNING | GNUNET_GE_DEVELOPER | GNUNET_GE_BULK, _ ("Reading result from gnunetd failed, reply invalid!\n")); GNUNET_free (rv); return GNUNET_SYSERR; } *ret = ntohl (rv->return_value); GNUNET_free (rv); return GNUNET_OK;}/** * Send a return value to the caller of a remote call via * TCP. * @param sock the TCP socket * @param ret the return value to send via TCP * @return GNUNET_SYSERR on error, GNUNET_OK if the return value was * send successfully */intGNUNET_client_connection_write_result (struct GNUNET_ClientServerConnection *sock, int ret){ GNUNET_MessageReturnValue rv; rv.header.size = htons (sizeof (GNUNET_MessageReturnValue)); rv.header.type = htons (GNUNET_CS_PROTO_RETURN_VALUE); rv.return_value = htonl (ret); return GNUNET_client_connection_write (sock, &rv.header);}/* end of tcpio.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -