Beispiel #1
0
int main(int argc, char const *argv[]) {
  addrinfo hints;
  int listener, fdmax, nbytes;
  char buf[BUFSIZE];
  fd_set master;
  fd_set readfs;

  FD_ZERO(&master);
  FD_ZERO(&readfs);

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  setup_socket(&hints, &listener); 

  /*freeaddrinfo(ai);*/

  if (listen(listener, BACKLOG) == -1) {
    perror("Listen error");
    return 2;
  }
  printf("Now listening on port %s\n", MYPORT);

  FD_SET(listener, &master);

  fdmax = listener;

  while (1) {
    int i;

    readfs = master;
    if (select(fdmax+1, &readfs, NULL, NULL, NULL) == -1) {
      perror("select");
      exit(4);
    }

    for (i = 0; i <= fdmax; ++i) {
      if (!FD_ISSET(i, &readfs)) continue;

      if (i == listener) {
        int newfd;
        if (!(newfd = accept_connection(listener))) continue;

        FD_SET(newfd, &master);
        fdmax = newfd > fdmax ? newfd : fdmax;
      } else {
        if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
          close_connection(i, nbytes);
          FD_CLR(i, &master);
        } else {
          int j;
          for (j = 0; j <= fdmax; j++) {
            if (!FD_ISSET(j, &master)) continue;
            if (j == listener) continue;
            if (j == i) continue;
            
            if (send(j, buf, nbytes, 0) == -1) {
              perror("send");
            }
          }
        }
      }
    }
  }

  return 0;
}
Beispiel #2
0
static bool init_ipc(void)
{
	struct sockaddr_un addr;

	int sk;
	int err;

	sk = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
	if (sk < 0) {
		err = errno;
		tester_warn("Failed to create socket: %d (%s)", err,
							strerror(err));
		return false;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;

	memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));

	if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		err = errno;
		tester_warn("Failed to bind socket: %d (%s)", err,
								strerror(err));
		close(sk);
		return false;
	}

	if (listen(sk, 2) < 0) {
		err = errno;
		tester_warn("Failed to listen on socket: %d (%s)", err,
								strerror(err));
		close(sk);
		return false;
	}

	/* Start Android Bluetooth daemon service */
	if (property_set("ctl.start", SERVICE_NAME) < 0) {
		tester_warn("Failed to start service %s", SERVICE_NAME);
		close(sk);
		return false;
	}

	cmd_sk = accept_connection(sk);
	if (cmd_sk < 0) {
		close(sk);
		return false;
	}

	notif_sk = accept_connection(sk);
	if (notif_sk < 0) {
		close(sk);
		close(cmd_sk);
		cmd_sk = -1;
		return false;
	}

	tester_print("bluetoothd connected");

	close(sk);

	return true;
}
Beispiel #3
0
int main(int argc, char **argv)
{
    int sock_fd;
    int msgsock;
    Connection *client;
    pthread_t broadcast_thread_id;
    char buffer[MAXDATASIZE];

    // listen on port
    sock_fd = listen_on(atoi(argv[1]));
    if (sock_fd < 0)
    {
        perror("listen_on");
        exit(-1);// create sender
    }

    // open pipe for message buffering
    pipe(buffer_queue);

    // start broadcast handler
    pthread_create(&broadcast_thread_id, NULL, broadcast_handler, NULL);

    printf("\nThis is the server with pid %d listening on port %s\n", getpid(), argv[1]);

    // loop
    while (1)
    {
        // accept connection
        msgsock = accept_connection(sock_fd);

        // store connections
        if ((client = next_available_slot()) == NULL)
        {
            printf("%s\n", ERROR_MSG);
            if (send_msg(msgsock, ERROR_MSG) < 0)
            {
                perror("send_msg");
                close(msgsock);
            }
        }


        client->msgsock = msgsock;
        get_peer_information(msgsock, client);
        sprintf(buffer, "[%s:%d] connected", client->ipstr, client->port);
        printf("%s\n", buffer);
        broadcast(NULL, buffer);

        // create thread to handle request
        pthread_create(&client->thread_id, NULL, request_handler, client);

    }

    // We never expect to run our code here, so we should trap our code at this point and
    // wait for all threads exit
    printf("Server Error\n");
    for (int i = 0; i < MAX_CONNECTIONS; i++)
    {
        if (connections[i].msgsock > 0)
        {
            pthread_join(connections[i].thread_id, NULL);
        }
    }
}
Beispiel #4
0
int main(int argc, char **argv)
{
  struct sockaddr_in addr;
  struct rdma_cm_event *event = NULL;
  struct rdma_cm_id *listener = NULL;
  struct rdma_event_channel *ec = NULL;
  uint16_t port = 0;

  if (argc != 2)
    usage(argv[0]);

  if (strcmp(argv[1], "write") == 0)
    set_mode(M_WRITE);
  else if (strcmp(argv[1], "read") == 0)
    set_mode(M_READ);
  else
    usage(argv[0]);

  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;

  TEST_Z(ec = rdma_create_event_channel());
  TEST_NZ(rdma_create_id(ec, &listener, NULL, RDMA_PS_TCP));
  TEST_NZ(rdma_bind_addr(listener, (struct sockaddr *)&addr));
  TEST_NZ(rdma_listen(listener, 10)); /* backlog=10 is arbitrary */

  port = ntohs(rdma_get_src_port(listener));

  printf("listening on port %d.\n", port);

  while (1) {
    //    pthread_t          thread_id;
    //    pthread_attr_t     thread_attr;
    //    simple_context_t  *context = NULL;
    //    struct rdma_cm_id *id = NULL;
    int rc =0;
    fprintf(stderr, "Waiting for cm_event... ");
    if ((rc = rdma_get_cm_event(ec, &event))){
      fprintf(stderr, "get event failed : %d\n", rc);
      break;
    }
    fprintf(stderr, "\"%s\"\n", event_type_str(event->event));
    switch (event->event){
      case RDMA_CM_EVENT_CONNECT_REQUEST:
	accept_connection(event->id);
	break;
      case RDMA_CM_EVENT_ESTABLISHED:
	on_connect(event->id->context);
	//	pthread_attr_init(&thread_attr);
	//	pthread_create(&thread_id,
	//			 &thread_attr,
	//			 handle_server_cq,
	//			 (void *)(event->id->context));
	break;
    case RDMA_CM_EVENT_DISCONNECTED:
      fprintf(stderr, "Disconnect from id : %p \n", event->id);
      //	fprintf(stderr, "Disconnect from id : %p (total connections %d)\n",
      //	 event->id, connections);
	//	context = (simple_context_t *)(event->id->context);
	//	id = event->id;
	break;
      default:
	break;
    }
    rdma_ack_cm_event(event);
    //    if (context){
    //	  context->quit_cq_thread = 1;
    //	  pthread_join(thread_id, NULL);
    //	  rdma_destroy_id(id);
    //	  free_connection(context);
    //	  context = NULL;
    //    }
  }

  rdma_destroy_id(listener);
  rdma_destroy_event_channel(ec);

  return 0;


  /*
  while (rdma_get_cm_event(ec, &event) == 0) {
    struct rdma_cm_event event_copy;

    memcpy(&event_copy, event, sizeof(*event));
    rdma_ack_cm_event(event);

    if (on_event(&event_copy))
      break;
  }

  rdma_destroy_id(listener);
  rdma_destroy_event_channel(ec);

  return 0;
  */
}
Beispiel #5
0
void child_status(void) { /* dead libwrap or 'exec' process detected */
    int pid, status;
    char *sig_name;

#ifdef HAVE_WAIT_FOR_PID
    while((pid=wait_for_pid(-1, &status, WNOHANG))>0) {
#else
    if((pid=wait(&status))>0) {
#endif
#ifdef WIFSIGNALED
        if(WIFSIGNALED(status)) {
            sig_name=signal_name(WTERMSIG(status));
            s_log(LOG_INFO, "Child process %d terminated on %s",
                pid, sig_name);
            str_free(sig_name);
        } else {
            s_log(LOG_INFO, "Child process %d finished with code %d",
                pid, WEXITSTATUS(status));
        }
#else
        s_log(LOG_INFO, "Child process %d finished with status %d",
            pid, status);
#endif
    }
}

#endif /* !defined(USE_OS2) */

#endif /* !defined(USE_WIN32) */

/**************************************** main loop accepting connections */

void daemon_loop(void) {
    while(1) {
        int temporary_lack_of_resources=0;
        int num=s_poll_wait(fds, -1, -1);
        if(num>=0) {
            SERVICE_OPTIONS *opt;
            s_log(LOG_DEBUG, "Found %d ready file descriptor(s)", num);
            if(service_options.log_level>=LOG_DEBUG) /* performance optimization */
                s_poll_dump(fds, LOG_DEBUG);
            if(s_poll_canread(fds, signal_pipe[0]))
                if(signal_pipe_dispatch()) /* SIGNAL_TERMINATE or error */
                    break; /* terminate daemon_loop */
            for(opt=service_options.next; opt; opt=opt->next)
                if(opt->option.accept && s_poll_canread(fds, opt->fd))
                    if(accept_connection(opt))
                        temporary_lack_of_resources=1;
        } else {
            log_error(LOG_NOTICE, get_last_socket_error(),
                "daemon_loop: s_poll_wait");
            temporary_lack_of_resources=1;
        }
        if(temporary_lack_of_resources) {
            s_log(LOG_NOTICE,
                "Accepting new connections suspended for 1 second");
            sleep(1); /* to avoid log trashing */
        }
    }
}

    /* return 1 when a short delay is needed before another try */
NOEXPORT int accept_connection(SERVICE_OPTIONS *opt) {
    SOCKADDR_UNION addr;
    char *from_address;
    SOCKET s;
    socklen_t addrlen;

    addrlen=sizeof addr;
    for(;;) {
        s=s_accept(opt->fd, &addr.sa, &addrlen, 1, "local socket");
        if(s!=INVALID_SOCKET) /* success! */
            break;
        switch(get_last_socket_error()) {
            case S_EINTR: /* interrupted by a signal */
                break; /* retry now */
            case S_EMFILE:
#ifdef S_ENFILE
            case S_ENFILE:
#endif
#ifdef S_ENOBUFS
            case S_ENOBUFS:
#endif
#ifdef S_ENOMEM
            case S_ENOMEM:
#endif
                return 1; /* temporary lack of resources */
            default:
                return 0; /* any other error */
        }
    }
    from_address=s_ntop(&addr, addrlen);
    s_log(LOG_DEBUG, "Service [%s] accepted (FD=%d) from %s",
        opt->servname, s, from_address);
    str_free(from_address);
#ifdef USE_FORK
    RAND_add("", 1, 0.0); /* each child needs a unique entropy pool */
#else
    if(max_clients && num_clients>=max_clients) {
        s_log(LOG_WARNING, "Connection rejected: too many clients (>=%ld)",
            max_clients);
        closesocket(s);
        return 0;
    }
#endif
    if(create_client(opt->fd, s,
            alloc_client_session(opt, s, s), client_thread)) {
        s_log(LOG_ERR, "Connection rejected: create_client failed");
        closesocket(s);
        return 0;
    }
    return 0;
}
Beispiel #6
0
int main(int argc, char *argv[])
{
	signal(SIGCHLD, SIG_IGN);

	int ret;
	int i;
	int pid;
	int sock_fd;
	int child_to_parent[2]; // pipe for child to communicate with parent
	char buffer[MAXDATASIZE];

	if (pipe(child_to_parent) < 0)
	{
		perror("pipe");
		exit(-1);
	}

	printf("\nThis is the server with pid %d listening on port %d\n", getpid(), SERVER_PORT);

	// setup the server to bind and listen on a port
	sock_fd = listen_on(SERVER_PORT);

	fd_set set;


	while(1) { // forever
		FD_ZERO(&set);
		FD_SET(sock_fd, &set);
		FD_SET(child_to_parent[0], &set);
		if ((ret = select(FD_SETSIZE, &set, NULL, NULL, NULL)) < 0)
		{
			// select can catch the signal but we want to ignore it
			if (errno == EINTR)
			{
				continue;
			}
			else
			{
				perror("select");
				exit(-1);
			}

		}

		if (FD_ISSET(sock_fd, &set))
		{
			int msgsock = accept_connection(sock_fd); // wait for a client to connect
			printf("Got connection from client!\n");

			// handle the request with a new process
			if ((pid = fork()) < 0)
			{
				perror("Fork");
				exit(-1);
			}
			else if (pid == 0) // child
			{
				handle_request(msgsock, child_to_parent[1]);
				exit(0);
			}
			else
			{
				close(msgsock);
			}
		}
		if (FD_ISSET(child_to_parent[0], &set))
		{
			memset(buffer, 0, sizeof(buffer));
			ret = read(child_to_parent[0], buffer, sizeof(buffer));
			if (ret > 0)
			{
				printf("PARENT RECV: [%s]\n", buffer);
			}
			else
			{
				break;
			}
		}
	}

	close(sock_fd);
	exit (0);
}
Beispiel #7
0
/*
 * put_file
 */
void put_file( char *fname)
{
   FILE *fp=NULL;
   int fd, nTotal=0, nBytesRead=0, retval, aborted=0;
   char *abortstr = "ABORrn", ch;
  /* void (*OldHandler)(int); */
   if( !fname || ! (*fname)) {
      printf("No file specified.n");
      return;
   }
   if(! (fp=fopen(fname,(bMode==ASCII) ? "rt" : "rb"))) {
      perror("file open");
      return;
   }
   if( get_listen_socket() < 0) {
       fclose(fp);
       return;
   }
   
   /*
    * send command to server & read reply
    */
   sprintf(tmp_buffer,"STOR %srn",fname);
   if(!send_ctrl_msg(tmp_buffer,strlen(tmp_buffer))) {
      fclose(fp);
      return;
   }
   int m=get_host_reply();
   if(m==550)
return;
   /*
    * accept server connection
    */
   if( accept_connection() <= 0) {
       fclose(fp);
       return;
   }
   /* 
    * now send file
    */
   
   fd = fileno(fp);
   printf("Type q and hit return to abortrn");
   while( (nBytesRead=read(fd,tmp_buffer,1024)) > 0) {
      send_data_msg(tmp_buffer,nBytesRead);
      nTotal+=nBytesRead;
      printf("%s : %d sentr",fname,nTotal);
   if( check_input() ) {
        ch = getchar();
        if( ch != 'n') {
        while( getchar() != 'n') ;      /* read 'til new line */
        }
        if( ch == 'q') 
        aborted = 1;
   }
   /*
    * send an abort command to server if we aborted.
    */
   if( aborted ) {
  
   printf("rnAbort: Waiting for server to finish.");
   send_ctrl_msg(abortstr,strlen(abortstr));
   break;
   }
   }
   /*(void)signal(SIGINT,OldHandler); */
   printf("rn");
   /*
    * close data connection
    */
   close_data_connection(hDataSocket);
   close(fd);
   get_host_reply();
}
Beispiel #8
0
int main(int argc, char const *argv[])
{

    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    int socket_server;
    int socket_client;

    char in_buf[MSGL];
    char out_buf[MSGL];

    bzero(in_buf, MSGL);
    bzero(out_buf, MSGL);


    socket_server = create_socket();


    bzero((char *) &server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);


    bind_socket(socket_server, server_addr);


    listen(socket_server, 5);


    socket_client = accept_connection(socket_server, client_addr);




    while(1)
    {   
        //wait for reply
        printf("waiting for reply...\n");
        bzero(in_buf, MSGL);
        get_message(socket_client, in_buf);
        printf("client sayz: %s\n", in_buf);

        //get input
        printf("Message to client: ");
        bzero(out_buf, MSGL);
        fgets(out_buf, MSGL, stdin);
        if (strcmp(out_buf,"quit\n") == 0){
            break;
        }

        //send input
        printf("sending: %s\n", out_buf);
        send_message(socket_client, out_buf);
    }


    close(socket_client);
    close(socket_server);


    return 0;
}
Beispiel #9
0
/* wait for incoming connection requests */
static void wait_for_connections(void) {
	struct sockaddr_in myname;
	int sock = 0;
	int flag = 1;

	int rval;
	int success = 0;
	struct addrinfo addrinfo;
	struct addrinfo *res, *r;

	memset(&addrinfo, 0, sizeof(addrinfo));
	addrinfo.ai_family = PF_UNSPEC;
	addrinfo.ai_socktype = SOCK_STREAM;
	addrinfo.ai_protocol = IPPROTO_TCP;

	if (!server_address || !strlen(server_address)) {
		server_address = NULL;
		addrinfo.ai_flags = AI_PASSIVE;
	}
	if (rval = getaddrinfo(server_address, server_port, &addrinfo, &res) != 0) {
		syslog(LOG_ERR, "Invalid server_address (%d: %s)", errno, strerror(errno));
		do_exit(STATE_CRITICAL);
	} else {
		for (r = res; r; r = r->ai_next) {
			sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
			/* socket should be non-blocking */
			fcntl(sock, F_SETFL, O_NONBLOCK);
			/* set the reuse address flag so we don't get errors when restarting */
			flag = 1;
			if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) {
				syslog(LOG_ERR, "Could not set reuse address option on socket!\n");
				do_exit(STATE_UNKNOWN);
			}
			if (bind(sock, r->ai_addr, r->ai_addrlen) < 0) {
				syslog(LOG_ERR, "Network server bind failure (%d: %s)\n", errno, strerror(errno));
				(void) close(sock);
			} else {
				success = 1;
				break;
			}
		}
		freeaddrinfo(res);
		if (success == 0) {
			do_exit(STATE_CRITICAL);
		}
	}

	/* open the socket for listening */
	if (listen(sock, SOMAXCONN) < 0) {
		syslog(LOG_ERR, "Network server listen failure (%d: %s)\n", errno, strerror(errno));
		do_exit(STATE_CRITICAL);
	}

	/* log info to syslog facility */
	syslog(LOG_NOTICE, "Starting up daemon");

	if (debug == TRUE) {
		syslog(LOG_DEBUG, "Listening for connections on port %d\n", htons(myname.sin_port));
	}

	/* socket should be non-blocking for mult-process daemon */
	if (mode == MULTI_PROCESS_DAEMON)
		fcntl(sock, F_SETFL, O_NONBLOCK);

	/* listen for connection requests */
	if (mode == SINGLE_PROCESS_DAEMON)
		register_read_handler(sock, accept_connection, NULL);
	while (1) {

		/* bail out if necessary */
		if (sigrestart == TRUE || sigshutdown == TRUE) {
			/* close the socket we're listening on */
			close(sock);
			break;
		}

		/* accept a new connection */
		if (mode == MULTI_PROCESS_DAEMON)
			accept_connection(sock, NULL);

		/* handle the new connection (if any) */
		else
			handle_events();
	}

	return;
}
Beispiel #10
0
Datei: tgc.c Projekt: BwRy/tgcd
/*-----------------------------------------------------------------------------
  Become a port forwarder
------------------------------------------------------------------------------*/
int tgc_pf(TGC *tgc)
{
	struct sockaddr_in 	addr;
	socklen_t    		in_addrlen = sizeof(addr);
	fd_set 			rfds, reads;
	int			sdi, sdx, rc=0;
	socket_pair_list	*conn, *prev_conn;
	char			ip[16];


	signal(SIGCLD, SIG_DFL); // to avoid zombie process

 	if ( (tgc->sdi_accept=open_server_socket(tgc->node.pf.port)) < 0 ) {
		PRINT_LOG(1, "Can't bind to port %d", tgc->node.pf.port);
		return E_TGC_NOCANDO;
	}
	
	PRINT_LOG(3, "waiting for incomming connections on port %d ...", tgc->node.pf.port);

	FD_ZERO(&rfds);
	FD_SET(tgc->sdi_accept, &rfds);

	while (1) {

		reads = rfds;
		if ( select(FD_SETSIZE, &reads, NULL, NULL, NULL) < 0 ) 
			continue;

		if (FD_ISSET(tgc->sdi_accept, &reads)) {
		
			sdi = accept_connection(tgc->sdi_accept, (struct sockaddr_in *) &addr, 
					                     (socklen_t *)&in_addrlen);

			if (sdi==-1) {
				if (errno==EINTR)
					continue;

				PRINT_LOG(0, "Error accepting new connection!");
				close_connection(&(tgc->sdi_accept));
				break; //exit
			}

			// run the filter
			strncpy(ip, inet_ntoa(addr.sin_addr), 16);
			PRINT_LOG(3, "Received a client from %s", ip);
			if (!tgc_check_filter(tgc, ip)) {
				close_connection(&sdi);
				sdi = -1;
				continue;
			}

			if ( (sdx=connect_server(tgc->node.pf.dst_host, tgc->node.pf.dst_port))<0 ) {
				PRINT_LOG(1, "failed connecting to %s:%d", tgc->node.pf.dst_host, tgc->node.pf.dst_port);
				close_connection(&sdi);
				sdi = -1;
				continue;
			}
			PRINT_LOG(3, "connected to the server");

			if (tgc->method == TGC_METHOD_SELECT) {
				if (!tgc_add_list( &(tgc->pairs), sdi, sdx)) {
					FD_SET(sdi, &rfds);
					FD_SET(sdx, &rfds);
					PRINT_LOG(3, "Added socket pairs to the list");
					continue;
				}
			} else { //fork method
#ifdef HAVE_FORK
				if (fork()==0) { //child
					close_connection(&(tgc->sdi_accept));
					tgc_pump(sdi, sdx, tgc->buf, tgc->key);
					break;
				} else {// parent
					close_connection(&sdi);
					close_connection(&sdx);
					PRINT_LOG(3, "waiting for incomming connections on port %d again...", tgc->node.pf.port);
				}
#endif
			}
		}

		// pump the data for each and every connection pairs
		if (tgc->method==TGC_METHOD_SELECT) {
			conn = tgc->pairs;
			while (conn) {
				if (FD_ISSET(conn->sdi , &reads)) { // from client
					if ( (rc=tgc_rxtx(conn->sdi, conn->sdx, tgc->buf, tgc->key)) < 0 ) {
						PRINT_LOG(3, "Error reading socket, closing pair");
						FD_CLR(conn->sdi, &rfds);
						FD_CLR(conn->sdx, &rfds);
						close_connection(&(conn->sdi));
						close_connection(&(conn->sdx));
						prev_conn = conn;
						conn = conn->next;
						tgc_remove_list( &(tgc->pairs), prev_conn);
						continue;
					}
				}

				if (FD_ISSET(conn->sdx, &reads)) { // from server
					if ( (rc=tgc_rxtx(conn->sdx, conn->sdi, tgc->buf, tgc->key)) < 0 ) {
						PRINT_LOG(3, "Error reading socket, closing pair.");
						FD_CLR(conn->sdi, &rfds);
						FD_CLR(conn->sdx, &rfds);
						close_connection(&(conn->sdi));
						close_connection(&(conn->sdx));
						prev_conn = conn;
						conn=conn->next;
						tgc_remove_list( &(tgc->pairs), prev_conn);
						continue;
					}
				}
				conn=conn->next;
			}
		}
	}
	return E_TGC_NOCANDO;
}
Beispiel #11
0
int engine_read_message(time_t delay)
{
    struct pollfd events[ENGINE_MAX_EVENTS], *pevent;
    struct dvpoll dopoll;
    int nfds, i, numloops = 0, eventsfull;
    unsigned int fdflags, fdevents;
    int          fdtype;
    void         *fdvalue;
    aClient      *cptr;   
    aListener    *lptr;

    dopoll.dp_fds = events;
    dopoll.dp_nfds = ENGINE_MAX_EVENTS;
    dopoll.dp_timeout = delay;
    do
    {
        nfds = ioctl(devpoll_id, DP_POLL, &dopoll);

        if (nfds < 0)
        {
            if (errno == EINTR || errno == EAGAIN)
                return -1; 

            report_error("ioctl(devpoll): %s:%s", &me);
            sleep(5);
            return -1;
        }
        eventsfull = nfds == ENGINE_MAX_EVENTS;

        if (delay || numloops) 
            NOW = timeofday = time(NULL);
        numloops++;

        for (i = 0, pevent = events; i < nfds; i++, pevent++)
        {
            fdevents = (unsigned int)get_fd_internal(pevent->fd);
            if (pevent->fd != -1)
            {
                int rr = (pevent->revents & (POLLIN|POLLHUP|POLLERR)) && (fdevents & (POLLIN|POLLHUP|POLLERR));
                int rw = (pevent->revents & POLLOUT) && (fdevents & POLLOUT);

                get_fd_info(pevent->fd, &fdtype, &fdflags, &fdvalue);

                switch (fdtype)
                {
                case FDT_NONE:
                    break;

                case FDT_AUTH:
                    cptr = (aClient*)fdvalue;
                    if (rr) read_authports(cptr);
                    if (rw && cptr->authfd >= 0) send_authports(cptr);
                    check_client_fd(cptr);
                    break;

                case FDT_LISTENER:
                    lptr = (aListener*)fdvalue;
                    if (rr) accept_connection(lptr);
                    break;

                case FDT_RESOLVER:
                    do_dns_async();
                    break;

                case FDT_CLIENT:
                    cptr = (aClient*)fdvalue;
                    readwrite_client(cptr, rr, rw);
                    break;

                case FDT_CALLBACKP:
                    {
                        struct fd_callbackp *fdcb = (struct fd_callbackp*)fdvalue;

                        fdcb->rdf = rr;
                        fdcb->wrf = rw;
                        (*fdcb->callback)(fdcb);
                        break;
                    }

                default:
                    abort();
                }
            }
        }
    } while (eventsfull && numloops < ENGINE_MAX_LOOPS);

    return 0;
}
Beispiel #12
0
Datei: tgc.c Projekt: BwRy/tgcd
/*-----------------------------------------------------------------------------
 * LL node
------------------------------------------------------------------------------*/
int tgc_ll(TGC *tgc)
{
	fd_set		rfds, reads;
	struct	sockaddr_in addr;
	socklen_t 	in_addrlen = sizeof(addr);
	int		rc=0, sdi, sdx, sd;
	socket_pair_list	*conn, *prev_conn;
	char		cmd;
	struct in_addr	cc_addr = { 0 } ;
	char		ip[16];
	int		close_control = 0;
	struct timeval	tv;

	if (!tgc)
		return E_TGC_IE;

	if ( (tgc->sdx_accept=open_server_socket(tgc->node.ll.port)) < 0 ) {
		PRINT_LOG(1, "Can't bind to port %d", tgc->node.ll.port);
		return E_TGC_NOCANDO;
	}

	if ( (tgc->sdi_accept=open_server_socket(tgc->node.ll.ll_port)) < 0 ) {
		PRINT_LOG(1, "Can't bind to port %d", tgc->node.ll.ll_port);
		return E_TGC_NOCANDO;
	}

	PRINT_LOG(3, "waiting for client on port %d ...", tgc->node.ll.port);
	PRINT_LOG(3, "waiting for CC on %d!", tgc->node.ll.ll_port);
	
	FD_ZERO(&rfds);
	FD_SET(tgc->sdi_accept, &rfds);
	FD_SET(tgc->sdx_accept, &rfds);

	tgc->node.ll.control_sd = -1;

	while(1) {
		tv.tv_sec = tgc->node.ll.timeout;
		tv.tv_usec = 0;
		reads = rfds;
		if ( (rc = select(FD_SETSIZE, &reads, NULL, NULL, &tv)) < 0 )
			continue;
		if (rc == 0 && tgc->node.ll.control_sd >= 0) {
			PRINT_LOG(1, "time out, closing control connection");
			FD_CLR(tgc->node.ll.control_sd, &rfds);
			close_connection(&(tgc->node.ll.control_sd));
			close_control = 0;
			continue;
		}

		if (FD_ISSET(tgc->sdx_accept, &reads)) { // incoming client connection
			sdx = accept_connection(tgc->sdx_accept, (struct sockaddr_in *)&addr, 
				       		(socklen_t *)&in_addrlen);

			if (sdx==-1) {
				if (errno==EINTR)
					continue;
				PRINT_LOG(1, "Error accepting new client connection");
				continue; //break; // exit
			}

			if (tgc->node.ll.control_sd<0) { 
				//client came in while there is no control connection, so we close it
				PRINT_LOG(3, "rejecting client connection before control connection received ");
				close_connection(&sdx);
				continue;
			}

			strncpy(ip, inet_ntoa(addr.sin_addr), 16);
			PRINT_LOG(3, "client (%s) connected on %d!", ip, tgc->node.ll.ll_port);
			// run the filter
			if (!tgc_check_filter(tgc, ip)) {
				close_connection(&sdx);
				continue;
			}
			PRINT_LOG(3, "Ask CC for a connection for the new client");

			if (tgc_send(tgc->node.ll.control_sd, TGC_COMM_CCC)>=0) {
				if (tgc_add_queue( &(tgc->node.ll.socketq), sdx)<0) {
					PRINT_LOG(1, "Error adding socket to queue!");
					close_connection(&sdx);
					return E_TGC_NOCANDO;
				}
				PRINT_LOG(5, "client connection added to the queue");
		 	} else 
				close_connection(&sdx); // couldn't ask CC for a new connection, close the client
		} 
		
		if (FD_ISSET(tgc->sdi_accept, &reads)) { // from CC
			sdi = accept_connection(tgc->sdi_accept, (struct sockaddr_in *)&addr, 
				       (socklen_t *)&in_addrlen);

			if (sdi==-1) {
				if (errno==EINTR)
					continue;
				PRINT_LOG(1, "Error accepting new CC connection");
				break; // exit
			}

			strncpy(ip, inet_ntoa(addr.sin_addr), 16);
			PRINT_LOG(3, "CC connected from %s", ip);
			// run the filter
			if (!tgc_check_filter(tgc, ip)) {
				close_connection(&sdi);
                                continue;
			}

			if (tgc->node.ll.control_sd<0) { 
				// it's the control connection
				tgc->node.ll.control_sd = sdi;
				cc_addr.s_addr = addr.sin_addr.s_addr;
				FD_SET(sdi, &rfds);
				PRINT_LOG(4, "Control connection established");
			} else { // it's a normal CC connection
				if (addr.sin_addr.s_addr!=cc_addr.s_addr || !tgc->node.ll.socketq) {
					// if this CC's address is different from control_sd's OR
					// if there are no client connections waiting in the queue
					// we reject the CC
					close_connection(&sdi);
					PRINT_LOG(1, "Suspicious CC rejected");
				} else { //everything seems good, lets do our thing!
					sdx = tgc_remove_queue(&(tgc->node.ll.socketq));
					if (sdx>=0) {
						if (tgc->method==TGC_METHOD_SELECT) {
							if (!tgc_add_list( &(tgc->pairs), sdi, sdx)) {
								FD_SET(sdi, &rfds);
								FD_SET(sdx, &rfds);
							} 
						} else {
#ifdef HAVE_FORK
							// FORK
							if (fork()==0) { // child
								close_connection(&(tgc->sdi_accept));
								close_connection(&(tgc->sdx_accept));
								close_connection(&(tgc->node.ll.control_sd));
								tgc_pump(sdi, sdx, tgc->buf, tgc->key);
								break; //exit(0);
							} else { // parent
								close_connection(&sdi);
								close_connection(&sdx);
							}
#endif
						}
					}
				}
			}
		} 
		
		if (tgc->node.ll.control_sd>=0 && FD_ISSET(tgc->node.ll.control_sd, &reads)) {
			close_control = 0;
			if (tgc_read(tgc->node.ll.control_sd, &cmd) == E_TGC_OK) {
				switch (cmd) {
					case TGC_COMM_PING:
						PRINT_LOG(2, "Received a ping from CC");
						if (tgc_send(tgc->node.ll.control_sd, TGC_COMM_PING)<0) {
							PRINT_LOG(1, "Internal Error: can't write to control connection");
							FD_CLR(tgc->node.ll.control_sd, &rfds);
							close_connection(&(tgc->node.ll.control_sd));
							tgc->node.ll.control_sd = -1;
							continue;
						}
						break;
					case TGC_COMM_CLOSE:
						PRINT_LOG(3, "CC wants us to close the lingering client connection!");
						if ((sd=tgc_remove_queue(&(tgc->node.ll.socketq)))>=0)
							close_connection(&sd);
						break;
					default:
						PRINT_LOG(1, "Internal Error: Uknown code (0x%x) recieved from CC!", cmd);
						close_control = 1;
				}
			} else {
				close_control = 1;
			}

			if (close_control) {
				PRINT_LOG(1, "closing control connection");
				FD_CLR(tgc->node.ll.control_sd, &rfds);
				close_connection(&(tgc->node.ll.control_sd));
				tgc->node.ll.control_sd = -1;
				close_control = 0;
				continue;
			}
		}

		// pump the data for each and every connection pairs
		if (tgc->method==TGC_METHOD_SELECT) {
			conn = tgc->pairs; 
			while (conn) {
				if (FD_ISSET(conn->sdi , &reads)) { // from CC?
					if ( (rc=tgc_rxtx(conn->sdi, conn->sdx, tgc->buf, tgc->key)) < 0 ) {
						FD_CLR(conn->sdi, &rfds);
						FD_CLR(conn->sdx, &rfds);
						close_connection(&(conn->sdi));
						close_connection(&(conn->sdx));
						prev_conn = conn;
						conn = conn->next;
						tgc_remove_list( &(tgc->pairs), prev_conn);
						continue;
					}
				}

				if (FD_ISSET(conn->sdx, &reads)) { // from client?
					if ( (rc=tgc_rxtx(conn->sdx, conn->sdi, tgc->buf, tgc->key)) < 0 ) {
						FD_CLR(conn->sdi, &rfds);
						FD_CLR(conn->sdx, &rfds);
						close_connection(&(conn->sdi));
						close_connection(&(conn->sdx));
						prev_conn = conn;
						conn = conn->next;
						tgc_remove_list( &(tgc->pairs), prev_conn);
						continue;
					}
				}
				conn=conn->next;
			}
		}
	}
	
	return 0;
}
Beispiel #13
0
static void
rtpp_cmd_acceptor_run(void *arg)
{
    struct rtpp_cmd_async_cf *cmd_cf;
    struct pollfd *tp;
    struct rtpp_cmd_pollset *psp;
    struct rtpp_cmd_accptset *asp;
    struct rtpp_cmd_connection *rcc;
    int nready, controlfd, i, tstate;

    cmd_cf = (struct rtpp_cmd_async_cf *)arg;
    psp = &cmd_cf->pset;
    asp = &cmd_cf->aset;

    for (;;) {
#ifndef LINUX_XXX
        nready = poll(asp->pfds, asp->pfds_used, INFTIM);
#else
	nready = poll(asp->pfds, asp->pfds_used, 100);
#endif
        pthread_mutex_lock(&cmd_cf->cmd_mutex);
        tstate = cmd_cf->tstate_acceptor;
        pthread_mutex_unlock(&cmd_cf->cmd_mutex);
        if (tstate == TSTATE_CEASE) {
            break;
        }
        if (nready <= 0)
            continue;
        for (i = 0; i < asp->pfds_used; i++) {
            if ((asp->pfds[i].revents & POLLIN) == 0) {
                continue;
            }
            pthread_mutex_lock(&psp->pfds_mutex);
            if (psp->pfds_used >= RTPC_MAX_CONNECTIONS) {
                pthread_mutex_unlock(&psp->pfds_mutex);
                continue;
            }
            controlfd = accept_connection(cmd_cf->cf_save, asp->pfds[i].fd);
            if (controlfd < 0) {
                pthread_mutex_unlock(&psp->pfds_mutex);
                continue;
            }
            tp = realloc(psp->pfds, sizeof(struct pollfd) * (psp->pfds_used + 1));
            if (tp == NULL) {
                pthread_mutex_unlock(&psp->pfds_mutex);
                close(controlfd); /* Yeah, sorry, please try later */
                continue;
            }
            rcc = rtpp_cmd_connection_ctor(controlfd, controlfd, asp->csocks[i]);
            if (rcc == NULL) {
                pthread_mutex_unlock(&psp->pfds_mutex);
                close(controlfd); /* Yeah, sorry, please try later */
                continue;
            }
            psp->pfds = tp;
            psp->pfds[psp->pfds_used].fd = controlfd;
            psp->pfds[psp->pfds_used].events = POLLIN | POLLERR | POLLHUP;
            psp->pfds[psp->pfds_used].revents = 0;
            psp->rccs[psp->pfds_used] = rcc;
            psp->pfds_used++;
            pthread_mutex_unlock(&psp->pfds_mutex);
            rtpp_command_async_wakeup(&cmd_cf->pub);
        }
    }
}
Beispiel #14
0
void select_loop(int listenfd)
{

    /* Common vars */

    char socket_pair_buffer[2];
    int nbytes;

    char remote_ip[INET6_ADDRSTRLEN];

    int fd, fdmax;
    int done = 0;

#ifndef NOPE_MAX_CON_CONS
    FdData fdDataList[MAX_NO_FDS];
#else
    FdData *fdDataList;
    LOG_ERROR_ON_NULL(fdDataList =
                      malloc(sizeof(FdData) * MAX_NO_FDS),
                      "Can't malloc() on fdDataList");
#endif

    struct timeval tv;
    int poll_timeout = POLL_TIMEOUT;
    tv.tv_sec = 0;
    tv.tv_usec = POLL_TIMEOUT * 1000;

    /* keep track of the biggest file descriptor */
    fdmax = listenfd;           /* so far, it's this one */

    for (fd = 0; fd < fdmax; fd++) {
        fdDataList[fd].state = STATE_PRE_REQUEST;
    }
#ifdef NOPE_EPOLL

    int eventfd;
    struct epoll_event event;
    struct epoll_event *events;

    eventfd = epoll_create(1234);       /*Number is ignored */

    if (eventfd == -1) {
        perror("epoll_create");
        return;
    }

    event.data.fd = listenfd;
    event.events = EPOLLIN | EPOLLET;

    if (epoll_ctl(eventfd, EPOLL_CTL_ADD, listenfd, &event)) {
        perror("epoll_ctl");
        return;
    }
#ifdef NOPE_THREADS
    /* Socket Pair */
    event.data.fd = socketpair_fd[1];
    event.events = EPOLLIN | EPOLLET;

    if (epoll_ctl(eventfd, EPOLL_CTL_ADD, socketpair_fd[1], &event)) {
        perror("epoll_ctl_socketpair");
        return;
    }
#endif

    events = calloc(MAX_EVENTS, sizeof event);
    /* Epoll main loop */
    while (1) {

#ifdef NOPE_THREADS
        cleaner_thread();       /*Run the thread clearer */
#endif
        int n, e;
        dbgprintf(KCYN "Waiting for events \n" KNRM);
        n = epoll_wait(eventfd, events, MAX_EVENTS, poll_timeout);
        dbgprintf(KCYN "Detected %d events \n" KNRM, n);
        for (e = 0; e < n; e++) {
            if ((events[e].events & EPOLLERR) ||
                (events[e].events & EPOLLHUP) || (!(events[e].events & EPOLLIN))) {
                fprintf(stderr, "epoll error detected in line %d\n", __LINE__);
                close(events[e].data.fd);
                continue;
            }

            else if (listenfd == events[e].data.fd) {
                while (1) {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int newfd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

                    in_len = sizeof in_addr;

                    newfd = accept(listenfd, &in_addr, &in_len);

                    if (newfd == -1) {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
                            /* We have processed all incoming  connections. */
                            break;
                        } else {
                            perror("accept");
                            break;
                        }
                    } else if (newfd >= MAX_NO_FDS) {
                        /* Process some events before accepting more */
                        fprintf(stderr, "Reached MAX_NO_FDS at %d\n", newfd);
                        break;
                    }

                    if (getnameinfo(&in_addr, in_len,
                                    hbuf, sizeof hbuf,
                                    sbuf, sizeof sbuf,
                                    NI_NUMERICHOST | NI_NUMERICSERV) == 0) {

                        /*dbgprintf("accept()ed connection on  %d (host=%s, port=%s)\n",
                           newfd, hbuf, sbuf); */

                        fdDataList[newfd].state = STATE_PRE_REQUEST;
                        new_fd_data(&fdDataList[newfd]);
                    }

                    /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */
                    if (FCNTL_NONBLOCK(newfd) < 0) {
                        perror("fcntl");
                        return;
                    }

                    event.data.fd = newfd;
                    event.events = EPOLLIN | EPOLLET;
                    if (epoll_ctl(eventfd, EPOLL_CTL_ADD, newfd, &event) < 0) {
                        perror("epoll_ctl");
                        return;
                    }
                }
                continue;
            }
#ifdef 	NOPE_THREADS
            else if (socketpair_fd[1] == events[e].data.fd) {
                nbytes = read(events[e].data.fd, socket_pair_buffer, 1);
                dbgprintf(KCYN "SocketPair Read %d : %d\n" KCYN, events[e].data.fd,
                          nbytes);
                if (nbytes == -1) {
                    if (errno != EAGAIN) {      /* EAGAINs we have read all data */
                        perror("read");
                    }
                }
            }
#endif
            else {
                fd = events[e].data.fd;
                while (1) {
                    nbytes =
                        read(fd, fdDataList[fd].readBuffer + fdDataList[fd].readBufferIdx,
                             MAX_REQUEST_SIZE - fdDataList[fd].readBufferLen);
                    dbgprintf(KCYN "Read %d : %d\n" KCYN, fd, nbytes);
                    if (nbytes == -1) {
                        if (errno != EAGAIN) {  /* EAGAINs we have read all data */
                            perror("read");
                            done = true;
                        }
                        break;
                    } else if (nbytes == 0) {
                        done = true;
                        break;
                    }
                    if ((done = state_machine(fdDataList, fd, nbytes, NULL))) {
                        break;
                    }
                }

                if (done) {
                    clear_connection_baggage(fdDataList, fd, NULL);
                }

            }
        }
    }
