Пример #1
0
void exec_client_process(int (*socket_pairs)[2], int index) {
    pid_t pid = fork();
    if (pid == 0) {
        const int client_num = get_client_count();
        close_all_client_fd_except(socket_pairs, client_num, index);
        close_all_server_fd(socket_pairs, client_num);
        move_fd(server_fd, socket_pairs[index][kFdConnectToClient]);
        execv(get_client_name(index), NULL);
        exit(0);
    }
}
Пример #2
0
void exec_server_process(int (*socket_pairs)[2]) {
    pid_t pid = fork();
    if (pid == 0) {
        const int client_num = get_client_count();
        close_all_client_fd_except(socket_pairs, client_num, -1);
        for (int i = 0; i < client_num; i++) {
            move_fd(client_fd(i), socket_pairs[i][kFdConnectToServer]);
        }
        execv(get_server_name(), NULL);
        exit(0);
    }
}
Пример #3
0
/*
 * Send a status update to all connected clients
 */
void broadcast_status() {
    struct cl_entry *current;
    struct net_status *status;
    uint8_t dcount;
    uint16_t scount;
    uint8_t tcount;
    uint8_t permission;
    int ret;
    
    /*
     * Start iteration over complete client list
     * This locks the mutex for the client list
     */
    current = start_iteration();

    /* Get number of users */
    dcount = docent_exists();
    tcount = tutor_exists();
    scount = get_client_count() - dcount - tcount;

    while (current != NULL) {
        if (current == get_write_user()) {
            permission = 1;
        } else {
            permission = 0;
        }

        /* Build the status message */
        status = build_status(current->cdata->role, current->cdata->cid,
                permission, dcount, tcount, scount);
        ret = send(current->cdata->sfd, status, sizeof(struct net_status), 0);
        if (ret < 0) {
            perror("send");
        }
        free(status);
        /* Select next client in list */
        current = iteration_next();
    }

    log_debug("broadcasting agent: status sent to all connected clients");
    /*
     * End of iteration
     * This unlocks the mutex of the client list
     */
    end_iteration();
}
Пример #4
0
char *lst_json(struct client **lst){

	cJSON *root,*root_object,*root_object_array;	

	root = cJSON_CreateArray();
	root_object=cJSON_CreateObject();
	cJSON_AddItemToArray(root,root_object);
	root_object_array = cJSON_CreateArray();

	cJSON_AddStringToObject(root_object, "request", "count_client");			            
	cJSON_AddNumberToObject(root_object, "data", get_client_count());
	cJSON_AddItemToObject(root_object, "users", root_object_array);
	if(new_user)
	cJSON_AddStringToObject(root_object, "user_changed", new_user);			            



	cJSON *prev=NULL;

	while( *lst != NULL ) 
	{
		cJSON *root_object_array_object = cJSON_CreateObject();
		cJSON_AddStringToObject(root_object_array_object, "user", (*lst)->name);
		cJSON_AddStringToObject(root_object_array_object, "id", (*lst)->session_id);
		cJSON_AddNumberToObject(root_object_array_object, "gid", (*lst)->gid);		
		if (!prev) root_object_array->child = root_object_array_object;
		else prev->next = root_object_array_object, root_object_array_object->prev = prev;
		prev = root_object_array_object;
		lst = &(*lst)->next;
	}

    char *json=NULL;
    json = (char *) malloc (sizeof(cJSON_Print(root)));      
    json=cJSON_Print(root);
    
    
    free(root);free(root_object);free(root_object_array);   
    return json;


}
Пример #5
0
int main(int argc, char **argv)
{
	daemonize();
	




	//saveData("admin",100,100,"admin");

	config_obj=parseConfigFile();
	ipWhitelist = cJSON_GetObjectItem(config_obj,"ipWhitelist");

	wiringPiSetup();
	pinDirections = cJSON_GetObjectItem(config_obj,"pinDirections");
	handlePinsDirection(pinDirections);

	signal(SIGINT, sighandler);
	


	struct lws_context_creation_info info;
	unsigned int ms, oldms= 0;
	const char *iface = NULL;
	char cert_path[1024];
	char key_path[1024];
	int use_ssl = 0;
	int opts = 0;
	int n = 0;

	/*
	 * take care to zero down the info struct, he contains random garbaage
	 * from the stack otherwise
	 */
	 memset(&info, 0, sizeof info);
	 info.port = 7681;


	 signal(SIGINT, sighandler);



	 info.iface = iface;
	 info.protocols = protocols;
	 info.ssl_cert_filepath = NULL;
	 info.ssl_private_key_filepath = NULL;

	 if (use_ssl) {
	 	if (strlen(resource_path) > sizeof(cert_path) - 32) {
	 		lwsl_err("resource path too long\n");
	 		return -1;
	 	}
	 	sprintf(cert_path, "%s/libwebsockets-test-server.pem",
	 		resource_path);
	 	if (strlen(resource_path) > sizeof(key_path) - 32) {
	 		lwsl_err("resource path too long\n");
	 		return -1;
	 	}
	 	sprintf(key_path, "%s/libwebsockets-test-server.key.pem",
	 		resource_path);

	 	info.ssl_cert_filepath = cert_path;
	 	info.ssl_private_key_filepath = key_path;
	 }
	 info.gid = -1;
	 info.uid = -1;
	 info.max_http_header_pool = 1;
	 info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8;
	 info.extensions = NULL;
	 context = lws_create_context(&info);
	 if (context == NULL) {
	 	lwsl_err("libwebsocket init failed\n");
	 	return -1;
	 }



	 n = 0;

	 while (n >= 0 && !force_exit) {
	 	struct timeval tv;

	 	gettimeofday(&tv, NULL);

		/*
		 * This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
		 * live websocket connection using the DUMB_INCREMENT protocol,
		 * as soon as it can take more packets (usually immediately)
		 */
		 extern struct ram_usage ram_l;
		 extern struct cpu_live cpu_l;
		 extern struct cpu_freq cpu_freq;




		if(old_client_count!=client_count){
			if(hash){
				free(hash);
			}

			hash=rand_string();
		 	lws_callback_on_writable_all_protocol(context,
		 		&protocols[PROTOCOL_GPIO]);
		 	lws_callback_on_writable_all_protocol(context,
		 		&protocols[PROTOCOL_DETAILS]);		
		 	lws_callback_on_writable_all_protocol(context,
		 		&protocols[PROTOCOL_SERVICES]);	
		 	lws_callback_on_writable_all_protocol(context,
		 		&protocols[PROTOCOL_HOME]);			 				 			 					
			old_client_count=client_count;
		}

		 ms = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
		 if ((ms - oldms) > 200 && get_client_count()>0 && (cpuLive(&cpu_l,5)==0 && ramLive(&ram_l,5)==0  && cpuLiveFreq(&cpu_freq)==0 )) {
		 	lws_callback_on_writable_all_protocol(context,
		 		&protocols[PROTOCOL_DETAILS]);
		 	oldms = ms;
		 }				 


		 n = lws_service(context, 50);
	}

		lws_context_destroy(context);

		lwsl_notice("libwebsockets-test-server exited cleanly\n");


		return 0;
	}
