1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

use libco instead of state-thread(st), still have some bug

This commit is contained in:
xiaozhihong 2020-02-16 21:07:54 +08:00
parent 51d6c367f5
commit 7c8a35aea9
88 changed files with 4836 additions and 19273 deletions

View file

@ -1,115 +0,0 @@
#
# Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of Silicon Graphics, Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##########################
# Supported OSes:
#
# AIX
# FREEBSD
# HPUX
# HPUX_64
# IRIX
# IRIX_64
# LINUX
# LINUX_IA64
# NETBSD
# OPENBSD
# OSF1
# SOLARIS
# SOLARIS_64
##########################
CC = cc
SHELL = /bin/sh
ECHO = /bin/echo
DEPTH = ..
BUILD =
TARGETDIR =
DEFINES =
CFLAGS =
OTHER_FLAGS =
OBJDIR = $(DEPTH)/$(TARGETDIR)
INCDIR = $(DEPTH)/$(TARGETDIR)
LIBST = $(OBJDIR)/libst.a
HEADER = $(INCDIR)/st.h
LIBRESOLV =
EXTRALIBS =
ifeq ($(OS),)
EXAMPLES = unknown
else
EXAMPLES = $(OBJDIR)/lookupdns $(OBJDIR)/proxy $(OBJDIR)/server
endif
##########################
# Platform section.
#
ifeq (DARWIN, $(findstring DARWIN, $(OS)))
LIBRESOLV = -lresolv
endif
ifeq (LINUX, $(findstring LINUX, $(OS)))
LIBRESOLV = -lresolv
endif
ifeq (SOLARIS, $(findstring SOLARIS, $(OS)))
LIBRESOLV = -lresolv
EXTRALIBS = -lsocket -lnsl
endif
#
# End of platform section.
##########################
all: $(EXAMPLES)
$(OBJDIR)/lookupdns: lookupdns.c $(OBJDIR)/res.o $(LIBST) $(HEADER)
$(CC) $(CFLAGS) -I$(INCDIR) lookupdns.c $(OBJDIR)/res.o $(LIBST) $(LIBRESOLV) $(EXTRALIBS) -o $@
$(OBJDIR)/proxy: proxy.c $(LIBST) $(HEADER)
$(CC) $(CFLAGS) -I$(INCDIR) proxy.c $(LIBST) $(EXTRALIBS) -o $@
$(OBJDIR)/server: server.c $(OBJDIR)/error.o $(LIBST) $(HEADER)
$(CC) $(CFLAGS) -I$(INCDIR) server.c $(OBJDIR)/error.o $(LIBST) $(EXTRALIBS) -o $@
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@
.DEFAULT:
@cd $(DEPTH); $(MAKE) $@

View file

@ -1,98 +0,0 @@
Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
All Rights Reserved.
This directory contains three example programs.
---------------------------------------------------------------------------
PROGRAM
lookupdns
FILES
lookupdns.c
res.c
USAGE
lookupdns <hostname1> [<hostname2>] ...
DESCRIPTION
This program performs asynchronous DNS host name resolution and reports
IP address for each <hostname> specified as a command line argument.
One ST thread is created for each host name. All threads do host name
resolution concurrently.
---------------------------------------------------------------------------
PROGRAM
proxy
FILES
proxy.c
USAGE
proxy -l <local_addr> -r <remote_addr> [-p <num_processes>] [-S]
-l <local_addr> bind to local address specified as [<host>]:<port>
-r <remote_addr> connect to remote address specified as <host>:<port>
-p <num_processes> create specified number of processes
-S serialize accept() calls from different processes
on the same listening socket (if needed).
DESCRIPTION
This program acts as a generic gateway. It listens for connections to a
local address. Upon accepting a client connection, it connects to the
specified remote address and then just pumps the data through without any
modification.
---------------------------------------------------------------------------
PROGRAM
server
FILES
server.c
error.c
USAGE
server -l <log_directory> [<options>]
-l <log_directory> open all log files in specified directory.
Possible options:
-b <host>:<port> bind to specified address (multiple addresses
are permitted)
-p <num_processes> create specified number of processes
-t <min_thr>:<max_thr> specify thread limits per listening socket
across all processes
-u <user> change server's user id to specified value
-q <backlog> set max length of pending connections queue
-a enable access logging
-i run in interactive mode (useful for debugging)
-S serialize accept() calls from different processes
on the same listening socket (if needed).
DESCRIPTION
This program is a general server example. It accepts a client connection
and outputs a short HTML page. It can be easily adapted to provide
other services.
---------------------------------------------------------------------------

View file

@ -1,168 +0,0 @@
/*
* Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Silicon Graphics, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "st.h"
/*
* Simple error reporting functions.
* Suggested in W. Richard Stevens' "Advanced Programming in UNIX
* Environment".
*/
#define MAXLINE 4096 /* max line length */
static void err_doit(int, int, const char *, va_list);
/*
* Nonfatal error related to a system call.
* Print a message and return.
*/
void err_sys_report(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(fd, 1, fmt, ap);
va_end(ap);
}
/*
* Fatal error related to a system call.
* Print a message and terminate.
*/
void err_sys_quit(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(fd, 1, fmt, ap);
va_end(ap);
exit(1);
}
/*
* Fatal error related to a system call.
* Print a message, dump core, and terminate.
*/
void err_sys_dump(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(fd, 1, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(1); /* shouldn't get here */
}
/*
* Nonfatal error unrelated to a system call.
* Print a message and return.
*/
void err_report(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(fd, 0, fmt, ap);
va_end(ap);
}
/*
* Fatal error unrelated to a system call.
* Print a message and terminate.
*/
void err_quit(int fd, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(fd, 0, fmt, ap);
va_end(ap);
exit(1);
}
/*
* Return a pointer to a string containing current time.
*/
char *err_tstamp(void)
{
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
static char str[32];
static time_t lastt = 0;
struct tm *tmp;
time_t currt = st_time();
if (currt == lastt)
return str;
tmp = localtime(&currt);
sprintf(str, "[%02d/%s/%d:%02d:%02d:%02d] ", tmp->tm_mday,
months[tmp->tm_mon], 1900 + tmp->tm_year, tmp->tm_hour,
tmp->tm_min, tmp->tm_sec);
lastt = currt;
return str;
}
/*
* Print a message and return to caller.
* Caller specifies "errnoflag".
*/
static void err_doit(int fd, int errnoflag, const char *fmt, va_list ap)
{
int errno_save;
char buf[MAXLINE];
errno_save = errno; /* value caller might want printed */
strcpy(buf, err_tstamp()); /* prepend a message with time stamp */
vsprintf(buf + strlen(buf), fmt, ap);
if (errnoflag)
sprintf(buf + strlen(buf), ": %s\n", strerror(errno_save));
else
strcat(buf, "\n");
write(fd, buf, strlen(buf));
errno = errno_save;
}

View file

@ -1,103 +0,0 @@
/*
* Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Silicon Graphics, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "st.h"
#if !defined(NETDB_INTERNAL) && defined(h_NETDB_INTERNAL)
#define NETDB_INTERNAL h_NETDB_INTERNAL
#endif
/* Resolution timeout (in microseconds) */
#define TIMEOUT (2*1000000LL)
/* External function defined in the res.c file */
int dns_getaddr(const char *host, struct in_addr *addr, st_utime_t timeout);
void *do_resolve(void *host)
{
struct in_addr addr;
/* Use dns_getaddr() instead of gethostbyname(3) to get IP address */
if (dns_getaddr(host, &addr, TIMEOUT) < 0) {
fprintf(stderr, "dns_getaddr: can't resolve %s: ", (char *)host);
if (h_errno == NETDB_INTERNAL)
perror("");
else
herror("");
} else
printf("%-40s %s\n", (char *)host, inet_ntoa(addr));
return NULL;
}
/*
* Asynchronous DNS host name resolution. This program creates one
* ST thread for each host name (specified as command line arguments).
* All threads do host name resolution concurrently.
*/
int main(int argc, char *argv[])
{
int i;
if (argc < 2) {
fprintf(stderr, "Usage: %s <hostname1> [<hostname2>] ...\n", argv[0]);
exit(1);
}
if (st_init() < 0) {
perror("st_init");
exit(1);
}
for (i = 1; i < argc; i++) {
/* Create a separate thread for each host name */
if (st_thread_create(do_resolve, argv[i], 0, 0) == NULL) {
perror("st_thread_create");
exit(1);
}
}
st_thread_exit(NULL);
/* NOTREACHED */
return 1;
}

View file

@ -1,541 +0,0 @@
/*
* Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Silicon Graphics, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "st.h"
#define IOBUFSIZE (16*1024)
#define IOV_LEN 256
#define IOV_COUNT (IOBUFSIZE / IOV_LEN)
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
static char *prog; /* Program name */
static struct sockaddr_in rmt_addr; /* Remote address */
static unsigned long testing;
#define TESTING_VERBOSE 0x1
#define TESTING_READV 0x2
#define TESTING_READ_RESID 0x4
#define TESTING_WRITEV 0x8
#define TESTING_WRITE_RESID 0x10
static void read_address(const char *str, struct sockaddr_in *sin);
static void start_daemon(void);
static int cpu_count(void);
static void set_concurrency(int nproc);
static void *handle_request(void *arg);
static void print_sys_error(const char *msg);
/*
* This program acts as a generic gateway. It listens for connections
* to a local address ('-l' option). Upon accepting a client connection,
* it connects to the specified remote address ('-r' option) and then
* just pumps the data through without any modification.
*/
int main(int argc, char *argv[])
{
extern char *optarg;
int opt, sock, n;
int laddr, raddr, num_procs, alt_ev, one_process;
int serialize_accept = 0;
struct sockaddr_in lcl_addr, cli_addr;
st_netfd_t cli_nfd, srv_nfd;
prog = argv[0];
num_procs = laddr = raddr = alt_ev = one_process = 0;
/* Parse arguments */
while((opt = getopt(argc, argv, "l:r:p:Saht:X")) != EOF) {
switch (opt) {
case 'a':
alt_ev = 1;
break;
case 'l':
read_address(optarg, &lcl_addr);
laddr = 1;
break;
case 'r':
read_address(optarg, &rmt_addr);
if (rmt_addr.sin_addr.s_addr == INADDR_ANY) {
fprintf(stderr, "%s: invalid remote address: %s\n", prog, optarg);
exit(1);
}
raddr = 1;
break;
case 'p':
num_procs = atoi(optarg);
if (num_procs < 1) {
fprintf(stderr, "%s: invalid number of processes: %s\n", prog, optarg);
exit(1);
}
break;
case 'S':
/*
* Serialization decision is tricky on some platforms. For example,
* Solaris 2.6 and above has kernel sockets implementation, so supposedly
* there is no need for serialization. The ST library may be compiled
* on one OS version, but used on another, so the need for serialization
* should be determined at run time by the application. Since it's just
* an example, the serialization decision is left up to user.
* Only on platforms where the serialization is never needed on any OS
* version st_netfd_serialize_accept() is a no-op.
*/
serialize_accept = 1;
break;
case 't':
testing = strtoul(optarg, NULL, 0);
break;
case 'X':
one_process = 1;
break;
case 'h':
case '?':
fprintf(stderr, "Usage: %s [options] -l <[host]:port> -r <host:port>\n",
prog);
fprintf(stderr, "options are:\n");
fprintf(stderr, " -p <num_processes> number of parallel processes\n");
fprintf(stderr, " -S serialize accepts\n");
fprintf(stderr, " -a use alternate event system\n");
#ifdef DEBUG
fprintf(stderr, " -t mask testing/debugging mode\n");
fprintf(stderr, " -X one process, don't daemonize\n");
#endif
exit(1);
}
}
if (!laddr) {
fprintf(stderr, "%s: local address required\n", prog);
exit(1);
}
if (!raddr) {
fprintf(stderr, "%s: remote address required\n", prog);
exit(1);
}
if (num_procs == 0)
num_procs = cpu_count();
fprintf(stderr, "%s: starting proxy daemon on %s:%d\n", prog,
inet_ntoa(lcl_addr.sin_addr), ntohs(lcl_addr.sin_port));
/* Start the daemon */
if (one_process)
num_procs = 1;
else
start_daemon();
if (alt_ev)
st_set_eventsys(ST_EVENTSYS_ALT);
/* Initialize the ST library */
if (st_init() < 0) {
print_sys_error("st_init");
exit(1);
}
/* Create and bind listening socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
print_sys_error("socket");
exit(1);
}
n = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0) {
print_sys_error("setsockopt");
exit(1);
}
if (bind(sock, (struct sockaddr *)&lcl_addr, sizeof(lcl_addr)) < 0) {
print_sys_error("bind");
exit(1);
}
listen(sock, 128);
if ((srv_nfd = st_netfd_open_socket(sock)) == NULL) {
print_sys_error("st_netfd_open");
exit(1);
}
/* See the comment regarding serialization decision above */
if (num_procs > 1 && serialize_accept && st_netfd_serialize_accept(srv_nfd)
< 0) {
print_sys_error("st_netfd_serialize_accept");
exit(1);
}
/* Start server processes */
if (!one_process)
set_concurrency(num_procs);
for ( ; ; ) {
n = sizeof(cli_addr);
cli_nfd = st_accept(srv_nfd, (struct sockaddr *)&cli_addr, &n,
ST_UTIME_NO_TIMEOUT);
if (cli_nfd == NULL) {
print_sys_error("st_accept");
exit(1);
}
if (st_thread_create(handle_request, cli_nfd, 0, 0) == NULL) {
print_sys_error("st_thread_create");
exit(1);
}
}
/* NOTREACHED */
return 1;
}
static void read_address(const char *str, struct sockaddr_in *sin)
{
char host[128], *p;
struct hostent *hp;
unsigned short port;
strcpy(host, str);
if ((p = strchr(host, ':')) == NULL) {
fprintf(stderr, "%s: invalid address: %s\n", prog, host);
exit(1);
}
*p++ = '\0';
port = (unsigned short) atoi(p);
if (port < 1) {
fprintf(stderr, "%s: invalid port: %s\n", prog, p);
exit(1);
}
memset(sin, 0, sizeof(struct sockaddr_in));
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (host[0] == '\0') {
sin->sin_addr.s_addr = INADDR_ANY;
return;
}
sin->sin_addr.s_addr = inet_addr(host);
if (sin->sin_addr.s_addr == INADDR_NONE) {
/* not dotted-decimal */
if ((hp = gethostbyname(host)) == NULL) {
fprintf(stderr, "%s: can't resolve address: %s\n", prog, host);
exit(1);
}
memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
}
}
#ifdef DEBUG
static void show_iov(const struct iovec *iov, int niov)
{
int i;
size_t total;
printf("iov %p has %d entries:\n", iov, niov);
total = 0;
for (i = 0; i < niov; i++) {
printf("iov[%3d] iov_base=%p iov_len=0x%lx(%lu)\n",
i, iov[i].iov_base, (unsigned long) iov[i].iov_len,
(unsigned long) iov[i].iov_len);
total += iov[i].iov_len;
}
printf("total 0x%lx(%ld)\n", (unsigned long) total, (unsigned long) total);
}
/*
* This version is tricked out to test all the
* st_(read|write)v?(_resid)? variants. Use the non-DEBUG version for
* anything serious. st_(read|write) are all this function really
* needs.
*/
static int pass(st_netfd_t in, st_netfd_t out)
{
char buf[IOBUFSIZE];
struct iovec iov[IOV_COUNT];
int ioviter, nw, nr;
if (testing & TESTING_READV) {
for (ioviter = 0; ioviter < IOV_COUNT; ioviter++) {
iov[ioviter].iov_base = &buf[ioviter * IOV_LEN];
iov[ioviter].iov_len = IOV_LEN;
}
if (testing & TESTING_VERBOSE) {
printf("readv(%p)...\n", in);
show_iov(iov, IOV_COUNT);
}
if (testing & TESTING_READ_RESID) {
struct iovec *riov = iov;
int riov_cnt = IOV_COUNT;
if (st_readv_resid(in, &riov, &riov_cnt, ST_UTIME_NO_TIMEOUT) == 0) {
if (testing & TESTING_VERBOSE) {
printf("resid\n");
show_iov(riov, riov_cnt);
printf("full\n");
show_iov(iov, IOV_COUNT);
}
nr = 0;
for (ioviter = 0; ioviter < IOV_COUNT; ioviter++)
nr += iov[ioviter].iov_len;
nr = IOBUFSIZE - nr;
} else
nr = -1;
} else
nr = (int) st_readv(in, iov, IOV_COUNT, ST_UTIME_NO_TIMEOUT);
} else {
if (testing & TESTING_READ_RESID) {
size_t resid = IOBUFSIZE;
if (st_read_resid(in, buf, &resid, ST_UTIME_NO_TIMEOUT) == 0)
nr = IOBUFSIZE - resid;
else
nr = -1;
} else
nr = (int) st_read(in, buf, IOBUFSIZE, ST_UTIME_NO_TIMEOUT);
}
if (testing & TESTING_VERBOSE)
printf("got 0x%x(%d) E=%d\n", nr, nr, errno);
if (nr <= 0)
return 0;
if (testing & TESTING_WRITEV) {
for (nw = 0, ioviter = 0; nw < nr;
nw += iov[ioviter].iov_len, ioviter++) {
iov[ioviter].iov_base = &buf[nw];
iov[ioviter].iov_len = nr - nw;
if (iov[ioviter].iov_len > IOV_LEN)
iov[ioviter].iov_len = IOV_LEN;
}
if (testing & TESTING_VERBOSE) {
printf("writev(%p)...\n", out);
show_iov(iov, ioviter);
}
if (testing & TESTING_WRITE_RESID) {
struct iovec *riov = iov;
int riov_cnt = ioviter;
if (st_writev_resid(out, &riov, &riov_cnt, ST_UTIME_NO_TIMEOUT) == 0) {
if (testing & TESTING_VERBOSE) {
printf("resid\n");
show_iov(riov, riov_cnt);
printf("full\n");
show_iov(iov, ioviter);
}
nw = 0;
while (--ioviter >= 0)
nw += iov[ioviter].iov_len;
nw = nr - nw;
} else
nw = -1;
} else
nw = st_writev(out, iov, ioviter, ST_UTIME_NO_TIMEOUT);
} else {
if (testing & TESTING_WRITE_RESID) {
size_t resid = nr;
if (st_write_resid(out, buf, &resid, ST_UTIME_NO_TIMEOUT) == 0)
nw = nr - resid;
else
nw = -1;
} else
nw = st_write(out, buf, nr, ST_UTIME_NO_TIMEOUT);
}
if (testing & TESTING_VERBOSE)
printf("put 0x%x(%d) E=%d\n", nw, nw, errno);
if (nw != nr)
return 0;
return 1;
}
#else /* DEBUG */
/*
* This version is the simple one suitable for serious use.
*/
static int pass(st_netfd_t in, st_netfd_t out)
{
char buf[IOBUFSIZE];
int nw, nr;
nr = (int) st_read(in, buf, IOBUFSIZE, ST_UTIME_NO_TIMEOUT);
if (nr <= 0)
return 0;
nw = st_write(out, buf, nr, ST_UTIME_NO_TIMEOUT);
if (nw != nr)
return 0;
return 1;
}
#endif
static void *handle_request(void *arg)
{
struct pollfd pds[2];
st_netfd_t cli_nfd, rmt_nfd;
int sock;
cli_nfd = (st_netfd_t) arg;
pds[0].fd = st_netfd_fileno(cli_nfd);
pds[0].events = POLLIN;
/* Connect to remote host */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
print_sys_error("socket");
goto done;
}
if ((rmt_nfd = st_netfd_open_socket(sock)) == NULL) {
print_sys_error("st_netfd_open_socket");
close(sock);
goto done;
}
if (st_connect(rmt_nfd, (struct sockaddr *)&rmt_addr,
sizeof(rmt_addr), ST_UTIME_NO_TIMEOUT) < 0) {
print_sys_error("st_connect");
st_netfd_close(rmt_nfd);
goto done;
}
pds[1].fd = sock;
pds[1].events = POLLIN;
/*
* Now just pump the data through.
* XXX This should use one thread for each direction for true full-duplex.
*/
for ( ; ; ) {
pds[0].revents = 0;
pds[1].revents = 0;
if (st_poll(pds, 2, ST_UTIME_NO_TIMEOUT) <= 0) {
print_sys_error("st_poll");
break;
}
if (pds[0].revents & POLLIN) {
if (!pass(cli_nfd, rmt_nfd))
break;
}
if (pds[1].revents & POLLIN) {
if (!pass(rmt_nfd, cli_nfd))
break;
}
}
st_netfd_close(rmt_nfd);
done:
st_netfd_close(cli_nfd);
return NULL;
}
static void start_daemon(void)
{
pid_t pid;
/* Start forking */
if ((pid = fork()) < 0) {
print_sys_error("fork");
exit(1);
}
if (pid > 0)
exit(0); /* parent */
/* First child process */
setsid(); /* become session leader */
if ((pid = fork()) < 0) {
print_sys_error("fork");
exit(1);
}
if (pid > 0) /* first child */
exit(0);
chdir("/");
umask(022);
}
/*
* Create separate processes ("virtual processors"). Since it's just an
* example, there is no watchdog - the parent just exits leaving children
* on their own.
*/
static void set_concurrency(int nproc)
{
pid_t pid;
int i;
if (nproc < 1)
nproc = 1;
for (i = 0; i < nproc; i++) {
if ((pid = fork()) < 0) {
print_sys_error("fork");
exit(1);
}
/* Child returns */
if (pid == 0)
return;
}
/* Parent just exits */
exit(0);
}
static int cpu_count(void)
{
int n;
#if defined (_SC_NPROCESSORS_ONLN)
n = (int) sysconf(_SC_NPROCESSORS_ONLN);
#elif defined (_SC_NPROC_ONLN)
n = (int) sysconf(_SC_NPROC_ONLN);
#elif defined (HPUX)
#include <sys/mpctl.h>
n = mpctl(MPC_GETNUMSPUS, 0, 0);
#else
n = -1;
errno = ENOSYS;
#endif
return n;
}
static void print_sys_error(const char *msg)
{
fprintf(stderr, "%s: %s: %s\n", prog, msg, strerror(errno));
}

View file

@ -1,305 +0,0 @@
/*
* Copyright (c) 1985, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Silicon Graphics, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined (DARWIN)
#define BIND_8_COMPAT
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <netdb.h>
#include <errno.h>
#include "st.h"
#define MAXPACKET 1024
#if !defined(NETDB_INTERNAL) && defined(h_NETDB_INTERNAL)
#define NETDB_INTERNAL h_NETDB_INTERNAL
#endif
/* New in Solaris 7 */
#if !defined(_getshort) && defined(ns_get16)
#define _getshort(cp) ns_get16(cp)
#endif
typedef union {
HEADER hdr;
u_char buf[MAXPACKET];
} querybuf_t;
static int parse_answer(querybuf_t *ans, int len, struct in_addr *addr)
{
char buf[MAXPACKET];
HEADER *ahp;
u_char *cp, *eoa;
int type, n;
ahp = &ans->hdr;
eoa = ans->buf + len;
cp = ans->buf + sizeof(HEADER);
while (ahp->qdcount > 0) {
ahp->qdcount--;
cp += dn_skipname(cp, eoa) + QFIXEDSZ;
}
while (ahp->ancount > 0 && cp < eoa) {
ahp->ancount--;
if ((n = dn_expand(ans->buf, eoa, cp, buf, sizeof(buf))) < 0)
break;
cp += n;
type = _getshort(cp);
cp += 8;
n = _getshort(cp);
cp += 2;
if (type == T_CNAME) {
cp += n;
continue;
}
memcpy(addr, cp, n);
return 0;
}
h_errno = TRY_AGAIN;
return -1;
}
static int query_domain(st_netfd_t nfd, const char *name, struct in_addr *addr,
st_utime_t timeout)
{
querybuf_t qbuf;
u_char *buf = qbuf.buf;
HEADER *hp = &qbuf.hdr;
int blen = sizeof(qbuf);
int i, len, id;
for (i = 0; i < _res.nscount; i++) {
len = res_mkquery(QUERY, name, C_IN, T_A, NULL, 0, NULL, buf, blen);
if (len <= 0) {
h_errno = NO_RECOVERY;
return -1;
}
id = hp->id;
if (st_sendto(nfd, buf, len, (struct sockaddr *)&(_res.nsaddr_list[i]),
sizeof(struct sockaddr), timeout) != len) {
h_errno = NETDB_INTERNAL;
/* EINTR means interrupt by other thread, NOT by a caught signal */
if (errno == EINTR)
return -1;
continue;
}
/* Wait for reply */
do {
len = st_recvfrom(nfd, buf, blen, NULL, NULL, timeout);
if (len <= 0)
break;
} while (id != hp->id);
if (len < HFIXEDSZ) {
h_errno = NETDB_INTERNAL;
if (len >= 0)
errno = EMSGSIZE;
else if (errno == EINTR) /* see the comment above */
return -1;
continue;
}
hp->ancount = ntohs(hp->ancount);
hp->qdcount = ntohs(hp->qdcount);
if ((hp->rcode != NOERROR) || (hp->ancount == 0)) {
switch (hp->rcode) {
case NXDOMAIN:
h_errno = HOST_NOT_FOUND;
break;
case SERVFAIL:
h_errno = TRY_AGAIN;
break;
case NOERROR:
h_errno = NO_DATA;
break;
case FORMERR:
case NOTIMP:
case REFUSED:
default:
h_errno = NO_RECOVERY;
}
continue;
}
if (parse_answer(&qbuf, len, addr) == 0)
return 0;
}
return -1;
}
#define CLOSE_AND_RETURN(ret) \
{ \
n = errno; \
st_netfd_close(nfd); \
errno = n; \
return (ret); \
}
int dns_getaddr(const char *host, struct in_addr *addr, st_utime_t timeout)
{
char name[MAXDNAME], **domain;
const char *cp;
int s, n, maxlen, dots;
int trailing_dot, tried_as_is;
st_netfd_t nfd;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
return -1;
}
if (_res.options & RES_USEVC) {
h_errno = NETDB_INTERNAL;
errno = ENOSYS;
return -1;
}
if (!host || *host == '\0') {
h_errno = HOST_NOT_FOUND;
return -1;
}
/* Create UDP socket */
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
h_errno = NETDB_INTERNAL;
return -1;
}
if ((nfd = st_netfd_open_socket(s)) == NULL) {
h_errno = NETDB_INTERNAL;
n = errno;
close(s);
errno = n;
return -1;
}
maxlen = sizeof(name) - 1;
n = 0;
dots = 0;
trailing_dot = 0;
tried_as_is = 0;
for (cp = host; *cp && n < maxlen; cp++) {
dots += (*cp == '.');
name[n++] = *cp;
}
if (name[n - 1] == '.')
trailing_dot = 1;
/*
* If there are dots in the name already, let's just give it a try
* 'as is'. The threshold can be set with the "ndots" option.
*/
if (dots >= _res.ndots) {
if (query_domain(nfd, host, addr, timeout) == 0)
CLOSE_AND_RETURN(0);
if (h_errno == NETDB_INTERNAL && errno == EINTR)
CLOSE_AND_RETURN(-1);
tried_as_is = 1;
}
/*
* We do at least one level of search if
* - there is no dot and RES_DEFNAME is set, or
* - there is at least one dot, there is no trailing dot,
* and RES_DNSRCH is set.
*/
if ((!dots && (_res.options & RES_DEFNAMES)) ||
(dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
name[n++] = '.';
for (domain = _res.dnsrch; *domain; domain++) {
strncpy(name + n, *domain, maxlen - n);
if (query_domain(nfd, name, addr, timeout) == 0)
CLOSE_AND_RETURN(0);
if (h_errno == NETDB_INTERNAL && errno == EINTR)
CLOSE_AND_RETURN(-1);
if (!(_res.options & RES_DNSRCH))
break;
}
}
/*
* If we have not already tried the name "as is", do that now.
* note that we do this regardless of how many dots were in the
* name or whether it ends with a dot.
*/
if (!tried_as_is) {
if (query_domain(nfd, host, addr, timeout) == 0)
CLOSE_AND_RETURN(0);
}
CLOSE_AND_RETURN(-1);
}

File diff suppressed because it is too large Load diff