#else
    /* Select stuff
     * Thank you Brian "Beej Jorgensen" Hall */
    fd_set master;              // pMaster file descriptor list
    fd_set read_fds;            // temp file descriptor list for select()

    FD_ZERO(&master);           /* clear the pMaster and temp sets */
    FD_ZERO(&read_fds);

    /* add the listener to the master set */
    FD_SET(listenfd, &master);

    /* Select main loop */
    while (1) {

#ifdef NOPE_THREADS
        cleaner_thread();       /*Run the thread clearer */
#endif

        read_fds = master;      /* copy it */

        dbgprintf(KRED "Select blocking\n" KNRM);
        if (select(fdmax + 1, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(4);
        }
        dbgprintf(KRED "Select blocked\n" KNRM);
        /* run through the existing connections looking for data to read */
        for (fd = 0; fd <= fdmax; fd++) {
            if (!FD_ISSET(fd, &read_fds))       // we got one!!
                continue;
            if (fd == listenfd) {
                accept_connection(fdDataList, listenfd, remote_ip, &fdmax, &master);
                break;
            }
            nbytes =
                recv(fd, fdDataList[fd].readBuffer + fdDataList[fd].readBufferIdx,
                     MAX_REQUEST_SIZE - fdDataList[fd].readBufferLen, 0);
            /* read failure */
            if (nbytes <= 0) {
                shutdown_connection(fdDataList, fd, nbytes, &master);
                break;
            }

            /* State Machine */
            done = state_machine(fdDataList, fd, nbytes, &master);
            if (done) {
                clear_connection_baggage(fdDataList, fd, &master);
            }
        }                       // END looping through file descriptors
    }                           // END for(;;)--and you thought it would never end!
#endif
    return;
}
Beispiel #15
0
static int main_loop (void *arg) {
  ICI *d = arg;
  struct sockaddr_in addr;
  int rv = 0;
#ifndef HAVE_WINDOWS
  signal(SIGPIPE, SIG_IGN);
#endif

  if ((d->fd = create_server_socket()) < 0) {rv = -1; goto daemon_end;}
  server_sockaddr(d, &addr);
  if(server_bind(d, addr)) {rv = -1; goto daemon_end;}

  if (d->uid || d->gid) {
    if (drop_privileges(d->uid, d->gid)) {rv = -1; goto daemon_end;}
  }

  if (access(d->docroot, R_OK)) {
    dlog(DLOG_CRIT, "SRV: can not read document-root (permission denied)\n");
    rv = -1;
    goto daemon_end;
  }

  global_shutdown = 0;
#ifdef CATCH_SIGNALS
  signal(SIGHUP, catchsig);
  signal(SIGINT, catchsig);
#endif

#ifdef USAGE_FREQUENCY_STATISTICS
  d->stat_start = time(NULL);
#endif

  while(d->run && !global_shutdown) {
    fd_set rfds;
    struct timeval tv;

    tv.tv_sec = 1; tv.tv_usec = 0;
    FD_ZERO(&rfds);
    FD_SET(d->fd, &rfds);

    // select() returns 0 on timeout, -1 on error.
    if((select(d->fd+1, &rfds, NULL, NULL, &tv))<0) {
      dlog(DLOG_WARNING, "SRV: unable to select the socket: %s\n", strerror(errno));
      if (errno != EINTR) {
        rv = -1;
        goto daemon_end;
      } else {
        continue;
      }
    }

    char *rh = NULL;
    unsigned short rp = 0;
    int s = -1;
    if(FD_ISSET(d->fd, &rfds)) {
      s = accept_connection(d, &rh, &rp);
    } else {
      d->age++;
#ifdef USAGE_FREQUENCY_STATISTICS
      /* may not be accurate, select() may skip a second once in a while */
      d->req_stats[time(NULL) % FREQ_LEN] = 0;
#endif
    }

    if (s >= 0) {
      start_child(d, s, rh, rp);
      d->age=0;
#ifdef USAGE_FREQUENCY_STATISTICS
      d->stat_count++;
      d->req_stats[time(NULL) % FREQ_LEN]++;
#endif
      continue; // no need to check age.
    }

    if (d->timeout > 0 && d->age > d->timeout) {
      dlog(DLOG_INFO, "SRV: no request since %d seconds shutting down.\n", d->age);
      global_shutdown = 1;
    }
  }

#ifdef CATCH_SIGNALS
  signal(SIGHUP, SIG_DFL);
  signal(SIGINT, SIG_DFL);
#endif

  /* wait until all connections are closed */
  int timeout = 31;

  if (d->num_clients > 0)
    dlog(DLOG_INFO, "SRV: server shutdown procedure: waiting up to %i sec for clients to disconnect..\n", timeout-1);

#ifdef VERBOSE_SHUTDOWN
  printf("\n");
#endif
  while (d->num_clients> 0 && --timeout > 0) {
#ifdef VERBOSE_SHUTDOWN
    if (timeout%3 == 0) printf("SRV: shutdown timeout (%i)    \r", timeout); fflush(stdout);
#endif
    mymsleep(1000);
  }
#ifdef VERBOSE_SHUTDOWN
  printf("\n");
#endif

  if (d->num_clients > 0) {
    dlog(DLOG_WARNING, "SRV: Terminating with %d active connections.\n", d->num_clients);
  } else {
    dlog(DLOG_INFO, "SRV: Closed all connections.\n");
  }

daemon_end:
  close(d->fd);
  dlog(DLOG_CRIT, "SRV: server shut down.\n");

  d->run = 0;
  if (d->local_addr) free(d->local_addr);
  pthread_mutex_destroy(&d->lock);
  free(d);
#ifdef HAVE_WINDOWS
  WSACleanup();
#endif
  return(rv);
}
Beispiel #16
0
static void process_clients(void)
{
	int32_t i, k, j, rc, pfdcount = 0;
	struct s_client *cl;
	struct s_reader *rdr;
	struct pollfd *pfd;
	struct s_client **cl_list;
	struct timeb start, end;  // start time poll, end time poll
	uint32_t cl_size = 0;

	uchar buf[10];

	if(pipe(thread_pipe) == -1)
	{
		printf("cannot create pipe, errno=%d\n", errno);
		exit(1);
	}

	cl_size = chk_resize_cllist(&pfd, &cl_list, 0, 100);

	pfd[pfdcount].fd = thread_pipe[0];
	pfd[pfdcount].events = POLLIN | POLLPRI;
	cl_list[pfdcount] = NULL;

	while(!exit_oscam)
	{
		pfdcount = 1;

		//connected tcp clients
		for(cl = first_client->next; cl; cl = cl->next)
		{
			if(cl->init_done && !cl->kill && cl->pfd && cl->typ == 'c' && !cl->is_udp)
			{
				if(cl->pfd && !cl->thread_active)
				{
					cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
					cl_list[pfdcount] = cl;
					pfd[pfdcount].fd = cl->pfd;
					pfd[pfdcount++].events = POLLIN | POLLPRI;
				}
			}
			//reader:
			//TCP:
			//  - TCP socket must be connected
			//  - no active init thread
			//UDP:
			//  - connection status ignored
			//  - no active init thread
			rdr = cl->reader;
			if(rdr && cl->typ == 'p' && cl->init_done)
			{
				if(cl->pfd && !cl->thread_active && ((rdr->tcp_connected && rdr->ph.type == MOD_CONN_TCP) || (rdr->ph.type == MOD_CONN_UDP)))
				{
					cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
					cl_list[pfdcount] = cl;
					pfd[pfdcount].fd = cl->pfd;
					pfd[pfdcount++].events = (POLLIN | POLLPRI);
				}
			}
		}

		//server (new tcp connections or udp messages)
		for(k = 0; k < CS_MAX_MOD; k++)
		{
			struct s_module *module = &modules[k];
			if((module->type & MOD_CONN_NET))
			{
				for(j = 0; j < module->ptab.nports; j++)
				{
					if(module->ptab.ports[j].fd)
					{
						cl_size = chk_resize_cllist(&pfd, &cl_list, cl_size, pfdcount);
						cl_list[pfdcount] = NULL;
						pfd[pfdcount].fd = module->ptab.ports[j].fd;
						pfd[pfdcount++].events = (POLLIN | POLLPRI);
					}
				}
			}
		}

		if(pfdcount >= 1024)
			{ cs_log("WARNING: too many users!"); }
		cs_ftime(&start); // register start time
		rc = poll(pfd, pfdcount, 5000);
		if(rc < 1) { continue; }
		cs_ftime(&end); // register end time

		for(i = 0; i < pfdcount && rc > 0; i++)
		{
			if(pfd[i].revents == 0) { continue; }  // skip sockets with no changes
			rc--; //event handled!
			cs_log_dbg(D_TRACE, "[OSCAM] new event %d occurred on fd %d after %"PRId64" ms inactivity", pfd[i].revents,
						  pfd[i].fd, comp_timeb(&end, &start));
			//clients
			cl = cl_list[i];
			if(cl && !is_valid_client(cl))
				{ continue; }

			if(pfd[i].fd == thread_pipe[0] && (pfd[i].revents & (POLLIN | POLLPRI)))
			{
				// a thread ended and cl->pfd should be added to pollfd list again (thread_active==0)
				int32_t len = read(thread_pipe[0], buf, sizeof(buf));
				if(len == -1)
				{
					cs_log_dbg(D_TRACE, "[OSCAM] Reading from pipe failed (errno=%d %s)", errno, strerror(errno));
				}
				cs_log_dump_dbg(D_TRACE, buf, len, "[OSCAM] Readed:");
				continue;
			}

			//clients
			// message on an open tcp connection
			if(cl && cl->init_done && cl->pfd && (cl->typ == 'c' || cl->typ == 'm'))
			{
				if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
				{
					//client disconnects
					kill_thread(cl);
					continue;
				}
				if(pfd[i].fd == cl->pfd && (pfd[i].revents & (POLLIN | POLLPRI)))
				{
					add_job(cl, ACTION_CLIENT_TCP, NULL, 0);
				}
			}


			//reader
			// either an ecm answer, a keepalive or connection closed from a proxy
			// physical reader ('r') should never send data without request
			rdr = NULL;
			struct s_client *cl2 = NULL;
			if(cl && cl->typ == 'p')
			{
				rdr = cl->reader;
				if(rdr)
					{ cl2 = rdr->client; }
			}

			if(rdr && cl2 && cl2->init_done)
			{
				if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
				{
					//connection to remote proxy was closed
					//oscam should check for rdr->tcp_connected and reconnect on next ecm request sent to the proxy
					network_tcp_connection_close(rdr, "closed");
					rdr_log_dbg(rdr, D_READER, "connection closed");
				}
				if(cl2->pfd && pfd[i].fd == cl2->pfd && (pfd[i].revents & (POLLIN | POLLPRI)))
				{
					add_job(cl2, ACTION_READER_REMOTE, NULL, 0);
				}
			}


			//server sockets
			// new connection on a tcp listen socket or new message on udp listen socket
			if(!cl && (pfd[i].revents & (POLLIN | POLLPRI)))
			{
				for(k = 0; k < CS_MAX_MOD; k++)
				{
					struct s_module *module = &modules[k];
					if((module->type & MOD_CONN_NET))
					{
						for(j = 0; j < module->ptab.nports; j++)
						{
							if(module->ptab.ports[j].fd && module->ptab.ports[j].fd == pfd[i].fd)
							{
								accept_connection(module, k, j);
							}
						}
					}
				}
			}
		}
		cs_ftime(&start); // register start time for new poll next run
		first_client->last = time((time_t *)0);
	}
	NULLFREE(pfd);
	NULLFREE(cl_list);
	return;
}
Beispiel #17
0
int main(void)
{
	static struct ImageParams imageParams;
	
	// *** init display ******************************************************
	tft_init();
	tft_test_image();
	
	// *** init network interfaces *******************************************
	init_all_network_interfaces();
	if(!eth0_up){
		diag_printf("failed to initialize eth0\naborting\n");
		return 1;
	}
	else{
		diag_printf(" eth0 up\n");
	}
	
	diag_printf("\n\n");
	diag_printf("########################################\n");
	diag_printf("#        Netimage receiver Demo        #\n");
	diag_printf("########################################\n");
	diag_printf("\n\n");
	
	// *** tcp/ip connect ****************************************************
	diag_printf("waiting for connection...\n");
	int fd = accept_connection();
	if(fd < 0){
		diag_printf("connection failed\naborting\n");
		return 1;
	}
	diag_printf("connection established\n");
	
	if(!recv_header(fd, &imageParams)){
		diag_printf("failed reading image parameters (header)\n");
		return 1;
	}
	
	diag_printf("\n");
	diag_printf("Image stream header:  width = %d\n", imageParams.width);
	diag_printf("                     height = %d\n", imageParams.height);
	diag_printf("                        bpc = %d\n", imageParams.depth);
	diag_printf("                   channels = %d\n", imageParams.nChannels);
	
	while(1){
		// current pixel coordinates
		int x,y;
		// number of bytes between the end of a line in the framebuffer
		// and the beginning of the next line.
		int step = tft_info.rlen/4 - imageParams.width;
		// buffer for incomming pixel data
		uint8_t line[4096];
		// frame buffer pointer
		uint32_t * fb_pos = tft_info.fb;
		
		for(y = 0; y < imageParams.height; y++){
			// read a line into the buffer
			tcp_read(fd, line, imageParams.depth/8*imageParams.nChannels*imageParams.width);
			// current position
			uint8_t * p = line;
			
			for(x = 0; x < imageParams.width; x++){
				// write pixel to framebuffer
				*fb_pos = p[0] | (p[1] << 8) | (p[2] << 16);
				// next pixel
				p += 3;
				fb_pos++;
			}
			// next line
			fb_pos += step;
		}
	}
	
	return 0; // never
}
Beispiel #18
0
/******************************************************************************
 * main
 *****************************************************************************/