Пример #6
0
/*
 * We will eventually be called from inetd or via the rc scripts directly
 * Parse arguments and act appropiately.
 */
int
main(int argc, char **argv)
{
    extern char *optarg;
    FILE *fp;
    int	c, *s, ns;
    struct pollfd *pfds;

#if PROFILE
    moncontrol(0);
#endif

    if ((progname = strrchr(*argv, '/')) != NULL) {
	progname++;
    } else
	progname = *argv;

    /* initialise global session data */
    memset(&session, 0, sizeof(session));
    session.peer = tac_strdup("unknown");


    if (argc <= 1) {
	usage();
	tac_exit(1);
    }

    while ((c = getopt(argc, argv, "B:C:d:hiPp:tGgvSsLw:u:")) != EOF)
	switch (c) {
	case 'B':		/* bind() address*/
	    bind_address = optarg;
	    break;
	case 'L':		/* lookup peer names via DNS */
	    lookup_peer = 1;
	    break;
	case 's':		/* don't respond to sendpass */
	    sendauth_only = 1;
	    break;
	case 'v':		/* print version and exit */
	    vers();
	    tac_exit(1);
	case 't':
	    console = 1;	/* log to console too */
	    break;
	case 'P':		/* Parse config file only */
	    parse_only = 1;
	    break;
	case 'G':		/* foreground */
	    opt_G = 1;
	    break;
	case 'g':		/* single threaded */
	    single = 1;
	    break;
	case 'p':		/* port */
	    port = atoi(optarg);
	    portstr = optarg;
	    break;
	case 'd':		/* debug */
	    debug |= atoi(optarg);
	    break;
	case 'C':		/* config file name */
	    session.cfgfile = tac_strdup(optarg);
	    break;
	case 'h':		/* usage */
	    usage();
	    tac_exit(0);
	case 'i':		/* inetd mode */
	    standalone = 0;
	    break;
	case 'S':		/* enable single-connection */
	    opt_S = 1;
	    break;
#ifdef MAXSESS
	case 'w':		/* wholog file */
	    wholog = tac_strdup(optarg);
	    break;
#endif
	case 'u':
	    wtmpfile = tac_strdup(optarg);
	    break;

	default:
	    fprintf(stderr, "%s: bad switch %c\n", progname, c);
	    usage();
	    tac_exit(1);
	}

    parser_init();

    /* read the configuration/etc */
    init();
#if defined(REAPCHILD) && defined(REAPSIGIGN)
    client_count_init();
#endif
    open_logfile();

    signal(SIGUSR1, handler);
    signal(SIGHUP, handler);
    signal(SIGUSR2, dump_clients_handler);
    signal(SIGTERM, die);
    signal(SIGPIPE, SIG_IGN);

    if (parse_only)
	tac_exit(0);

    if (debug)
	report(LOG_DEBUG, "tac_plus server %s starting", version);

    if (!standalone) {
	/* running under inetd */
	char host[NI_MAXHOST];
	int on;
#ifdef IPV6
	struct sockaddr_in6 name;
#else
  struct sockaddr_in name;
#endif
	socklen_t name_len;

	name_len = sizeof(name);
	session.flags |= SESS_NO_SINGLECONN;

	session.sock = 0;
#ifdef IPV6
	if (getpeername(session.sock, (struct sockaddr6 *)&name, &name_len)) {
	    report(LOG_ERR, "getpeername failure %s", strerror(errno));
#else
	if (getpeername(session.sock, (struct sockaddr *)&name, &name_len)) {
	    report(LOG_ERR, "getpeername failure %s", strerror(errno));
#endif
	} else {
	    if (lookup_peer)
		on = 0;
	    else
		on = NI_NUMERICHOST;
#ifdef IPV6
	    if (getnameinfo((struct sockaddr6 *)&name, name_len, host, 128,
			    NULL, 0, on)) {
#else
	    if (getnameinfo((struct sockaddr *)&name, name_len, host, 128,
			    NULL, 0, on)) {
#endif
		strncpy(host, "unknown", NI_MAXHOST - 1);
		host[NI_MAXHOST - 1] = '\0';
	    }
	    if (session.peer) free(session.peer);
	    session.peer = tac_strdup(host);

	    if (session.peerip) free(session.peerip);
#ifdef IPV6
	    session.peerip = tac_strdup((char *)inet_ntop(name.sin6_family,
					&name.sin6_addr, host, name_len));
#else
	    session.peerip = tac_strdup((char *)inet_ntop(name.sin_family,
					&name.sin_addr, host, name_len));
#endif
	    if (debug & DEBUG_AUTHEN_FLAG)
		report(LOG_INFO, "session.peerip is %s", session.peerip);
	}
#ifdef FIONBIO
	on = 1;
	if (ioctl(session.sock, FIONBIO, &on) < 0) {
	    report(LOG_ERR, "ioctl(FIONBIO) %s", strerror(errno));
	    tac_exit(1);
	}
#endif
	start_session();
	tac_exit(0);
 }

    if (single) {
	session.flags |= SESS_NO_SINGLECONN;
    } else {
	/*
	 * Running standalone; background ourselves and release controlling
	 * tty, unless -G option was specified to keep the parent in the
	 * foreground.
	 */
#ifdef SIGTTOU
	signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
	signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTSTP
	signal(SIGTSTP, SIG_IGN);
#endif
	if (!opt_S)
	    session.flags |= SESS_NO_SINGLECONN;

	if (!opt_G) {
	    if ((childpid = fork()) < 0)
		report(LOG_ERR, "Can't fork first child");
	    else if (childpid > 0)
		exit(0);		/* parent */

	    if (debug)
		report(LOG_DEBUG, "Backgrounded");

#if SETPGRP_VOID
	    if (setpgrp() == -1)
#else
	    if (setpgrp(0, getpid()) == -1)
#endif /* SETPGRP_VOID */
		report(LOG_ERR, "Can't change process group: %s",
		       strerror(errno));

	    /* XXX What does "REAPCHILD" have to do with TIOCNOTTY? */
#ifndef REAPCHILD
	    c = open("/dev/tty", O_RDWR);
	    if (c >= 0) {
		ioctl(c, TIOCNOTTY, (char *)0);
		(void) close(c);
	    }
#else /* REAPCHILD */
	    if ((childpid = fork()) < 0)
		report(LOG_ERR, "Can't fork second child");
	    else if (childpid > 0)
		exit(0);

	    if (debug & DEBUG_FORK_FLAG)
		report(LOG_DEBUG, "Forked grandchild");

#endif /* REAPCHILD */

	    /* some systems require this */
	    closelog();

	    for (c = getdtablesize(); c >= 0; c--)
		(void)close(c);

	    /*
	     * make sure we can still log to syslog now that we have closed
	     * everything
	     */
	    open_logfile();
	}
    }
#if REAPCHILD
#if REAPSIGIGN
    signal(SIGCHLD, reapchild);
#else
    signal(SIGCHLD, SIG_IGN);
#endif
#endif

    ostream = NULL;
    /* chdir("/"); */
    umask(022);
    errno = 0;

    get_socket(&s, &ns);

#ifndef SOMAXCONN
#define SOMAXCONN 5
#endif

    for (c = 0; c < ns; c++) {
	if (listen(s[c], SOMAXCONN) < 0) {
	    console = 1;
	report(LOG_ERR, "listen: %s", strerror(errno));
	tac_exit(1);
    }
    }

    if (port == TAC_PLUS_PORT) {
	if (bind_address == NULL) {
	    strncpy(pidfilebuf, TACPLUS_PIDFILE, PIDSZ);
	    if (pidfilebuf[PIDSZ - 1] != '\0')
		c = PIDSZ;
	    else
		c = PIDSZ - 1;
	} else
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%s", TACPLUS_PIDFILE,
			 bind_address);
    } else {
	if (bind_address == NULL)
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%d", TACPLUS_PIDFILE, port);
	else
	    c = snprintf(pidfilebuf, PIDSZ, "%s.%s.%d", TACPLUS_PIDFILE,
			 bind_address, port);
    }
    if (c >= PIDSZ) {
	pidfilebuf[PIDSZ - 1] = '\0';
	report(LOG_ERR, "pid filename truncated: %s", pidfilebuf);
	childpid = 0;
    } else {
	/* write process id to pidfile */
	if ((fp = fopen(pidfilebuf, "w")) != NULL) {
	    fprintf(fp, "%d\n", (int)getpid());
	    fclose(fp);
	    /*
	     * After forking to disassociate; make sure we know we're the
	     * mother so that we remove our pid file upon exit in die().
	     */
	    childpid = 1;
	} else {
	    report(LOG_ERR, "Cannot write pid to %s %s", pidfilebuf,
		   strerror(errno));
	    childpid = 0;
	}
    }
#ifdef TACPLUS_GROUPID
    if (setgid(TACPLUS_GROUPID))
	report(LOG_ERR, "Cannot set group id to %d %s",
	       TACPLUS_GROUPID, strerror(errno));
#endif

#ifdef TACPLUS_USERID
    if (setuid(TACPLUS_USERID))
	report(LOG_ERR, "Cannot set user id to %d %s",
	       TACPLUS_USERID, strerror(errno));
#endif

#ifdef MAXSESS
    maxsess_loginit();
#endif /* MAXSESS */

    report(LOG_DEBUG, "uid=%d euid=%d gid=%d egid=%d s=%d",
	   getuid(), geteuid(), getgid(), getegid(), s);

    pfds = malloc(sizeof(struct pollfd) * ns);
    if (pfds == NULL) {
	report(LOG_ERR, "malloc failure: %s", strerror(errno));
	tac_exit(1);
    }
    for (c = 0; c < ns; c++) {
	pfds[c].fd = s[c];
	pfds[c].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
    }

    for (;;) {
#if HAVE_PID_T
	pid_t pid;
#else
	int pid;
#endif
	char host[NI_MAXHOST];
#ifdef IPV6
	struct sockaddr_in6 from;
#else
	struct sockaddr_in from;
#endif
	socklen_t from_len;
	int newsockfd, status;
	int flags;
  int procs_for_client;

#if defined(REAPCHILD) && defined(REAPSIGIGN)
  if (reap_children)
    reapchildren();
#endif

	if (reinitialize)
	    init();

  if (dump_client_table) {
    report(LOG_ALERT, "Dumping Client Tables");
    dump_client_tables();
    dump_client_table = 0;
  }

	status = poll(pfds, ns, cfg_get_accepttimeout() * 1000);
	if (status == 0)
	    continue;
	if (status == -1)
	    if (errno == EINTR)
		continue;

	from_len = sizeof(from);
	memset((char *)&from, 0, from_len);
	for (c = 0; c < ns; c++) {
	    if (pfds[c].revents & POLLIN)
  #ifdef IPV6
		newsockfd = accept(s[c], (struct sockaddr6 *)&from, &from_len);
  #else
		newsockfd = accept(s[c], (struct sockaddr *)&from, &from_len);
  #endif
	    else if (pfds[c].revents & (POLLERR | POLLHUP | POLLNVAL)) {
		report(LOG_ERR, "exception on listen FD %d", s[c]);
		tac_exit(1);
	    }
	}

	if (newsockfd < 0) {
	    if (errno == EINTR)
		continue;

	    report(LOG_ERR, "accept: %s", strerror(errno));
	    continue;
	}

	if (lookup_peer)
	    flags = 0;
	else
	    flags = NI_NUMERICHOST;
#ifdef IPV6
	if (getnameinfo((struct sockaddr_in6 *)&from, from_len, host, 128, NULL, 0,
			flags)) {
#else
	if (getnameinfo((struct sockaddr_in *)&from, from_len, host, 128, NULL, 0,
			flags)) {
#endif
	    strncpy(host, "unknown", NI_MAXHOST - 1);
	    host[NI_MAXHOST - 1] = '\0';
	}

	if (session.peer) free(session.peer);
	session.peer = tac_strdup(host);

	if (session.peerip) free(session.peerip);
#ifdef IPV6
	session.peerip = tac_strdup((char *)inet_ntop(from.sin6_family,
          &from.sin6_addr, host, INET6_ADDRSTRLEN));
#else
	session.peerip = tac_strdup((char *)inet_ntop(from.sin_family,
          &from.sin_addr, host, INET_ADDRSTRLEN));
#endif
	if (debug & DEBUG_PACKET_FLAG)
	    report(LOG_DEBUG, "session request from %s sock=%d",
		   session.peer, newsockfd);

	if (!single) {
#if defined(REAPCHILD) && defined(REAPSIGIGN)
      /* first we check the tocal process count to see if we are at the limit */
      if (total_child_count >= cfg_get_maxprocs()) {
        report(LOG_ALERT, "refused connection from %s [%s] at global max procs [%d]",
          session.peer, session.peerip, total_child_count);
        shutdown(newsockfd, 2);
        close(newsockfd);
        continue;
      }
      /* no we check the process count per client */
      procs_for_client = get_client_count(session.peerip);
      report(LOG_ALERT, "connection [%d] from %s [%s]", procs_for_client + 1, session.peer, session.peerip);
      if (procs_for_client >= cfg_get_maxprocsperclt()) {
        report(LOG_ALERT, "refused connection from %s [%s] at client max procs [%d]",
          session.peer, session.peerip, procs_for_client);
        shutdown(newsockfd, 2);
        close(newsockfd);
        continue;
      }
#endif
	    pid = fork();
	    if (pid < 0) {
		    report(LOG_ERR, "fork error");
		    tac_exit(1);
	    }
	} else {
	    pid = 0;
	}
	if (pid == 0) {
	  /* child */
	  if (!single) {
            if (ns > 1) {
              for (c = 0; c < ns; c++) {
                close(s[c]);
              }
            }
          }
	  session.sock = newsockfd;
#ifdef LIBWRAP
	  if (! hosts_ctl(progname,session.peer,session.peerip,progname)) {
		  report(LOG_ALERT, "refused connection from %s [%s]",
		       session.peer, session.peerip);
      shutdown(session.sock, 2);
      close(session.sock);
      if (!single) {
          tac_exit(0);
      } else {
          close(session.sock);
          continue;
      }
    }
    if (debug)
      report(LOG_DEBUG, "connect from %s [%s]", session.peer, session.peerip);
#endif
#if PROFILE
	    moncontrol(1);
#endif

	    start_session();
	    shutdown(session.sock, 2);
	    close(session.sock);
	    if (!single)
		    tac_exit(0);
	} else {
	    /* parent */
#if defined(REAPCHILD) && defined(REAPSIGIGN)
      total_child_count++;
      procs_for_client = increment_client_count_for_proc(pid, session.peerip);
      snprintf(msgbuf, MSGBUFSZ, "forked %lu for %s, procs %d, procs for client %d",
            (long)pid, session.peerip, total_child_count, procs_for_client);
		    report(LOG_DEBUG, msgbuf);
#endif
	    close(newsockfd);
	}
    }
}