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

📄 socket.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Socket handling tests   Copyright (C) 2002-2004, Joe Orton <joe@manyfish.co.uk>   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.     This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.     You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* This module can be compiled with -DSOCKET_SSL enabled, to run all * the tests over an SSL connection. */#include "config.h"#include <sys/types.h>#include <sys/socket.h> /* for AF_INET6 */#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#include <time.h> /* for time() */#include "ne_socket.h"#include "ne_utils.h"#include "ne_alloc.h"#include "child.h"#include "tests.h"#include "utils.h"#ifdef SOCKET_SSL#include <openssl/err.h>#include <openssl/ssl.h>#include "ne_ssl.h"SSL_CTX *server_ctx;ne_ssl_context *client_ctx;#endifstatic ne_sock_addr *localhost;static char buffer[BUFSIZ];#if defined(AF_INET6) && defined(USE_GETADDRINFO)#define TEST_IPV6#endif/* tests for doing init/finish multiple times. */static int multi_init(void){    int res1 = ne_sock_init(), res2 = ne_sock_init();        ONV(res1 != res2, ("cached init result changed from %d to %d",                       res1, res2));        ne_sock_exit();    res1 = ne_sock_init();        ONV(res1 != res2, ("re-init after exit gave %d not %d",                       res1, res2));        res2 = ne_sock_init();        ONV(res1 != res2, ("second time, cached init result changed from %d to %d",                       res1, res2));        return OK;}static ne_socket *do_connect(ne_sock_addr *addr, unsigned int port){    ne_socket *sock = ne_sock_create();    const ne_inet_addr *ia;    if (!sock) return NULL;    for (ia = ne_addr_first(addr); ia; ia = ne_addr_next(addr)) {	if (ne_sock_connect(sock, ia, port) == 0)            return sock;    }        ne_sock_close(sock);    return NULL;}#ifdef SOCKET_SSL/* FIXME: largely cut'n'pasted from ssl.c. */static int init_ssl(void){    char *server_key;    ne_ssl_certificate *cert;     /* take srcdir as argv[1]. */    if (test_argc > 1) {	server_key = ne_concat(test_argv[1], "/server.key", NULL);    } else {	server_key = "server.key";    }    ONN("sock_init failed.\n", ne_sock_init());    server_ctx = SSL_CTX_new(SSLv23_server_method());    ONN("SSL_CTX_new failed", server_ctx == NULL);    ONN("failed to load private key",	!SSL_CTX_use_PrivateKey_file(server_ctx, server_key, 				     SSL_FILETYPE_PEM));    ONN("failed to load certificate",	!SSL_CTX_use_certificate_file(server_ctx, "server.cert", 				      SSL_FILETYPE_PEM));    client_ctx = ne_ssl_context_create();    ONN("SSL_CTX_new failed for client", client_ctx == NULL);        cert = ne_ssl_cert_read("ca/cert.pem");    ONN("could not load ca/cert.pem", cert == NULL);    ne_ssl_ctx_trustcert(client_ctx, cert);    return OK;}#endifstatic int resolve(void){    char buf[256];    localhost = ne_addr_resolve("localhost", 0);    ONV(ne_addr_result(localhost),	("could not resolve `localhost': %s", 	 ne_addr_error(localhost, buf, sizeof buf)));    /* and again for child.c */    return lookup_localhost();}static int serve_close(ne_socket *sock, void *ud){    return 0;}#ifdef SOCKET_SSLstruct serve_pair {    server_fn fn;    void *userdata;};static int wrap_serve(ne_socket *sock, void *ud){    struct serve_pair *pair = ud;    int fd = ne_sock_fd(sock), ret;    SSL *ssl = SSL_new(server_ctx);    BIO *bio = BIO_new_socket(fd, BIO_NOCLOSE);    ONN("SSL_new failed", ssl == NULL);    SSL_set_bio(ssl, bio, bio);#define ERROR_SSL_STRING (ERR_reason_error_string(ERR_get_error()))    NE_DEBUG(NE_DBG_SOCKET, "Doing SSL accept:\n");    ret = SSL_accept(ssl);    if (ret != 1) {	NE_DEBUG(NE_DBG_SOCKET, "SSL_accept failed: %s\n", ERROR_SSL_STRING);	return 1;    }        NE_DEBUG(NE_DBG_SOCKET, "SSL accept okay.\n");    ne_sock_switch_ssl(sock, ssl);    return pair->fn(sock, pair->userdata);}static int begin(ne_socket **sock, server_fn fn, void *ud){    struct serve_pair pair;    pair.fn = fn;    pair.userdata = ud;    CALL(spawn_server(7777, wrap_serve, &pair));    *sock = do_connect(localhost, 7777);    ONN("could not connect to localhost:7777", *sock == NULL);    ONV(ne_sock_connect_ssl(*sock, client_ctx),	("SSL negotation failed: %s", ne_sock_error(*sock)));    return OK;}#else/* non-SSL begin() function. */static int begin(ne_socket **sock, server_fn fn, void *ud){    CALL(spawn_server(7777, fn, ud));    *sock = do_connect(localhost, 7777);    ONN("could not connect to localhost:7777", *sock == NULL);    return OK;}#endifstatic int resolve_numeric(void){    ne_sock_addr *addr = ne_addr_resolve("127.0.0.1", 0);    ONV(ne_addr_result(addr),	("failed to resolve 127.0.0.1: %s",	 ne_addr_error(addr, buffer, sizeof buffer)));    ONN("ne_addr_first returned NULL", ne_addr_first(addr) == NULL);    ONN("ne_iaddr_print didn't return buffer", 	ne_iaddr_print(ne_addr_first(addr), buffer, sizeof buffer) != buffer);    ONV(strcmp(buffer, "127.0.0.1"), ("ntop gave `%s' not 127.0.0.1", buffer));    ne_addr_destroy(addr);    return OK;}#if 0static int resolve_ipv6(void){    char err[256];    ne_sock_addr *addr = ne_addr_resolve("[::1]", 0);    ONV(ne_addr_result(addr),	("could not resolve `[::1]': %s",	 ne_addr_error(addr, err, sizeof err)));    ne_addr_destroy(addr);    return OK;}#endifstatic const unsigned char raw_127[4] = "\x7f\0\0\01", /* 127.0.0.1 */raw6_nuls[16] = /* :: */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";#ifdef TEST_IPV6static const unsigned char raw6_cafe[16] = /* feed::cafe */ "\xfe\xed\0\0\0\0\0\0\0\0\0\0\0\0\xca\xfe",raw6_babe[16] = /* cafe:babe:: */ "\xca\xfe\xba\xbe\0\0\0\0\0\0\0\0\0\0\0\0";#endifstatic int addr_make_v4(void){    ne_inet_addr *ia;    char pr[50];        ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);    ONN("ne_iaddr_make returned NULL", ia == NULL);    ne_iaddr_print(ia, pr, sizeof pr);    ONV(strcmp(pr, "127.0.0.1"), ("address was %s not 127.0.0.1", pr));    ne_iaddr_free(ia);    return OK;}static int addr_make_v6(void){#ifdef TEST_IPV6       struct {	const unsigned char *addr;	const char *rep;    } as[] = {	{ raw6_cafe, "feed::cafe" },	{ raw6_babe, "cafe:babe::" },	{ raw6_nuls, "::" },	{ NULL, NULL }    };    int n;        for (n = 0; as[n].rep != NULL; n++) {	ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv6, as[n].addr);	char pr[128];	ONV(ia == NULL, ("could not make address for %d", n));	ne_iaddr_print(ia, pr, sizeof pr);	ONV(strcmp(pr, as[n].rep), 	    ("address %d was '%s' not '%s'", n, pr, as[n].rep));		ne_iaddr_free(ia);    }    return OK;#else    /* should fail when lacking IPv6 support. */    ne_inet_addr *ia = ne_iaddr_make(ne_iaddr_ipv6, raw6_nuls);    ONN("ne_iaddr_make did not return NULL", ia != NULL);#endif    return OK;}static int addr_compare(void){    ne_inet_addr *ia1, *ia2;    int ret;    ia1 = ne_iaddr_make(ne_iaddr_ipv4, raw_127);    ia2 = ne_iaddr_make(ne_iaddr_ipv4, raw_127);    ONN("addr_make returned NULL", !ia1 || !ia2);    ret = ne_iaddr_cmp(ia1, ia2);    ONV(ret != 0, ("comparison of equal IPv4 addresses was %d", ret));    ne_iaddr_free(ia2);    ia2 = ne_iaddr_make(ne_iaddr_ipv4, "abcd");    ret = ne_iaddr_cmp(ia1, ia2);    ONN("comparison of unequal IPv4 addresses was zero", ret == 0);    #ifdef TEST_IPV6    ne_iaddr_free(ia2);    ia2 = ne_iaddr_make(ne_iaddr_ipv6, "feed::1");    ret = ne_iaddr_cmp(ia1, ia2);    ONN("comparison of IPv4 and IPv6 addresses was zero", ret == 0);    ne_iaddr_free(ia1);    ia1 = ne_iaddr_make(ne_iaddr_ipv4, "feed::1");    ret = ne_iaddr_cmp(ia1, ia2);    ONN("comparison of equal IPv6 addresses was zero", ret == 0);#endif        ne_iaddr_free(ia1);    ne_iaddr_free(ia2);    return OK;}static int just_connect(void){    ne_socket *sock;        CALL(begin(&sock, serve_close, NULL));    ne_sock_close(sock);    return await_server();}/* Connect to an address crafted using ne_iaddr_make rather than from * the resolver. */static int addr_connect(void){    ne_socket *sock = ne_sock_create();    ne_inet_addr *ia;    ia = ne_iaddr_make(ne_iaddr_ipv4, raw_127);    ONN("ne_iaddr_make returned NULL", ia == NULL);        CALL(spawn_server(7777, serve_close, NULL));    ONN("could not connect", ne_sock_connect(sock, ia, 7777));    ne_sock_close(sock);    CALL(await_server());    ne_iaddr_free(ia);    return OK;}/* Exect a read() to return EOF */static int expect_close(ne_socket *sock){    ssize_t n = ne_sock_read(sock, buffer, 1);    ONV(n > 0, ("read got %" NE_FMT_SSIZE_T "bytes not closure", n));    ONV(n < 0 && n != NE_SOCK_CLOSED,	("read got error not closure: `%s'", ne_sock_error(sock)));    return OK;}static int good_close(ne_socket *sock){    NE_DEBUG(NE_DBG_SOCKET, "Socket error was %s\n", ne_sock_error(sock));    ONN("close failed", ne_sock_close(sock));    return OK;    }/* Finish a test, closing socket and rejoining child. If eof is non-zero, * expects to read EOF from the socket before closing. */static int finish(ne_socket *sock, int eof){    if (eof)	CALL(expect_close(sock));    CALL(good_close(sock));    return await_server();}/* Exect a ne_sock_peek() to return EOF */static int expect_peek_close(ne_socket *sock){    ssize_t n = ne_sock_read(sock, buffer, 1);    ONV(n != NE_SOCK_CLOSED, ("peek gave %" NE_FMT_SSIZE_T " not closure", n));    return OK;}/* Test that just does a connect then a close. */static int read_close(void){    ne_socket *sock;    CALL(begin(&sock, serve_close, NULL));    CALL(expect_close(sock));        ONN("close failed", ne_sock_close(sock));    return await_server();}/* Test that just does a connect then a close (but gets the close via * ne_sock_peek). */static int peek_close(void){    ne_socket *sock;    CALL(begin(&sock, serve_close, NULL));    CALL(expect_peek_close(sock));        ONN("close failed", ne_sock_close(sock));    return await_server();}/* Don't change this string. */#define STR "Hello, World."/* do a sock_peek() on sock for 'len' bytes, and expect 'str'. */static int peek_expect(ne_socket *sock, const char *str, size_t len){    ssize_t ret = ne_sock_peek(sock, buffer, len);    ONV((ssize_t)len != ret, 	("peek got %" NE_FMT_SSIZE_T " bytes not %" NE_FMT_SIZE_T, ret, len));    ONV(memcmp(str, buffer, len),	("peek mismatch: `%.*s' not `%.*s'", 	 (int)len, buffer, (int)len, str));        return OK;}/* do a sock_read() on sock for 'len' bytes, and expect 'str'. */static int read_expect(ne_socket *sock, const char *str, size_t len){    ssize_t ret = ne_sock_read(sock, buffer, len);    ONV((ssize_t)len != ret,	("peek got %" NE_FMT_SSIZE_T " bytes not %" NE_FMT_SIZE_T, ret, len));    ONV(memcmp(str, buffer, len),	("read mismatch: `%.*s' not `%.*s'", 	 (int)len, buffer, (int)len, str));        return OK;}/* Declare a struct string */#define DECL(var,str) struct string var = { str, 0 }; var.len = strlen(str)/* Test a simple read. */static int single_read(void){    ne_socket *sock;    DECL(hello, STR);

⌨️ 快捷键说明

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