int main (int argc, char *argv[])
{
  int listenSfd;        // Listen for control connections on this sfd.
  int *csfd;            // An accepted control socket file descriptor.
  pthread_t thread;     // The handle for a new thread.
  pthread_attr_t attr;  // pthread attribute, to set detached state on creation.
  
  char *rootTemp;

  //Retrieve the name of the root directory from the config file.
  if ((rootTemp = get_config_value ("ROOT_PATH_CONFIG", FTP_CONFIG_FILE)) == NULL)
    return -1;

  /* Append the relative path from the server executable to the server root directory
   * to the absolute path of the server executable. */
  if ((rootdir = get_config_path (rootTemp)) == NULL) {
    free (rootTemp);
    return -1;
  }
  free (rootTemp);

  rootTemp = rootdir;
  /* Canonicalize the path to the server root directory 
   * (eg. resolve all "..", ".", excessive "/" and symbolic links). */
  if ((rootdir = canonicalize_file_name (rootTemp)) == NULL) {
    fprintf (stderr, "%s: canonicalize_file_name: %s\n", __FUNCTION__, strerror (errno));
  }
  free (rootTemp);

  //Initialize the pthread attributes.
  if (pthread_attr_init (&attr) != 0) {
    fprintf (stderr, "%s: pthread_attr_init: %s\n", __FUNCTION__, strerror (errno));
    return -1;
  }

  //Set the detach state attribute.
  if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0) {
    fprintf (stderr, "%s: pthread_attr_init: %s\n", __FUNCTION__, strerror (errno));
    return -1;
  }

  //Create a socket to listen for control connections.
  if ((listenSfd = get_control_sock ()) == -1)
    return -1;

  //Display usage instructions to the server operator, and connection information.
  if (welcome_message() == -1) {
    return -1;
  }

  /* This loop does the following:
   *   -Accepts a control connection from a client.
   *   -Starts a thread for the accepted control connection.
   *   OR
   *   -Read a command from stdin entered on the server console.
   *   -Call server_cmd_handler to perform the command.
   *
   * This loop will exit when:
   *    -malloc cannot allocate memory for an integer.
   *    -The functions pthread_mutex_lock or pthread_mutex_unlock return error.
   *    -The command "shutdown" is entered on the server console. */ 
  while (1) {
    if ((csfd = malloc (sizeof(*csfd))) == NULL) {
      fprintf (stderr, "%s: malloc of %lu bytes failed\n", __FUNCTION__, sizeof(*csfd));
      break;
    }

    //Accept a connection from the client, or read a server command on stdin.
    if ((*csfd = accept_connection (listenSfd, ACCEPT_CONTROL, NULL)) == -1) {
      free (csfd);
      continue;
    } else if (*csfd == STDIN_READY) {   //There is something to read on stdin.
      if (read_server_cmd () == SHUTDOWN_SERVER) {
	shutdownServer = true;
	free (csfd);
	break;
      } else {
	free (csfd);
	continue;
      }
    }

    //Create a new thread for this control connection.
    if (pthread_create (&thread, &attr, &control_thread, csfd) != 0) {
      fprintf (stderr, "%s: pthread_create: %s\n", __FUNCTION__, strerror (errno));
      free (csfd);
      continue;
    }

    //Increment the control connection thread count.
    if (modify_cthread_count (1) == -1)
      break;
  }

  free (rootdir);

  if (activeControlThreads > 0)
    printf ("waiting on threads to resolve...\n");

  //Wait for the control threads to shutdown.
  while (activeControlThreads > 0) {
    sleep (1);
  }

  if (pthread_attr_destroy (&attr) == -1)
    fprintf (stderr, "%s: pthread_attr_destroy: %s\n", __FUNCTION__, strerror (errno));

  printf ("All threads have terminated, exiting the program.\n");
  return 0;
}
Beispiel #19
0
static void do_TCP_epoll(TCP_Server *TCP_server)
{
#define MAX_EVENTS 16
    struct epoll_event events[MAX_EVENTS];
    int nfds;

    while ((nfds = epoll_wait(TCP_server->efd, events, MAX_EVENTS, 0)) > 0) {
        int n;

        for (n = 0; n < nfds; ++n) {
            sock_t sock = events[n].data.u64 & 0xFFFFFFFF;
            int status = (events[n].data.u64 >> 32) & 0xFFFF, index = (events[n].data.u64 >> 48);

            if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP)) {
                switch (status) {
                    case TCP_SOCKET_LISTENING: {
                        //should never happen
                        break;
                    }

                    case TCP_SOCKET_INCOMING: {
                        kill_TCP_connection(&TCP_server->incomming_connection_queue[index]);
                        break;
                    }

                    case TCP_SOCKET_UNCONFIRMED: {
                        kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index]);
                        break;
                    }

                    case TCP_SOCKET_CONFIRMED: {
                        kill_accepted(TCP_server, index);
                        break;
                    }
                }

                continue;
            }


            if (!(events[n].events & EPOLLIN)) {
                continue;
            }

            switch (status) {
                case TCP_SOCKET_LISTENING: {
                    //socket is from socks_listening, accept connection
                    struct sockaddr_storage addr;
                    unsigned int addrlen = sizeof(addr);
                    sock_t sock_new;

                    sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen);

                    int index_new = TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS;

                    if (!accept_connection(TCP_server, sock_new)) {
                        break;
                    }

                    struct epoll_event ev = {
                        .events = EPOLLIN | EPOLLET,
                        .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 48)
                    };

                    if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) {
                        kill_TCP_connection(&TCP_server->incomming_connection_queue[index_new]);
                        break;
                    }

                    break;
                }

                case TCP_SOCKET_INCOMING: {
                    int index_new;

                    if ((index_new = do_incoming(TCP_server, index)) != -1) {
                        events[n].events = EPOLLIN | EPOLLET;
                        events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 48);

                        if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
                            kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index_new]);
                            break;
                        }
                    }

                    break;
                }

                case TCP_SOCKET_UNCONFIRMED: {
                    int index_new;

                    if ((index_new = do_unconfirmed(TCP_server, index)) != -1) {
                        events[n].events = EPOLLIN | EPOLLET;
                        events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 48);

                        if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) {
                            //remove from confirmed connections
                            kill_accepted(TCP_server, index_new);
                            break;
                        }
                    }

                    break;
                }

                case TCP_SOCKET_CONFIRMED: {
                    do_confirmed_recv(TCP_server, index);
                    break;
                }
            }
        }
    }

