📄 fixmesimplenetwork.c
字号:
/* * * * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */#include <stdio.h>#include <string.h>#include <pcsl_network.h>#include <donuts.h>#define PORT_ECHO 7#define PORT_DISCARD 9#define PORT_DAYTIME 13#define PORT_CHARGEN 19#define PORT_NEWS 144static char msgbuf[100];static char testhost[] = "host.domain";static unsigned char testaddr[4] = { 10, 5, 32, 19 }; /* address of host.domain */static char testString[] = "When the comments and the code differ,\n" "both are probably wrong.\n" "-- Dennis Ritchie\n";static int utilGetHostByName(char *, unsigned char *, int, int *);static int utilOpen(void **, unsigned char *, unsigned int);static int utilRead(void *, unsigned char *, int);static int utilWrite(void *, unsigned char *, int);static int utilClose(void *);/** * Internal utility to lookup an address for a hostname, synchronously. * * @param hostname the hostname to look up * @param addr_return the location to which to write the address * @param len_return the address length * * @return 1 if successful, 0 if failed */static intutilGetHostByName( char *hostname, unsigned char *addr_return, int maxLen, int *len_return){ int status; int len; void *handle; void *context; status = pcsl_network_gethostbyname_start( hostname, addr_return, maxLen, len_return, &handle, &context); if (status == PCSL_NET_SUCCESS) { return 1; } else { return 0; } /* IMPL NOTE: need to handle asynchronous gethostbyname */}/** * Internal utility to open a socket, synchronously. * * @param handle_return receives the open handle, if successful * @param addr pointer to base of ip address * @param port the port number to open * * @return 1 if successful, 0 if failed */static intutilOpen( void **handle_return, unsigned char *addr, unsigned int port){ int status; char *exception; void *handle; void *context; status = pcsl_socket_open_start( addr, port, &handle, &context); if (status == PCSL_NET_SUCCESS) { *handle_return = handle; return 1; } if (status == PCSL_NET_WOULDBLOCK) { if (wait_on_handle(handle, 0)) { status = pcsl_socket_open_finish(handle, context); if (status == PCSL_NET_SUCCESS) { *handle_return = handle; return 1; } } utilClose(handle); } return 0;}/** * Internal utility to read from a socket, synchronously. * * @param handle the open socket handle * @param buf the buffer into which to read * @param len the number of bytes to attempt to read * * @return -1 if error, otherwise the number of bytes actually read */static intutilRead( void *handle, unsigned char *buf, int len){ int status; int nread; void *context; status = pcsl_socket_read_start( handle, buf, len, &nread, &context); if (status == PCSL_NET_SUCCESS) { return nread; } if (status == PCSL_NET_WOULDBLOCK) { if (wait_on_handle(handle, 1)) { status = pcsl_socket_read_finish(handle, buf, len, &nread, context); if (status == PCSL_NET_SUCCESS) { return nread; } } } return -1;}/** * Internal utility to write to a socket, synchronously. * * @param handle the open socket handle * @param buf the buffer from which to write * @param len the number of bytes to attempt to write * * @return -1 if error, otherwise the number of bytes actually written */static intutilWrite( void *handle, unsigned char *buf, int len){ int status; int nwritten; void *context; status = pcsl_socket_write_start( handle, buf, len, &nwritten, &context); if (status == PCSL_NET_SUCCESS) { return nwritten; } if (status == PCSL_NET_WOULDBLOCK) { if (wait_on_handle(handle, 0)) { status = pcsl_socket_write_finish(handle, buf, len, &nwritten, context); if (status == PCSL_NET_SUCCESS) { return nwritten; } } } return -1;}/** * Internal utility to close a socket synchronously. * * @param handle the socket to close * * @return 1 if successful, 0 if failure */static intutilClose(void *handle){ int status; void *context; status = pcsl_socket_close_start(handle, &context); if (status == PCSL_NET_SUCCESS) { return 1; } if (status == PCSL_NET_WOULDBLOCK) { if (wait_on_handle(handle, 1)) { status = pcsl_socket_close_finish(handle, context); if (status == PCSL_NET_SUCCESS) { return 1; } } } return 0;} /* * The tests. *//** * Test of opening a socket. */voidtestSocketOpen() { int status; char *exception; void *handle; void *context; status = pcsl_socket_open_start( testaddr, PORT_DISCARD, &handle, &context); switch (status) { case PCSL_NET_SUCCESS: assertTrue("open successful", 1); break; case PCSL_NET_WOULDBLOCK: if (wait_on_handle(handle, 0)) { status = pcsl_socket_open_finish(handle, context); if (status == PCSL_NET_SUCCESS) { assertTrue("open successful after waiting", 1); } else { sprintf(msgbuf, "open_finish => %d\n", status); assertTrue(msgbuf, 0); } } else { assertTrue("wait failed", 0); } break; default: sprintf(msgbuf, "open_start => %d\n", status); assertTrue(msgbuf, 0); break; } (void)utilClose(handle);}/** * Test opening a socket to a port on which no one should be listening * (NeWS). */voidtestSocketOpenFail() { int status; void *handle; status = utilOpen(&handle, testaddr, PORT_NEWS); assertTrue("open succeeded unexpectedly", status == 0);}/** * Test of reading from a socket. */voidtestSocketRead() { int status; void *handle; void *context; char buf[100]; int nread; status = utilOpen(&handle, testaddr, PORT_DAYTIME); assertTrue("open failed", status); while (1) { status = utilRead(handle, buf, sizeof(buf)-1); assertTrue("read failed", status != -1); if (status == 0) { break; } buf[status] = '\0'; printf("read => '%s'\n", buf); } puts("read => EOF"); (void)utilClose(handle);}/** * Test of writing to a socket. */voidtestSocketWrite() { int status; void *handle; void *context; int ntowrite; int nwritten; char *buf = testString; status = utilOpen(&handle, testaddr, PORT_DISCARD); assertTrue("open failed", status); ntowrite = sizeof(*buf); do { status = utilWrite(handle, buf, ntowrite); assertTrue("write failed", status > 0); ntowrite -= status; buf += status; } while (ntowrite > 0); (void)utilClose(handle);}/** * Test writing to and reading from the same socket. */voidtestSocketReadWrite() { int status; void *handle; void *context; int ntowrite; int nwritten; char *buf = testString; char inbuf[100]; status = utilOpen(&handle, testaddr, PORT_ECHO); assertTrue("open failed", status); ntowrite = strlen(buf); do { status = utilWrite(handle, buf, ntowrite); assertTrue("write failed", status > 0); ntowrite -= status; buf += status; } while (ntowrite > 0); status = pcsl_socket_shutdown_output(handle); assertTrue("shutdown failed", status == PCSL_NET_SUCCESS); while (1) { status = utilRead(handle, inbuf, sizeof(inbuf)-1); assertTrue("read failed", status != -1); if (status == 0) { break; } inbuf[status] = '\0'; printf("read => '%s'\n", inbuf); } (void)utilClose(handle);}/** * Test hostname lookup. */voidtestGetHostByName() { unsigned char addr[4]; int len; int status; /* test of success */ status = utilGetHostByName(testhost, addr, sizeof(addr), &len); assertTrue("gethostbyname failed", status); assertTrue("wrong length", len == 4); printf("address of %s is %d.%d.%d.%d\n", testhost, addr[0], addr[1], addr[2], addr[3]); /* failure - unknown host */ status = utilGetHostByName( "foobar.xyzzy.example.com", addr, sizeof(addr), &len); assertTrue("gethostbyname didn't fail", status == 0); /* failure - buffer too short */ status = utilGetHostByName( testhost, addr, sizeof(addr)-1, &len); assertTrue("gethostbyname didn't fail", status == 0);}/** * Test address to string conversion. */voidtestAddrToString() { unsigned char addr[4]; unsigned short* result; int resultLen; int status; int i; /* test of success */ addr[0] = 80; addr[1] = 80; addr[2] = 80; addr[3] = 80; status = pcsl_network_addrToString(addr, &result, &resultLen); assertTrue("gethostbyname failed", PCSL_NET_SUCCESS == status); if (PCSL_NET_SUCCESS != status) { return; } printf("Result of addr \"80.80.80.80\" = "); for (i = 0; i < resultLen, i++) { putchar(result[i]); } putchar('\n'); pcsl_mem_free(result);}/** * Test retrieval of the number of bytes available. */voidtestAvailable(){ int status; void *handle; int avail; int ii; status = utilOpen(&handle, testaddr, PORT_CHARGEN); assertTrue("open failed", status); wait_on_handle(handle, 1); for (ii = 0; ii < 5; ii++) { status = pcsl_socket_available(handle, &avail); assertTrue("available failed", status == PCSL_NET_SUCCESS); printf("avail = %d\n", avail); usleep(1000); } (void)utilClose(handle);}/** * Main entry point for donuts. */voidtestSimpleNetwork_runTests(){ puts("===== testSocketOpen ====="); testSocketOpen(); puts("===== testSocketOpenFail ====="); testSocketOpenFail(); puts("===== testSocketRead ====="); testSocketRead(); puts("===== testSocketWrite ====="); testSocketWrite(); puts("===== testSocketReadWrite ====="); testSocketReadWrite(); puts("===== testGetHostByName ====="); testGetHostByName(); puts("===== testAddrToString ====="); testAddrToString(); puts("===== testAvailable ====="); testAvailable(); puts("===== testSimpleNetwork finished =====");}/* ***** BSD-specific stuff ********************************************** */#include <sys/types.h>intwait_on_handle(void *handle, int reading){ int fd = (int)handle; fd_set rset; fd_set wset; fd_set eset; int r; FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset); if (reading) { FD_SET(fd, &rset); } else { FD_SET(fd, &wset); } FD_SET(fd, &eset); r = select(fd+1, &rset, &wset, &eset, NULL);/* printf("select=%d r=%d w=%d e=%d\n", r, FD_ISSET(fd, &rset), FD_ISSET(fd, &wset), FD_ISSET(fd, &eset));*/ if (reading && FD_ISSET(fd, &rset)) { return 1; } if (!reading && FD_ISSET(fd, &wset)) { return 1; } if (FD_ISSET(fd, &eset)) { return 0; } printf("unexpected return from select!\n"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -