Пример #1
0
/* process command within a request
 */
static int
process_command( int new_sockfd, struct server_ctx* ctx,
                 const char* param, size_t plen )
{
    int rc = 0;
    const int STAT_OPTIONS = 0;
    const int RESTART_OPTIONS = MSO_SKIP_CLIENTS | MSO_RESTART;

    assert( (new_sockfd > 0) && ctx && param );

    if( 0 == strncmp( ctx->cmd, CMD_UDP, sizeof(ctx->cmd) ) ||
        0 == strncmp( ctx->cmd, CMD_RTP, sizeof(ctx->cmd) ) ) {
        if( ctx->clfree ) {
            rc = udp_relay( new_sockfd, param, plen,
                            &(ctx->mcast_inaddr), ctx );
        }
        else {
            send_http_response( new_sockfd, 401, "Bad request" );
            (void)tmfprintf( g_flog, "Client limit [%d] has been reached.\n",
                    ctx->clmax);
        }
    }
    else if( 0 == strncmp( ctx->cmd, CMD_STATUS, sizeof(ctx->cmd) ) ) {
        rc = report_status( new_sockfd, ctx, STAT_OPTIONS );
    }
    else if( 0 == strncmp( ctx->cmd, CMD_RESTART, sizeof(ctx->cmd) ) ) {
        (void) report_status( new_sockfd, ctx, RESTART_OPTIONS );

        terminate_all_clients( ctx );
        wait_all( ctx );
    }
    else {
        TRACE( (void)tmfprintf( g_flog, "Unrecognized command [%s]"
                    " - ignoring.\n", ctx->cmd) );
        send_http_response( new_sockfd, 401, "Unrecognized request" );
    }

    return rc;
}
Пример #2
0
int
serv_loop(void)
{
    int    cs, ss = 0;
    struct sockaddr_storage cl, udp;
    fd_set readable;
    int    i, n, len;
    char   cl_addr[NI_MAXHOST];
    char   cl_name[NI_MAXHOST];
    int    error;
    pid_t  pid;

#ifdef USE_THREAD
    if (threading)
      {
	blocksignal(SIGHUP);
	blocksignal(SIGINT);
	blocksignal(SIGUSR1);
      }
#endif

    for (;;)
      {
	readable = allsock;

	MUTEX_LOCK(mutex_select);
	n = select(maxsock+1, &readable, 0, 0, 0);

	if (n <= 0)
	  {
	    if (n < 0 && errno != EINTR)
	      msg_out(warn, "select: %m");

	    MUTEX_UNLOCK(mutex_select);
	    continue;
	  }

#ifdef USE_THREAD
	if ( ! threading )
	  {
#endif
	    /* handle any queued signal flags */
	    if (FD_ISSET(sig_queue[0], &readable))
	      {
		if (ioctl(sig_queue[0], FIONREAD, &i) != 0)
		  {
		    msg_out(crit, "ioctl: %m");
		    exit(-1);
		  }
		while (--i >= 0)
		  {
		    char c;
		    if (read(sig_queue[0], &c, 1) != 1)
		      {
			msg_out(crit, "read: %m");
			exit(-1);
		      }

		    switch(c)
		      {
		      case 'H': /* sighup */
			reload();
			break;

		      case 'C': /* sigchld */
			reapchild();
			break;

		      case 'T': /* sigterm */
			cleanup();
			break;

		      default:
			break;
		      }
		  }
	      }
#ifdef USE_THREAD
	  }
#endif

	for ( i = 0; i < serv_sock_ind; i++ )
	  {
	    if (FD_ISSET(serv_sock[i], &readable))
	      {
		n--;
		break;
	      }
	  }

	if ( n < 0 || i >= serv_sock_ind )
	  {
	    MUTEX_UNLOCK(mutex_select);
	    continue;
	  }

	len = sizeof(struct sockaddr_storage);
	cs = accept(serv_sock[i], (struct sockaddr *)&cl, &len);

	if (cs < 0)
	  {
	    if (errno == EINTR
#ifdef SOLARIS
		|| errno == EPROTO
#endif
		|| errno == EWOULDBLOCK
		|| errno == ECONNABORTED)
	      {
		; /* ignore */
	      }
	    else
	      /* real accept error */
	      msg_out(warn, "accept: %m");

	    MUTEX_UNLOCK(mutex_select);
	    continue;
	  }
	MUTEX_UNLOCK(mutex_select);

#ifdef USE_THREAD
	if ( !threading )
	  {
#endif
	    if (max_child > 0 && cur_child >= max_child)
	      {
		msg_out(warn, "child: cur %d; exeedeing max(%d)\n",
			cur_child, max_child);
		close(cs);
		continue;
	      }
#ifdef USE_THREAD
	  }
#endif

	error = getnameinfo((struct sockaddr *)&cl, len,
			    cl_addr, sizeof(cl_addr),
			    NULL, 0,
			    NI_NUMERICHOST);

	if (resolv_client)
	  {
	    error = getnameinfo((struct sockaddr *)&cl, len,
				cl_name, sizeof(cl_name),
				NULL, 0, 0);
	    msg_out(norm, "%s[%s] connected\n", cl_name, cl_addr);
	  }
	else
	  {
	    msg_out(norm, "%s connected\n", cl_addr);
	    strncpy(cl_name, cl_addr, sizeof(cl_name));
	  }

	i = validate_access(cl_addr, cl_name);
	if (i < 1)
	  {
	    /* access denied */
	    close(cs);
	    continue;
	  }

	set_blocking(cs);

#ifdef USE_THREAD
	if (!threading )
	  {
#endif
	    blocksignal(SIGHUP);
	    blocksignal(SIGCHLD);
	    pid = fork();
	    switch (pid)
	      {
	      case -1:  /* fork child failed */
		break;

	      case 0:   /* i am child */
		for ( i = 0; i < serv_sock_ind; i++ )
		  close(serv_sock[i]);

		setsignal(SIGCHLD, SIG_DFL);
		setsignal(SIGHUP, SIG_DFL);
		releasesignal(SIGCHLD);
		releasesignal(SIGHUP);
#ifdef IPHONE_OS
		iphone_app_check_connection();
#endif
		bzero(&udp, sizeof(struct sockaddr_storage));
		udp.ss_family = AF_UNSPEC;

		ss = proto_socks(cs, &udp);
		if ( ss == -1 )
		  {
		    close(cs);  /* may already be closed */
		    exit(1);
		  }
		if (udp.ss_family == AF_UNSPEC)
		  {
		    errno = 0;
		    perror("start udp_relay()\n");
		    udp_relay(cs, ss, &udp);
		  }
		else
		  {
		    errno = 0;
		    perror("start relay()\n");
		    relay(cs, ss);
		  }

		exit(0);

	      default: /* may be parent */
		proclist_add(pid);
		break;
	      }

	    close(cs);
	    releasesignal(SIGHUP);
	    releasesignal(SIGCHLD);
#ifdef USE_THREAD
	  }
	else
	  {
#ifdef IPHONE_OS
	    iphone_app_check_connection();
#endif
	    bzero(&udp, sizeof(struct sockaddr_storage));
	    udp.ss_family = AF_UNSPEC;

	    ss = proto_socks(cs, &udp);
	    if ( ss == -1 )
	      {
		close(cs);  /* may already be closed */
		continue;
	      }
	    if (udp.ss_family != AF_UNSPEC)
	      {
		errno = 0;
		udp_relay(cs, ss, &udp);
	      }
	    else
	      {
		errno = 0;
		relay(cs, ss);
	      }
	  }
#endif
      }
}
Пример #3
0
int service_udprelay(Connection *Conn)
{
	udp_relay(Conn,FromC);
	return 0;
}