#undef MAX_EVENTS
}
#endif

void do_TCP_server(TCP_Server *TCP_server)
{
    unix_time_update();

#ifdef TCP_SERVER_USE_EPOLL
    do_TCP_epoll(TCP_server);

#else
    do_TCP_accept_new(TCP_server);
    do_TCP_incomming(TCP_server);
    do_TCP_unconfirmed(TCP_server);
#endif

    do_TCP_confirmed(TCP_server);
}
Beispiel #20
0
void poll_event(struct pollfd *pfds, int nr)
{
	struct connection *conn;
	struct pollfd *pfd;
	int i, res, opt;

	for (i = 0; i < LISTEN_MAX; i++) {
		if (pfds[POLL_LISTEN + i].revents)
			accept_connection(pfds, pfds[POLL_LISTEN + i].fd);
	}

	for (i = 0; i < INCOMING_MAX; i++) {
		conn = incoming[i];
		pfd = &pfds[POLL_INCOMING + i];
		if (!conn || !pfd->revents)
			continue;

		pfd->revents = 0;

		switch (conn->iostate) {
		case IOSTATE_READ_BHS:
		case IOSTATE_READ_AHS_DATA:
		read_again:
			res = read(pfd->fd, conn->buffer, conn->rwsize);
			if (res <= 0) {
				if (res == 0 || (errno != EINTR && errno != EAGAIN))
					conn->state = STATE_CLOSE;
				else if (errno == EINTR)
					goto read_again;
				break;
			}
			conn->rwsize -= res;
			conn->buffer += res;
			if (conn->rwsize)
				break;

			switch (conn->iostate) {
			case IOSTATE_READ_BHS:
				conn->iostate = IOSTATE_READ_AHS_DATA;
				conn->req.ahssize =
					conn->req.bhs.hlength * 4;
				conn->req.datasize =
					ntoh24(conn->req.bhs.dlength);
				conn->rwsize = (conn->req.ahssize + conn->req.datasize + 3) & -4;
				if (conn->rwsize) {
					if (!conn->req_buffer)
						conn->req_buffer = malloc(INCOMING_BUFSIZE);
					conn->buffer = conn->req_buffer;
					conn->req.ahs = conn->buffer;
					conn->req.data = conn->buffer + conn->req.ahssize;
					goto read_again;
				}

			case IOSTATE_READ_AHS_DATA:
				conn_write_pdu(conn);
				pfd->events = POLLOUT;

				if (!cmnd_execute(conn))
					conn->state = STATE_CLOSE;
				break;
			}
			break;

		case IOSTATE_WRITE_BHS:
		case IOSTATE_WRITE_AHS:
		case IOSTATE_WRITE_DATA:
		write_again:
			opt = 1;
			setsockopt(pfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
			res = write(pfd->fd, conn->buffer, conn->rwsize);
			if (res < 0) {
				if (errno != EINTR && errno != EAGAIN)
					conn->state = STATE_CLOSE;
				else if (errno == EINTR)
					goto write_again;
				break;
			}

			conn->rwsize -= res;
			conn->buffer += res;
			if (conn->rwsize)
				goto write_again;

			switch (conn->iostate) {
			case IOSTATE_WRITE_BHS:
				if (conn->rsp.ahssize) {
					conn->iostate = IOSTATE_WRITE_AHS;
					conn->buffer = conn->rsp.ahs;
					conn->rwsize = conn->rsp.ahssize;
					goto write_again;
				}
			case IOSTATE_WRITE_AHS:
				if (conn->rsp.datasize) {
					int o;

					conn->iostate = IOSTATE_WRITE_DATA;
					conn->buffer = conn->rsp.data;
					conn->rwsize = conn->rsp.datasize;
					o = conn->rwsize & 3;
					if (o) {
						for (o = 4 - o; o; o--)
							*((uint8_t *)conn->buffer + conn->rwsize++) = 0;
					}
					goto write_again;
				}
			case IOSTATE_WRITE_DATA:
				opt = 0;
				setsockopt(pfd->fd, SOL_TCP, TCP_CORK, &opt, sizeof(opt));
				cmnd_finish(conn);

				switch (conn->state) {
				case STATE_KERNEL:
					conn_take_fd(conn, pfd->fd);
					conn->state = STATE_CLOSE;
					break;
				case STATE_EXIT:
				case STATE_CLOSE:
					break;
				default:
					conn_read_pdu(conn);
					pfd->events = POLLIN;
					break;
				}
				break;
			}

			break;
		default:
			log_error("illegal iostate %d for port %d!\n", conn->iostate, i);
			exit(1);
		}

		if (conn->state == STATE_CLOSE) {
			log_debug("connection closed");
			conn_free_pdu(conn);
			conn_free(conn);
			close(pfd->fd);
			pfd->fd = -1;
			incoming[i] = NULL;
		}
	}
}
Beispiel #21
0
/* called to retrive a file from remote host */
void getfile( char *fname)
{
   FILE *fp=NULL;
   int fd, nTotal=0, nBytesRead=0, retval, aborted=0;
   char *abortstr = "ABORrn", ch;
   if( !fname || ! (*fname)) {
      printf("No file specified.n");
      return;
   }
   /*
    * open the file with current mode
    */
   if(! (fp=fopen(fname,(bMode==ASCII) ? "wt" : "wb"))) {
      perror("file open");
      return;
   }
   /*
    * obtain a listen socket
    */
   if( get_listen_socket() < 0) {
       fclose(fp);
       return;
   }
   
   /*
    * send command to server and read response
    */
   sprintf(tmp_buffer,"RETR %srn",fname);
   if(!send_ctrl_msg(tmp_buffer,strlen(tmp_buffer))) {
      fclose(fp);
      return;
   }
   int l= get_host_reply();
if(l==550)return;
   
   /*
    * accept server connection
    */
   if( accept_connection() <= 0) {
       fclose(fp);
       return;
   }
   /* 
    * now get file and store
    */
   
   fd = fileno(fp);
   printf("Type q and hit return to abortrn");
   while( (nBytesRead=data_msg(tmp_buffer,1024)) > 0) {
       
   
   write(fd,tmp_buffer,nBytesRead);
   nTotal+=nBytesRead;
   printf("%s : %d receivedr",fname,nTotal);
   if( check_input() ) {
        ch = getchar();
        if( ch != 'n') {
        while( getchar() != 'n') ;      /* read 'til new line */
        }
        if( ch == 'q') 
        aborted = 1;
   }
   
   /*
    * did we abort?
    */
   if( aborted ) {
  
   printf("rnAbort: Waiting for server to finish.");
   send_ctrl_msg(abortstr,strlen(abortstr));
   break;
   }
   }
   if( aborted ) {         // ignore everything if aborted.
   while( (nBytesRead=data_msg(tmp_buffer,1024)) > 0);
   get_host_reply();
   }
 /*  (void)signal(SIGINT,OldHandler); */
   printf("rn");
   close(fd);
   close_data_connection(hDataSocket);
 /*/  ControlCHit = 0; */
   get_host_reply();
}
Beispiel #22
0
// main entry point
int main(int argc, char * argv[])
{
	char * source_addr = "0.0.0.0";
	int source_port = 21;
	strcpy(basedir, "/");

	int c;
	while ((c = getopt (argc, argv, ":s:p:d:h")) != -1)
	{
		if (c == 's')
		{
			source_addr = optarg;
		}
		else if (c == 'p')
		{
			source_port = atoi(optarg);
		}
		else if (c == 'd')
		{
			strcpy(basedir, optarg);
		}
		else if (c == ':')
		{
			printf("-%c requires an argument\n", optopt);
			return 1;
		}
		else if (c == 'h')
		{
			return help();
		}
		else if (c == '?')
		{
			printf("Unrecognized parameter. Use '-h' for help.\n");
			return 1;
		}
	}

	struct stat s;
	if (stat(basedir, &s) == -1)
	{
		printf("The specified base directory does not exist.\n");
		return 1;
	}

	char tmpbasedir[PATH_MAX + 1] = { 0 };
	if (! realpath(basedir, tmpbasedir)) epicfail("realpath");
	strcpy(basedir, tmpbasedir);

	printf("adoftp server is starting...\n");
	printf("base directory is %s\n", basedir);

	if (strcmp(basedir, "/") == 0) strcpy(basedir, "");

	printf("listening on %s:%d\n", source_addr, source_port);
	int server = create_tcp_server_socket(source_addr, source_port);

	while (1)
	{
		int client = accept_connection(server);
		pthread_t thread_id;
		int result = pthread_create(&thread_id, NULL, thread_proc, (void *)client);
		if (result) epicfail("pthread_create");
	}
}
Beispiel #23
0
/******************************************************************************
 * cmd_pasv - see net.h
 *****************************************************************************/
int cmd_pasv (session_info_t *si)
{
  //The setting to be searched for in the config file.
  char *interfaceSetting = "INTERFACE_CONFIG";
  //The value for the setting that was searched for in the config file.
  char *interfaceResult;
  //The IPv4 address of the configuration file interface.
  char interfaceAddr[INET_ADDRSTRLEN];

  int csfd = si->csfd;

  //Ensure the client has logged in.
  if (!si->loggedin) {
    send_mesg_530 (csfd, REPLY_530_REQUEST);
    return -1;
  }

  /* The server "MUST" close the data connection port when:
   * "The port specification is changed by a command from the user".
   * Source: RFC 959 page 19 */
  if (si->dsfd > 0) {
    if (close (si->dsfd) == -1)
      fprintf (stderr, "%s: close: %s\n", __FUNCTION__, strerror (errno));
    si->dsfd = 0;
  }

  //Read the config file to find which interface to use to make the socket.
  if ((interfaceResult = get_config_value (interfaceSetting,
					    FTP_CONFIG_FILE)) == NULL) {
    return -1;
  }

  /* Get the IPv4 address for the interface specified in the configuration
   * file. Free the interface string, it is no longer required. */
  if (get_interface_address (interfaceResult, &interfaceAddr) == -1) {
    free (interfaceResult);
    return -1;
  }
  free (interfaceResult);


  //Create a socket that will listen for a data connection from a client.
  if ((si->dsfd = get_pasv_sock (interfaceAddr, NULL)) == -1) {
    return -1;
  }

  //Send the data connection address information to the control socket.
  if (send_mesg_227 (csfd, si->dsfd) == -1) {
    close (si->dsfd);
    si->dsfd = 0;
    return -1;
  }
 
  //Accept a connection from the client on the listening socket.
  if ((si->dsfd = accept_connection (si->dsfd, ACCEPT_PASV, si)) == -1) {
  si->dsfd = 0;
  return -1;
  }

  return si->dsfd;
}
Beispiel #24
0
int main(int argc, char**argv)
{
  int msock; /* master socket */
  int ssock; /* slave socket */
  int portno; /* port to listen on */
  socklen_t clientlen; /* byte size of client's address */
  struct sockaddr_in serveraddr; /* server's addr */
  struct sockaddr_in clientaddr; /* client addr */
 
 
  char buf[400]; /* message buffer */
  char *hostaddrp; /* dotted decimal host addr string */
  int optval; /* flag value for setsockopt */
  int n; /* message byte size */

  if (argc != 2) {
    fprintf(stderr, "usage: %s <port>\n", argv[0]);
    exit(1);
  }
  portno = atoi(argv[1]);

  msock = create_socket(AF_207TCP, SOCK_207STREAM, IPPROTO_207TCP);
  if (msock < 0)
    perror("ERROR opening socket");

  bzero((char *) &serveraddr, sizeof(serveraddr));

  serveraddr.sin_family = AF_INET;
  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  serveraddr.sin_port = htons((unsigned short)portno);
  if (bind_socket(msock, (struct sockaddr_in *) &serveraddr,
       sizeof(serveraddr)) < 0)
    perror("ERROR on binding");
 
 
 
  while (1) {
     
      if (listen_socket(msock, 5) < 0) 
                perror("ERROR on listen");
 
  clientlen = sizeof(clientaddr);
  ssock = accept_connection(msock, (struct sockaddr_in *) &clientaddr, clientlen);
  if (ssock < 0)
    perror("ERROR on accept");
 
  pid_t childpid=fork();
 
  if (childpid  == 0)
  {
      //close(ssock);
      //int abc;
      //scanf("%d",&abc);
      char buffer[4000],converted[4000];
      int nr = recv_data(ssock,buffer,sizeof(buffer),0);
     
      int i;
      for(i=0;i<nr;i++)
      converted[i]=  toupper(buffer[i]);
      printf("\nConverted %s",converted);
      printf("\n\n");
      send_data(ssock,converted,sizeof(converted),0);
      //close_connection(ssock);
            nr = recv_data(ssock,buffer,sizeof(buffer),0);
     exit(0);      
  }
  }
 
 // int i;
 // for(i=0;i<3000;i++)
 // printf("\nData Recieved: %d\n%s",buffer[i]);

}
Beispiel #25
0
int main(int argc, char * argv[]) {

	if(argc < 3 || argc > 4) {
		print_usage();
	}

	int i = 0;

	if(argc == 4) {
		if(strcmp(argv[1], "-d")) {
			print_usage();
		}
		debug = 1;
		i = 1;
	}

	int portno = atoi(argv[++i]);
	set_dropper(atoi(argv[++i]));

	if((socket_descriptor = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		fprintf(stderr, "Could not create socket.\n");
		exit(2);
	}

	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(portno);

	init();

	if(bind(socket_descriptor, (struct sockaddr *) &server, sizeof(server)) < 0) {
		fprintf(stderr, "Could not bind socket to port %d.\n", portno);
		exit(3);
	}

	if(debug)
		printf("Server started on port %d.\n", portno);

	serving = 0;

	max_in_size = 1024;
	in_buffer = (uchar *)malloc(max_in_size*sizeof(uchar));

	src = &client;

	while(1) {
		if(!serving) {
			accept_connection();
		} else if(!prepare_packet()) {
			if(write_read_data()) {
				printf("Error while receiving data. Terminating Connection");
				finished = 0;
				serving = 0;
				free(out_buffer);
				continue;
			}
			process_read();
		}
	}

	return 0;
}
Beispiel #26
0
int main(int argc, char **argv)
{
    int port;
    int listensock;
    int sock;

    setbuf(stdout,NULL);
    memset(&recvbuf,0,sizeof(recvbuf));

    if (2 > argc) {
        fprintf(stderr,"Usage: msgserver <port>\n");
        return -1;
    }

    port = atoi(argv[1]);
    if (0 > (listensock = start_listening(port)))
        return -1;

    printf("Waiting for connection...\n");
    while (0 <= (sock = accept_connection(listensock))) {

        /* Reset the buffer size to 0 in case a previous connection closed without
           completing the last message. */
        recvbuf.size = 0;

        while (1) {
            int r;

            /* Allocate more memory for the receive buffer, if necessary */
            if (recvbuf.alloc < recvbuf.size+CHUNKSIZE) {
                recvbuf.alloc = recvbuf.size+CHUNKSIZE;
                recvbuf.data = realloc(recvbuf.data,recvbuf.alloc);
            }

            /* Read the next chunk of data */
            r = read(sock,&recvbuf.data[recvbuf.size],CHUNKSIZE);
            if (0 > r) {
                /* Read error */
                perror("read");
                close(sock);
                break;
            }
            else if (0 == r) {
                /* Clean disconnect */
                if (0 < recvbuf.size)
                    fprintf(stderr,"Client disconnected without completing message\n");
                close(sock);
                break;
            }
            else {
                /* We have some data... process all of the completed messages we've
                   received so far. It is possible that the call to read may have
                   obtained the data from a message that was incomplete the last
                   time round, so this will be processed too. */
                recvbuf.size += r;
                process_incoming();
            }
        }
        printf("Client closed connection\n");
    }

    return 0;
}
int
engine_read_message (time_t delay)
{
  fd_set read_set, write_set;
  struct timeval wt;
  int nfds, length, i;
  unsigned int fdflags;
  int fdtype;
  void *fdvalue;
  aClient *client_p;

  engine_get_fdsets (&read_set, &write_set);

  wt.tv_sec = delay;
  wt.tv_usec = 0;

  nfds = select (MAXCONNECTIONS, &read_set, &write_set, NULL, &wt);
  if (nfds == -1)
  {
    if (((errno == EINTR) || (errno == EAGAIN)))
      return -1;
    report_error ("select %s:%s", &me);
    sleep (5);
    return -1;
  }
  else if (nfds == 0)
    return 0;

  if (delay)
    NOW = timeofday = time (NULL);

  for (i = 0; i < MAXCONNECTIONS; i++)
  {
    get_fd_info (i, &fdtype, &fdflags, &fdvalue);

    client_p = NULL;
    length = -1;

    if (nfds)
    {
      int rr = FD_ISSET (i, &read_set);
      int rw = FD_ISSET (i, &write_set);

      if (rr || rw)
        nfds--;
      else
        continue;

      fdfprintf (stderr, "fd %d: %s%s\n", i, rr ? "read " : "",
                 rw ? "write" : "");

      switch (fdtype)
      {
         case FDT_NONE:
           break;

         case FDT_AUTH:
           client_p = (aClient *) fdvalue;
           if (rr)
             read_authports (client_p);
           if (rw && client_p->authfd >= 0)
             send_authports (client_p);
           check_client_fd (client_p);
           break;

         case FDT_LISTENER:
           client_p = (aClient *) fdvalue;
           if (rr)
             accept_connection (client_p);
           break;

         case FDT_RESOLVER:
#ifdef USE_ADNS
           dns_do_callbacks ();
#else
           do_dns_async ();
#endif
           break;

         case FDT_CLIENT:
           client_p = (aClient *) fdvalue;
           readwrite_client (client_p, rr, rw);
           break;

         default:
           abort ();            /* unknown client type? bail! */
      }
    }
    else
      break;                    /* no more fds? break out of the loop */
  }                             /* end of for() loop for testing selected sockets */

  return 0;
}
Beispiel #28
0
/*
 * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
 * either return an error to be displayed, or set *EXIT_CODE to non-zero and
 * return SVN_NO_ERROR.
 */
static svn_error_t *
sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
  enum run_mode run_mode = run_mode_unspecified;
  svn_boolean_t foreground = FALSE;
  apr_socket_t *sock;
  apr_sockaddr_t *sa;
  svn_error_t *err;
  apr_getopt_t *os;
  int opt;
  serve_params_t params;
  const char *arg;
  apr_status_t status;
#ifndef WIN32
  apr_proc_t proc;
#endif
  svn_boolean_t is_multi_threaded;
  enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
  svn_boolean_t cache_fulltexts = TRUE;
  svn_boolean_t cache_nodeprops = TRUE;
  svn_boolean_t cache_txdeltas = TRUE;
  svn_boolean_t cache_revprops = FALSE;
  svn_boolean_t use_block_read = FALSE;
  apr_uint16_t port = SVN_RA_SVN_PORT;
  const char *host = NULL;
  int family = APR_INET;
  apr_int32_t sockaddr_info_flags = 0;
#if APR_HAVE_IPV6
  svn_boolean_t prefer_v6 = FALSE;
#endif
  svn_boolean_t quiet = FALSE;
  svn_boolean_t is_version = FALSE;
  int mode_opt_count = 0;
  int handling_opt_count = 0;
  const char *config_filename = NULL;
  const char *pid_filename = NULL;
  const char *log_filename = NULL;
  svn_node_kind_t kind;
  apr_size_t min_thread_count = THREADPOOL_MIN_SIZE;
  apr_size_t max_thread_count = THREADPOOL_MAX_SIZE;
#ifdef SVN_HAVE_SASL
  SVN_ERR(cyrus_init(pool));
#endif

  /* Check library versions */
  SVN_ERR(check_lib_versions());

  /* Initialize the FS library. */
  SVN_ERR(svn_fs_initialize(pool));

  /* Initialize the efficient Authz support. */
  SVN_ERR(svn_repos_authz_initialize(pool));

  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

  params.root = "/";
  params.tunnel = FALSE;
  params.tunnel_user = NULL;
  params.read_only = FALSE;
  params.base = NULL;
  params.cfg = NULL;
  params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
  params.logger = NULL;
  params.config_pool = NULL;
  params.fs_config = NULL;
  params.vhost = FALSE;
  params.username_case = CASE_ASIS;
  params.memory_cache_size = (apr_uint64_t)-1;
  params.zero_copy_limit = 0;
  params.error_check_interval = 4096;
  params.max_request_size = MAX_REQUEST_SIZE * 0x100000;
  params.max_response_size = 0;

  while (1)
    {
      status = apr_getopt_long(os, svnserve__options, &opt, &arg);
      if (APR_STATUS_IS_EOF(status))
        break;
      if (status != APR_SUCCESS)
        {
          usage(argv[0], pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }
      switch (opt)
        {
        case '6':
#if APR_HAVE_IPV6
          prefer_v6 = TRUE;
#endif
          /* ### Maybe error here if we don't have IPV6 support? */
          break;

        case 'h':
          help(pool);
          return SVN_NO_ERROR;

        case 'q':
          quiet = TRUE;
          break;

        case SVNSERVE_OPT_VERSION:
          is_version = TRUE;
          break;

        case 'd':
          if (run_mode != run_mode_daemon)
            {
              run_mode = run_mode_daemon;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_FOREGROUND:
          foreground = TRUE;
          break;

        case SVNSERVE_OPT_SINGLE_CONN:
          handling_mode = connection_mode_single;
          handling_opt_count++;
          break;

        case 'i':
          if (run_mode != run_mode_inetd)
            {
              run_mode = run_mode_inetd;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_LISTEN_PORT:
          {
            apr_uint64_t val;

            err = svn_cstring_strtoui64(&val, arg, 0, APR_UINT16_MAX, 10);
            if (err)
              return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
                                       _("Invalid port '%s'"), arg);
            port = (apr_uint16_t)val;
          }
          break;

        case SVNSERVE_OPT_LISTEN_HOST:
          host = arg;
          break;

        case 't':
          if (run_mode != run_mode_tunnel)
            {
              run_mode = run_mode_tunnel;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_TUNNEL_USER:
          params.tunnel_user = arg;
          break;

        case 'X':
          if (run_mode != run_mode_listen_once)
            {
              run_mode = run_mode_listen_once;
              mode_opt_count++;
            }
          break;

        case 'r':
          SVN_ERR(svn_utf_cstring_to_utf8(&params.root, arg, pool));

          SVN_ERR(svn_io_check_resolved_path(params.root, &kind, pool));
          if (kind != svn_node_dir)
            {
              return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                       _("Root path '%s' does not exist "
                         "or is not a directory"), params.root);
            }

          params.root = svn_dirent_internal_style(params.root, pool);
          SVN_ERR(svn_dirent_get_absolute(&params.root, params.root, pool));
          break;

        case 'R':
          params.read_only = TRUE;
          break;

        case 'T':
          handling_mode = connection_mode_thread;
          handling_opt_count++;
          break;

        case 'c':
          params.compression_level = atoi(arg);
          if (params.compression_level < SVN_DELTA_COMPRESSION_LEVEL_NONE)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE;
          if (params.compression_level > SVN_DELTA_COMPRESSION_LEVEL_MAX)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_MAX;
          break;

        case 'M':
          {
            apr_uint64_t sz_val;
            SVN_ERR(svn_cstring_atoui64(&sz_val, arg));

            params.memory_cache_size = 0x100000 * sz_val;
          }
          break;

        case SVNSERVE_OPT_CACHE_TXDELTAS:
          cache_txdeltas = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_FULLTEXTS:
          cache_fulltexts = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_REVPROPS:
          cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_NODEPROPS:
          cache_nodeprops = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_BLOCK_READ:
          use_block_read = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CLIENT_SPEED:
          {
            apr_size_t bandwidth = (apr_size_t)apr_strtoi64(arg, NULL, 0);

            /* for slower clients, don't try anything fancy */
            if (bandwidth >= 1000)
              {
                /* block other clients for at most 1 ms (at full bandwidth).
                   Note that the send buffer is 16kB anyways. */
                params.zero_copy_limit = bandwidth * 120;

                /* check for aborted connections at the same rate */
                params.error_check_interval = bandwidth * 120;
              }
          }
          break;

        case SVNSERVE_OPT_MAX_REQUEST:
          params.max_request_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MAX_RESPONSE:
          params.max_response_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MIN_THREADS:
          min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MAX_THREADS:
          max_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

#ifdef WIN32
        case SVNSERVE_OPT_SERVICE:
          if (run_mode != run_mode_service)
            {
              run_mode = run_mode_service;
              mode_opt_count++;
            }
          break;
#endif

        case SVNSERVE_OPT_CONFIG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&config_filename, arg, pool));
          config_filename = svn_dirent_internal_style(config_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&config_filename, config_filename,
                                          pool));
          break;

        case SVNSERVE_OPT_PID_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool));
          pid_filename = svn_dirent_internal_style(pid_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&pid_filename, pid_filename, pool));
          break;

         case SVNSERVE_OPT_VIRTUAL_HOST:
           params.vhost = TRUE;
           break;

         case SVNSERVE_OPT_LOG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&log_filename, arg, pool));
          log_filename = svn_dirent_internal_style(log_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&log_filename, log_filename, pool));
          break;

        }
    }

  if (is_version)
    {
      SVN_ERR(version(quiet, pool));
      return SVN_NO_ERROR;
    }

  if (os->ind != argc)
    {
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (mode_opt_count != 1)
    {
      svn_error_clear(svn_cmdline_fputs(
#ifdef WIN32
                      _("You must specify exactly one of -d, -i, -t, "
                        "--service or -X.\n"),
#else
                      _("You must specify exactly one of -d, -i, -t or -X.\n"),
#endif
                       stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (handling_opt_count > 1)
    {
      svn_error_clear(svn_cmdline_fputs(
                      _("You may only specify one of -T or --single-thread\n"),
                      stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  /* construct object pools */
  is_multi_threaded = handling_mode == connection_mode_thread;
  params.fs_config = apr_hash_make(pool);
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
                cache_txdeltas ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                cache_fulltexts ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS,
                cache_nodeprops ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                cache_revprops ? "2" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ,
                use_block_read ? "1" :"0");

  SVN_ERR(svn_repos__config_pool_create(&params.config_pool,
                                        is_multi_threaded,
                                        pool));

  /* If a configuration file is specified, load it and any referenced
   * password and authorization files. */
  if (config_filename)
    {
      params.base = svn_dirent_dirname(config_filename, pool);

      SVN_ERR(svn_repos__config_pool_get(&params.cfg,
                                         params.config_pool,
                                         config_filename,
                                         TRUE, /* must_exist */
                                         NULL,
                                         pool));
    }

  if (log_filename)
    SVN_ERR(logger__create(&params.logger, log_filename, pool));
  else if (run_mode == run_mode_listen_once)
    SVN_ERR(logger__create_for_stderr(&params.logger, pool));

  if (params.tunnel_user && run_mode != run_mode_tunnel)
    {
      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
               _("Option --tunnel-user is only valid in tunnel mode"));
    }

  if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
    {
      apr_pool_t *connection_pool;
      svn_ra_svn_conn_t *conn;
      svn_stream_t *stdin_stream;
      svn_stream_t *stdout_stream;

      params.tunnel = (run_mode == run_mode_tunnel);
      apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
                                redirect_stdout);

      /* We are an interactive server, i.e. can't use APR buffering on
       * stdin. */
      SVN_ERR(svn_stream_for_stdin2(&stdin_stream, FALSE, pool));
      SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

      /* Use a subpool for the connection to ensure that if SASL is used
       * the pool cleanup handlers that call sasl_dispose() (connection_pool)
       * and sasl_done() (pool) are run in the right order. See issue #3664. */
      connection_pool = svn_pool_create(pool);
      conn = svn_ra_svn_create_conn5(NULL, stdin_stream, stdout_stream,
                                     params.compression_level,
                                     params.zero_copy_limit,
                                     params.error_check_interval,
                                     params.max_request_size,
                                     params.max_response_size,
                                     connection_pool);
      err = serve(conn, &params, connection_pool);
      svn_pool_destroy(connection_pool);

      return err;
    }

#ifdef WIN32
  /* If svnserve needs to run as a Win32 service, then we need to
     coordinate with the Service Control Manager (SCM) before
     continuing.  This function call registers the svnserve.exe
     process with the SCM, waits for the "start" command from the SCM
     (which will come very quickly), and confirms that those steps
     succeeded.

     After this call succeeds, the service is free to run.  At some
     point in the future, the SCM will send a message to the service,
     requesting that it stop.  This is translated into a call to
     winservice_notify_stop().  The service is then responsible for
     cleanly terminating.

     We need to do this before actually starting the service logic
     (opening files, sockets, etc.) because the SCM wants you to
     connect *first*, then do your service-specific logic.  If the
     service process takes too long to connect to the SCM, then the
     SCM will decide that the service is busted, and will give up on
     it.
     */
  if (run_mode == run_mode_service)
    {
      err = winservice_start();
      if (err)
        {
          svn_handle_error2(err, stderr, FALSE, "svnserve: ");

          /* This is the most common error.  It means the user started
             svnserve from a shell, and specified the --service
             argument.  svnserve cannot be started, as a service, in
             this way.  The --service argument is valid only valid if
             svnserve is started by the SCM. */
          if (err->apr_err ==
              APR_FROM_OS_ERROR(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT))
            {
              svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                  _("svnserve: The --service flag is only valid if the"
                    " process is started by the Service Control Manager.\n")));
            }

          svn_error_clear(err);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }

      /* The service is now in the "starting" state.  Before the SCM will
         consider the service "started", this thread must call the
         winservice_running() function. */
    }
#endif /* WIN32 */

  /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get
     APR_UNSPEC, because it may give us back an IPV6 address even if we can't
     create IPV6 sockets. */

#if APR_HAVE_IPV6
#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status == 0)
    {
      apr_socket_close(sock);
      family = APR_UNSPEC;

      if (prefer_v6)
        {
          if (host == NULL)
            host = "::";
          sockaddr_info_flags = APR_IPV6_ADDR_OK;
        }
      else
        {
          if (host == NULL)
            host = "0.0.0.0";
          sockaddr_info_flags = APR_IPV4_ADDR_OK;
        }
    }
#endif

  status = apr_sockaddr_info_get(&sa, host, family, port,
                                 sockaddr_info_flags, pool);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't get address info"));
    }


#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't create server socket"));
    }

  /* Prevents "socket in use" errors when server is killed and quickly
   * restarted. */
  status = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't set options on server socket"));
    }

  status = apr_socket_bind(sock, sa);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't bind server socket"));
    }

  status = apr_socket_listen(sock, ACCEPT_BACKLOG);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't listen on server socket"));
    }

#if APR_HAS_FORK
  if (run_mode != run_mode_listen_once && !foreground)
    /* ### ignoring errors... */
    apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);

  apr_signal(SIGCHLD, sigchld_handler);
#endif

#ifdef SIGPIPE
  /* Disable SIGPIPE generation for the platforms that have it. */
  apr_signal(SIGPIPE, SIG_IGN);
#endif

#ifdef SIGXFSZ
  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
   * working with large files when compiled against an APR that doesn't have
   * large file support will crash the program, which is uncool. */
  apr_signal(SIGXFSZ, SIG_IGN);
#endif

  if (pid_filename)
    SVN_ERR(write_pid_file(pid_filename, pool));

#ifdef WIN32
  status = apr_os_sock_get(&winservice_svnserve_accept_socket, sock);
  if (status)
    winservice_svnserve_accept_socket = INVALID_SOCKET;

  /* At this point, the service is "running".  Notify the SCM. */
  if (run_mode == run_mode_service)
    winservice_running();
#endif

  /* Configure FS caches for maximum efficiency with svnserve.
   * For pre-forked (i.e. multi-processed) mode of operation,
   * keep the per-process caches smaller than the default.
   * Also, apply the respective command line parameters, if given. */
  {
    svn_cache_config_t settings = *svn_cache_config_get();

    if (params.memory_cache_size != -1)
      settings.cache_size = params.memory_cache_size;

    settings.single_threaded = TRUE;
    if (handling_mode == connection_mode_thread)
      {
#if APR_HAS_THREADS
        settings.single_threaded = FALSE;
#else
        /* No requests will be processed at all
         * (see "switch (handling_mode)" code further down).
         * But if they were, some other synchronization code
         * would need to take care of securing integrity of
         * APR-based structures. That would include our caches.
         */
#endif
      }

    svn_cache_config_set(&settings);
  }

