⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_socket.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
	    ne_snprintf(sock->error, sizeof sock->error, 			_("SSL error: %s"), ERR_reason_error_string(err));	}	break;    default:	ne_snprintf(sock->error, sizeof sock->error, _("SSL error: %s"), 		    ERR_reason_error_string(ERR_get_error()));	break;    }    return ret;}/* Work around OpenSSL's use of 'int' rather than 'size_t', to prevent * accidentally passing a negative number, etc. */#define CAST2INT(n) (((n) > INT_MAX) ? INT_MAX : (n))static ssize_t read_ossl(ne_socket *sock, char *buffer, size_t len){    int ret;    ret = readable_ossl(sock, sock->rdtimeout);    if (ret) return ret;        ret = SSL_read(sock->ssl.ssl, buffer, CAST2INT(len));    if (ret <= 0)	ret = error_ossl(sock, ret);    return ret;}static ssize_t write_ossl(ne_socket *sock, const char *data, size_t len){    int ret, ilen = CAST2INT(len);    ret = SSL_write(sock->ssl.ssl, data, ilen);    /* ssl.h says SSL_MODE_ENABLE_PARTIAL_WRITE must be enabled to     * have SSL_write return < length...  so, SSL_write should never     * return < length. */    if (ret != ilen)	return error_ossl(sock, ret);    return 0;}static const struct iofns iofns_ossl = {    read_ossl,    write_ossl,    readable_ossl};#endif /* NEON_SSL */int ne_sock_fullwrite(ne_socket *sock, const char *data, size_t len){    return sock->ops->write(sock, data, len);}ssize_t ne_sock_readline(ne_socket *sock, char *buf, size_t buflen){    char *lf;    size_t len;        if ((lf = memchr(sock->bufpos, '\n', sock->bufavail)) == NULL	&& sock->bufavail < RDBUFSIZ) {	/* The buffered data does not contain a complete line: move it	 * to the beginning of the buffer. */	if (sock->bufavail)	    memmove(sock->buffer, sock->bufpos, sock->bufavail);	sock->bufpos = sock->buffer;		/* Loop filling the buffer whilst no newline is found in the data	 * buffered so far, and there is still buffer space available */ 	do {	    /* Read more data onto end of buffer. */	    ssize_t ret = sock->ops->read(sock, sock->buffer + sock->bufavail,					  RDBUFSIZ - sock->bufavail);	    if (ret < 0) return ret;	    sock->bufavail += ret;	} while ((lf = memchr(sock->buffer, '\n', sock->bufavail)) == NULL		 && sock->bufavail < RDBUFSIZ);    }    if (lf)	len = lf - sock->bufpos + 1;    else	len = buflen; /* fall into "line too long" error... */    if ((len + 1) > buflen) {	set_error(sock, _("Line too long"));	return NE_SOCK_ERROR;    }    memcpy(buf, sock->bufpos, len);    buf[len] = '\0';    /* consume the line from buffer: */    sock->bufavail -= len;    sock->bufpos += len;    return len;}ssize_t ne_sock_fullread(ne_socket *sock, char *buffer, size_t buflen) {    ssize_t len;    while (buflen > 0) {	len = ne_sock_read(sock, buffer, buflen);	if (len < 0) return len;	buflen -= len;	buffer += len;    }    return 0;}#ifndef INADDR_NONE#define INADDR_NONE ((unsigned long) -1)#endif#if !defined(USE_GETADDRINFO) && !defined(HAVE_DECL_H_ERRNO) && !defined(WIN32)/* Ancient versions of netdb.h don't export h_errno. */extern int h_errno;#endif/* This implemementation does not attempt to support IPv6 using * gethostbyname2 et al.  */ne_sock_addr *ne_addr_resolve(const char *hostname, int flags){    ne_sock_addr *addr = ne_calloc(sizeof *addr);#ifdef USE_GETADDRINFO    struct addrinfo hints = {0};    char *pnt;    hints.ai_socktype = SOCK_STREAM;    if (hostname[0] == '[' && ((pnt = strchr(hostname, ']')) != NULL)) {	char *hn = ne_strdup(hostname + 1);	hn[pnt - hostname - 1] = '\0';#ifdef AI_NUMERICHOST /* added in the RFC2553 API */	hints.ai_flags = AI_NUMERICHOST;#endif        hints.ai_family = AF_INET6;	addr->errnum = getaddrinfo(hn, NULL, &hints, &addr->result);	ne_free(hn);    } else {#ifdef USE_GAI_ADDRCONFIG /* added in the RFC3493 API */        hints.ai_flags = AI_ADDRCONFIG;        hints.ai_family = AF_UNSPEC;        addr->errnum = getaddrinfo(hostname, NULL, &hints, &addr->result);#else        hints.ai_family = ipv6_disabled ? AF_INET : AF_UNSPEC;	addr->errnum = getaddrinfo(hostname, NULL, &hints, &addr->result);#endif    }#else /* Use gethostbyname() */    unsigned long laddr;    struct hostent *hp;        laddr = inet_addr(hostname);    if (laddr == INADDR_NONE) {	hp = gethostbyname(hostname);	if (hp == NULL) {#ifdef WIN32	    addr->errnum = WSAGetLastError();#else            addr->errnum = h_errno;#endif	} else if (hp->h_length != sizeof(struct in_addr)) {	    /* fail gracefully if somebody set RES_USE_INET6 */	    addr->errnum = NO_RECOVERY;	} else {	    size_t n;	    /* count addresses */	    for (n = 0; hp->h_addr_list[n] != NULL; n++)		/* noop */;	    addr->count = n;	    addr->addrs = ne_malloc(n * sizeof *addr->addrs);	    for (n = 0; n < addr->count; n++)		memcpy(&addr->addrs[n], hp->h_addr_list[n], hp->h_length);	}    } else {	addr->addrs = ne_malloc(sizeof *addr->addrs);	addr->count = 1;	memcpy(addr->addrs, &laddr, sizeof *addr->addrs);    }#endif    return addr;}int ne_addr_result(const ne_sock_addr *addr){    return addr->errnum;}const ne_inet_addr *ne_addr_first(ne_sock_addr *addr){#ifdef USE_GETADDRINFO    addr->cursor = addr->result->ai_next;    return addr->result;#else    addr->cursor = 0;    return &addr->addrs[0];#endif}const ne_inet_addr *ne_addr_next(ne_sock_addr *addr){#ifdef USE_GETADDRINFO    struct addrinfo *ret = addr->cursor;    if (addr->cursor) addr->cursor = addr->cursor->ai_next;#else    struct in_addr *ret;    if (++addr->cursor < addr->count)	ret = &addr->addrs[addr->cursor];    else	ret = NULL;#endif    return ret;}char *ne_addr_error(const ne_sock_addr *addr, char *buf, size_t bufsiz){#ifdef WIN32    print_error(addr->errnum, buf, bufsiz);#else    const char *err;#ifdef USE_GETADDRINFO    /* override horrible generic "Name or service not known" error. */    if (addr->errnum == EAI_NONAME)	err = _("Host not found");    else	err = gai_strerror(addr->errnum);#elif defined(HAVE_HSTRERROR)    err = hstrerror(addr->errnum);#else    err = _("Host not found");#endif    ne_strnzcpy(buf, err, bufsiz);#endif /* WIN32 */    return buf;}char *ne_iaddr_print(const ne_inet_addr *ia, char *buf, size_t bufsiz){#ifdef USE_GETADDRINFO /* implies inet_ntop */    const char *ret;#ifdef AF_INET6    if (ia->ai_family == AF_INET6) {	struct sockaddr_in6 *in6 = SACAST(in6, ia->ai_addr);	ret = inet_ntop(AF_INET6, &in6->sin6_addr, buf, bufsiz);    } else#endif    if (ia->ai_family == AF_INET) {	struct sockaddr_in *in = SACAST(in, ia->ai_addr);	ret = inet_ntop(AF_INET, &in->sin_addr, buf, bufsiz);    } else	ret = NULL;    if (ret == NULL)	ne_strnzcpy(buf, "[IP address]", bufsiz);#else    ne_strnzcpy(buf, inet_ntoa(*ia), bufsiz);#endif    return buf;}void ne_addr_destroy(ne_sock_addr *addr){#ifdef USE_GETADDRINFO    if (addr->result)	freeaddrinfo(addr->result);#else    if (addr->addrs)	ne_free(addr->addrs);#endif    ne_free(addr);}/* Connect socket 'fd' to address 'addr' on given 'port': */static int raw_connect(int fd, const ne_inet_addr *addr, unsigned int port){#ifdef USE_GETADDRINFO#ifdef AF_INET6    /* fill in the _family field for AIX 4.3, which forgets to do so. */    if (addr->ai_family == AF_INET6) {	struct sockaddr_in6 in6;	memcpy(&in6, addr->ai_addr, sizeof in6);	in6.sin6_port = port;        in6.sin6_family = AF_INET6;	return connect(fd, (struct sockaddr *)&in6, sizeof in6);    } else#endif    if (addr->ai_family == AF_INET) {	struct sockaddr_in in;	memcpy(&in, addr->ai_addr, sizeof in);	in.sin_port = port;        in.sin_family = AF_INET;	return connect(fd, (struct sockaddr *)&in, sizeof in);    } else {	errno = EINVAL;	return -1;    }#else    struct sockaddr_in sa = {0};    sa.sin_family = AF_INET;    sa.sin_port = port;    sa.sin_addr = *addr;    return connect(fd, (struct sockaddr *)&sa, sizeof sa);#endif}ne_socket *ne_sock_create(void){    ne_socket *sock = ne_calloc(sizeof *sock);    sock->rdtimeout = SOCKET_READ_TIMEOUT;    sock->bufpos = sock->buffer;    sock->ops = &iofns_raw;    sock->fd = -1;    return sock;}int ne_sock_connect(ne_socket *sock,                    const ne_inet_addr *addr, unsigned int port){    int fd;#ifdef USE_GETADDRINFO    /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo     * implementations do not set ai_socktype, e.g. RHL6.2. */    fd = socket(addr->ai_family, SOCK_STREAM, addr->ai_protocol);#else    fd = socket(AF_INET, SOCK_STREAM, 0);#endif    if (fd < 0) {        set_strerror(sock, ne_errno);	return -1;    }    #if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) && defined(IPPROTO_TCP)    { /* Disable the Nagle algorithm; better to add write buffering       * instead of doing this. */        int flag = 1;        setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);    }#endif    if (raw_connect(fd, addr, ntohs(port))) {        set_strerror(sock, ne_errno);	ne_close(fd);	return -1;    }    sock->fd = fd;    return 0;}ne_inet_addr *ne_iaddr_make(ne_iaddr_type type, const unsigned char *raw){    ne_inet_addr *ia;#if !defined(AF_INET6) || !defined(USE_GETADDRINFO)    /* fail if IPv6 address is given if IPv6 is not supported. */    if (type == ne_iaddr_ipv6)	return NULL;#endif    ia = ne_calloc(sizeof *ia);#ifdef USE_GETADDRINFO    /* ai_protocol and ai_socktype aren't used by raw_connect so     * ignore them here. (for now) */    if (type == ne_iaddr_ipv4) {	struct sockaddr_in *in4 = ne_calloc(sizeof *in4);	ia->ai_family = AF_INET;	ia->ai_addr = (struct sockaddr *)in4;	ia->ai_addrlen = sizeof *in4;	in4->sin_family = AF_INET;	memcpy(&in4->sin_addr.s_addr, raw, sizeof in4->sin_addr.s_addr);    }#ifdef AF_INET6    else {	struct sockaddr_in6 *in6 = ne_calloc(sizeof *in6);	ia->ai_family = AF_INET6;	ia->ai_addr = (struct sockaddr *)in6;	ia->ai_addrlen = sizeof *in6;	in6->sin6_family = AF_INET6;	memcpy(&in6->sin6_addr, raw, sizeof in6->sin6_addr.s6_addr);    }#endif#else /* !USE_GETADDRINFO */    memcpy(&ia->s_addr, raw, sizeof ia->s_addr);#endif        return ia;}int ne_iaddr_cmp(const ne_inet_addr *i1, const ne_inet_addr *i2){#ifdef USE_GETADDRINFO    if (i1->ai_family != i2->ai_family)	return i2->ai_family - i1->ai_family;    if (i1->ai_family == AF_INET) {	struct sockaddr_in *in1 = SACAST(in, i1->ai_addr), 	    *in2 = SACAST(in, i2->ai_addr);	return memcmp(&in1->sin_addr.s_addr, &in2->sin_addr.s_addr, 		      sizeof in1->sin_addr.s_addr);    } else if (i1->ai_family == AF_INET6) {	struct sockaddr_in6 *in1 = SACAST(in6, i1->ai_addr), 	    *in2 = SACAST(in6, i2->ai_addr);	return memcmp(in1->sin6_addr.s6_addr, in2->sin6_addr.s6_addr,		      sizeof in1->sin6_addr.s6_addr);    } else	return -1;#else    return memcmp(&i1->s_addr, &i2->s_addr, sizeof i1->s_addr);#endif}void ne_iaddr_free(ne_inet_addr *addr){#ifdef USE_GETADDRINFO    ne_free(addr->ai_addr);#endif    ne_free(addr);}int ne_sock_accept(ne_socket *sock, int listener) {    int fd = accept(listener, NULL, NULL);    if (fd < 0)        return -1;    sock->fd = fd;    return 0;}int ne_sock_fd(const ne_socket *sock){    return sock->fd;}void ne_sock_read_timeout(ne_socket *sock, int timeout){    sock->rdtimeout = timeout;}#ifdef NEON_SSLvoid ne_sock_switch_ssl(ne_socket *sock, void *ssl){    sock->ssl.ssl = ssl;    sock->ops = &iofns_ossl;}int ne_sock_connect_ssl(ne_socket *sock, ne_ssl_context *ctx){    SSL *ssl;    int ret;    if (seed_ssl_prng()) {	set_error(sock, _("SSL disabled due to lack of entropy"));	return NE_SOCK_ERROR;    }    sock->ssl.ssl = ssl = SSL_new(ctx->ctx);    if (!ssl) {	set_error(sock, _("Could not create SSL structure"));	return NE_SOCK_ERROR;    }        SSL_set_app_data(ssl, ctx);    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);    SSL_set_fd(ssl, sock->fd);    sock->ops = &iofns_ossl;        if (ctx->sess)	SSL_set_session(ssl, ctx->sess);    ret = SSL_connect(ssl);    if (ret != 1) {	error_ossl(sock, ret);	SSL_free(ssl);	sock->ssl.ssl = NULL;	return NE_SOCK_ERROR;    }    return 0;}ne_ssl_socket *ne_sock_sslsock(ne_socket *sock){    return &sock->ssl;}#endifconst char *ne_sock_error(const ne_socket *sock){    return sock->error;}/* Closes given ne_socket */int ne_sock_close(ne_socket *sock){    int ret;#ifdef NEON_SSL    if (sock->ssl.ssl) {	SSL_shutdown(sock->ssl.ssl);	SSL_free(sock->ssl.ssl);    }#endif    if (sock->fd < 0)        ret = 0;    else        ret = ne_close(sock->fd);    ne_free(sock);    return ret;}/* Returns HOST byte order port of given name */int ne_service_lookup(const char *name){    struct servent *ent;    ent = getservbyname(name, "tcp");    if (ent)	return ntohs(ent->s_port);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -