예제 #1
0
int main(int argc, char *argv[]) 
{
    fd_set rfds, wfds;
    struct connstruct *tp, *to;
    struct serverstruct *sp;
    int rnum, wnum, active;
    int i = 1;
    time_t currtime;
    char *httpAddress = NULL;
    int httpPort = CONFIG_HTTP_PORT;
    char *httpsAddress = NULL;
    int httpsPort = CONFIG_HTTP_HTTPS_PORT;
    uint32_t options = CONFIG_HTTP_DEFAULT_SSL_OPTIONS;
    char *portStr;
    char *private_key = NULL;
    char *cert = NULL;

#ifdef WIN32
    WORD wVersionRequested = MAKEWORD(2, 2);
    WSADATA wsaData;
    WSAStartup(wVersionRequested,&wsaData);
#else
    signal(SIGPIPE, SIG_IGN);
#if defined(CONFIG_HTTP_HAS_CGI)
    signal(SIGCHLD, reaper);
#endif
#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGQUIT, die);
#endif
#endif

#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGTERM, die);
    signal(SIGINT, sigint_cleanup);
#endif
    tdate_init();

    /* get some command-line parameters */
    while (argv[i] != NULL)
    {
        if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpAddress = argv[i+1];
                *portStr = 0;
                httpPort = atoi(portStr + 1);
            }
            else
                httpPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-s") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpsAddress = argv[i+1];
                *portStr = 0;
                httpsPort = atoi(portStr + 1);
            }
            else
                httpsPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-w") == 0 && argv[i+1] != NULL)
        {
            webroot = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-cert") == 0 && argv[i+1] != NULL)
        {
            cert = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-key") == 0 && argv[i+1] != NULL)
        {
            private_key = argv[i+1];
            i += 2;
            continue;
        }
        printf("%s:\n"
               "    [-p [address:]httpport]\n"
               "    [-s [address:]httpsport]\n"
               "    [-key private_key]\n"
               "    [-cert cert]\n"
               "    [-w webroot]\n", argv[0]);
        exit(1);
    }

    for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) 
    {
        tp = freeconns;
        freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct));
        freeconns->next = tp;
    }

    if ((active = openlistener(httpAddress, httpPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if ((active = openlistener(httpsAddress, httpsPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpsPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if (cert != NULL && private_key != NULL)
        options |=  SSL_NO_DEFAULT_KEY;

    servers->ssl_ctx = ssl_ctx_new(options, CONFIG_HTTP_SESSION_CACHE_SIZE);
    servers->is_ssl = 1;

    if (cert != NULL && private_key != NULL)
    {
        printf("YEAH\n");
        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_RSA_KEY, private_key,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load private key %s\n", private_key);
#endif
            exit(1);
        }

        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_X509_CERT, cert,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load cert %s\n", cert);
#endif
            exit(1);
        }
    }

#if defined(CONFIG_HTTP_HAS_CGI)
    addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
#endif

#if defined(CONFIG_HTTP_VERBOSE)
#if defined(CONFIG_HTTP_HAS_CGI)
    printf("addcgiext %s\n", CONFIG_HTTP_CGI_EXTENSIONS); 
#endif
    printf("%s: listening on ports %d (http) and %d (https)\n", 
            server_version, httpPort, httpsPort);
    TTY_FLUSH();
#endif

    ax_chdir();

#ifdef CONFIG_HTTP_ENABLE_DIFFERENT_USER
    {
        struct passwd *pd = getpwnam(CONFIG_HTTP_USER);

        if (pd != NULL)
        {
            int res = setuid(pd->pw_uid);
            res |= setgid(pd->pw_gid);

#if defined(CONFIG_HTTP_VERBOSE)
            if (res == 0)
            {
                printf("change to '%s' successful\n", CONFIG_HTTP_USER); 
                TTY_FLUSH();
            }
#endif
        }

    }
#endif

#ifndef WIN32 
#ifdef CONFIG_HTTP_IS_DAEMON
    if (fork() > 0)  /* parent will die */
        exit(0);

    setsid();
#endif
#endif

    /* main loop */
    while (1)
    {
        struct timeval tv = { 10, 0 };
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        rnum = wnum = -1;
        sp = servers;

        while (sp != NULL)  /* read each server port */
        {
            FD_SET(sp->sd, &rfds);

            if (sp->sd > rnum) 
                rnum = sp->sd;
            sp = sp->next;
        }

        /* Add the established sockets */
        tp = usedconns;
        currtime = time(NULL);

        while (tp != NULL) 
        {
            if (currtime > tp->timeout)     /* timed out? Kill it. */
            {
                to = tp;
                tp = tp->next;
                removeconnection(to);
                continue;
            }

            if (tp->state == STATE_WANT_TO_READ_HEAD) 
            {
                FD_SET(tp->networkdesc, &rfds);
                if (tp->networkdesc > rnum) 
                    rnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_HEAD) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_READ_FILE) 
            {
                FD_SET(tp->filedesc, &rfds);
                if (tp->filedesc > rnum) 
                    rnum = tp->filedesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_FILE) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (tp->state == STATE_DOING_DIR) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }
#endif
            tp = tp->next;
        }

        active = select(wnum > rnum ? wnum+1 : rnum+1,
                rnum != -1 ? &rfds : NULL, 
                wnum != -1 ? &wfds : NULL,
                NULL, usedconns ? &tv : NULL);

        /* timeout? */
        if (active == 0)
            continue;

        /* New connection? */
        sp = servers;
        while (active > 0 && sp != NULL) 
        {
            if (FD_ISSET(sp->sd, &rfds)) 
            {
                handlenewconnection(sp->sd, sp->is_ssl);
                active--;
            }

            sp = sp->next;
        }

        /* Handle the established sockets */
        tp = usedconns;

        while (active > 0 && tp != NULL) 
        {
            to = tp;
            tp = tp->next;

            if (to->state == STATE_WANT_TO_READ_HEAD &&
                        FD_ISSET(to->networkdesc, &rfds)) 
            {
                active--;
#if defined(CONFIG_HTTP_HAS_CGI)
                if (to->post_state)
                    read_post_data(to);
                else
#endif
                    procreadhead(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_HEAD &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendhead(to);
            } 

            if (to->state == STATE_WANT_TO_READ_FILE && 
                        FD_ISSET(to->filedesc, &rfds)) 
            {
                active--;
                procreadfile(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_FILE && 
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendfile(to);
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (to->state == STATE_DOING_DIR &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procdodir(to);
            }
#endif
        }
    }

    return 0;
}
예제 #2
0
파일: server.c 프로젝트: ytz2/cs820
void listener(char *server_port, char *interface_name) {
	socklen_t len;
	int listening_fd, errcode;
	struct sockaddr server;
	struct sockaddr_in *iptr;
	char text_buf[TEXT_SIZE];
	char local_node[HOSTMAX];
	char *host_name;
	struct thread_params *params;
	pthread_t agent_id;

	no_sigpipe();
	/* establish a server "listening post" */
	listening_fd = openlistener(server_port, interface_name, &server);

	/* get the hostname of server*/
	if (interface_name == NULL) {
		if (gethostname(local_node, HOSTMAX) < 0) {
			perror("Server gethostname");
			exit(1);
		}
		host_name = local_node;
	} else {
		host_name = interface_name;
	}

	if (listening_fd < 0)
		exit(EXIT_FAILURE);

	/* we are now successfully established as a server */
	/* infinite loop -- server serves forever, must be killed by ^C */
	for (;;) {
		iptr = (struct sockaddr_in *) &server;
		if (inet_ntop(iptr->sin_family, &iptr->sin_addr, text_buf,
				TEXT_SIZE) == NULL) {
			perror("inet_ntop server");
			break;
		}
		fprintf(stderr, "%s listening at IP address %s port %d\n", host_name,
				text_buf, ntohs(iptr->sin_port));
		/* accept a client connection (block until one arrives) */
		params = malloc(sizeof(struct thread_params));
		if (params == NULL) {
			perror("listener malloc");
			break;
		}
		len = sizeof(params->client);
		if ((params->client_fd = accept(listening_fd, &params->client, &len))
				< 0) {
			perror("rplcsd accept");
			break;
		}

		iptr = (struct sockaddr_in *) (&params->client);
		if (inet_ntop(iptr->sin_family, &iptr->sin_addr, text_buf,
				TEXT_SIZE) == NULL) {
			perror("inet_ntop client");
			free(params);
			continue;
		}
		fprintf(stderr, "connected to client at IP address %s "
				"port %d\n", text_buf, ntohs(iptr->sin_port));

		/* we are now successfully connected to a remote client */
		errcode = pthread_create(&agent_id, NULL, server_agent, params);
		if (errcode != 0) {
			fprintf(stderr, "pthread_create server agent: %s\n",
					strerror(errcode));
			break;
		}
	} /* infinite loop */

	if (close(listening_fd) < 0) {
		perror("rplcsd server close");
	}
	pthread_exit(NULL);
} /* listener */