#if APR_HAS_THREADS
  SVN_ERR(svn_root_pools__create(&connection_pools));

  if (handling_mode == connection_mode_thread)
    {
      /* create the thread pool with a valid range of threads */
      if (max_thread_count < 1)
        max_thread_count = 1;
      if (min_thread_count > max_thread_count)
        min_thread_count = max_thread_count;

      status = apr_thread_pool_create(&threads,
                                      min_thread_count,
                                      max_thread_count,
                                      pool);
      if (status)
        {
          return svn_error_wrap_apr(status, _("Can't create thread pool"));
        }

      /* let idle threads linger for a while in case more requests are
         coming in */
      apr_thread_pool_idle_wait_set(threads, THREADPOOL_THREAD_IDLE_LIMIT);

      /* don't queue requests unless we reached the worker thread limit */
      apr_thread_pool_threshold_set(threads, 0);
    }
  else
    {
      threads = NULL;
    }
#endif

  while (1)
    {
      connection_t *connection = NULL;
      SVN_ERR(accept_connection(&connection, sock, &params, handling_mode,
                                pool));
      if (run_mode == run_mode_listen_once)
        {
          err = serve_socket(connection, connection->pool);
          close_connection(connection);
          return err;
        }

      switch (handling_mode)
        {
        case connection_mode_fork:
#if APR_HAS_FORK
          status = apr_proc_fork(&proc, connection->pool);
          if (status == APR_INCHILD)
            {
              /* the child would't listen to the main server's socket */
              apr_socket_close(sock);

              /* serve_socket() logs any error it returns, so ignore it. */
              svn_error_clear(serve_socket(connection, connection->pool));
              close_connection(connection);
              return SVN_NO_ERROR;
            }
          else if (status != APR_INPARENT)
            {
              err = svn_error_wrap_apr(status, "apr_proc_fork");
              logger__log_error(params.logger, err, NULL, NULL);
              svn_error_clear(err);
            }
#endif
          break;

        case connection_mode_thread:
          /* Create a detached thread for each connection.  That's not a
             particularly sophisticated strategy for a threaded server, it's
             little different from forking one process per connection. */
#if APR_HAS_THREADS
          attach_connection(connection);

          status = apr_thread_pool_push(threads, serve_thread, connection,
                                        0, NULL);
          if (status)
            {
              return svn_error_wrap_apr(status, _("Can't push task"));
            }
#endif
          break;

        case connection_mode_single:
          /* Serve one connection at a time. */
          /* serve_socket() logs any error it returns, so ignore it. */
          svn_error_clear(serve_socket(connection, connection->pool));
        }

      close_connection(connection);
    }

  /* NOTREACHED */
}