Example #1
0
int main(int argc, char **argv)
{
    int fd, i, j, k;

    int c;
    int foreground=0;
    int active_slave=0;
    int log_options;
    char config_file_name[PATH_MAX] = RENDERD_CONFIG;

    while (1) {
        int option_index = 0;
        static struct option long_options[] = {
            {"config", 1, 0, 'c'},
            {"foreground", 1, 0, 'f'},
            {"slave", 1, 0, 's'},
            {"help", 0, 0, 'h'},
            {0, 0, 0, 0}
        };

        c = getopt_long(argc, argv, "hfc:", long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {
            case 'f':
                foreground=1;
                break;
            case 'c':
                strncpy(config_file_name, optarg, PATH_MAX-1);
                config_file_name[PATH_MAX-1] = 0;
                break;
            case 's':
                if (sscanf(optarg, "%i", &active_slave) != 1) {
                    fprintf(stderr, "--slave needs to be nummeric (%s)\n", optarg);
                    active_slave = 0;
                }
                break;
            case 'h':
                fprintf(stderr, "Usage: renderd [OPTION] ...\n");
                fprintf(stderr, "Mapnik rendering daemon\n");
                fprintf(stderr, "  -f, --foreground     run in foreground\n");
                fprintf(stderr, "  -h, --help           display this help and exit\n");
                fprintf(stderr, "  -c, --config=CONFIG  set location of config file (default /etc/renderd.conf)\n");
                fprintf(stderr, "  -s, --slave=CONFIG_NR set which render slave this is (default 0)\n");
                exit(0);
            default:
                fprintf(stderr, "unknown config option '%c'\n", c);
                exit(1);
        }
    }

    log_options = LOG_PID;
#ifdef LOG_PERROR
    if (foreground)
        log_options |= LOG_PERROR;
#endif
    openlog("renderd", log_options, LOG_DAEMON);

    syslog(LOG_INFO, "Rendering daemon started");

    pthread_mutex_init(&qLock, NULL);
    pthread_cond_init(&qCond, NULL);
    reqHead.next = reqHead.prev = &reqHead;
    reqPrioHead.next = reqPrioHead.prev = &reqPrioHead;
    reqBulkHead.next = reqBulkHead.prev = &reqBulkHead;
    dirtyHead.next = dirtyHead.prev = &dirtyHead;
    renderHead.next = renderHead.prev = &renderHead;
    hashidxSize = HASHIDX_SIZE;
    item_hashidx = (struct item_idx *) malloc(sizeof(struct item_idx) * hashidxSize);
    bzero(item_hashidx, sizeof(struct item_idx) * hashidxSize);

    stats.noDirtyRender = 0;
    stats.noReqDroped = 0;
    stats.noReqRender = 0;
    stats.noReqPrioRender = 0;
    stats.noReqBulkRender = 0;

    xmlconfigitem maps[XMLCONFIGS_MAX];
    bzero(maps, sizeof(xmlconfigitem) * XMLCONFIGS_MAX);

    renderd_config config_slaves[MAX_SLAVES];
    bzero(config_slaves, sizeof(renderd_config) * MAX_SLAVES);
    bzero(&config, sizeof(renderd_config));

    dictionary *ini = iniparser_load(config_file_name);
    if (! ini) {
        exit(1);
    }

    noSlaveRenders = 0;

    int iconf = -1;
    char buffer[PATH_MAX];
    for (int section=0; section < iniparser_getnsec(ini); section++) {
        char *name = iniparser_getsecname(ini, section);
        syslog(LOG_INFO, "Parsing section %s\n", name);
        if (strncmp(name, "renderd", 7) && strcmp(name, "mapnik")) {
            if (config.tile_dir == NULL) {
                fprintf(stderr, "No valid (active) renderd config section available\n");
                exit(7);
            }
            /* this is a map section */
            iconf++;
            if (iconf >= XMLCONFIGS_MAX) {
                fprintf(stderr, "Config: more than %d configurations found\n", XMLCONFIGS_MAX);
                exit(7);
            }

            if (strlen(name) >= (XMLCONFIG_MAX - 1)) {
                fprintf(stderr, "XML name too long: %s\n", name);
                exit(7);
            }

            strcpy(maps[iconf].xmlname, name);
            
            sprintf(buffer, "%s:uri", name);
            char *ini_uri = iniparser_getstring(ini, buffer, (char *)"");
            if (strlen(ini_uri) >= (PATH_MAX - 1)) {
                fprintf(stderr, "URI too long: %s\n", ini_uri);
                exit(7);
            }
            strcpy(maps[iconf].xmluri, ini_uri);

            sprintf(buffer, "%s:xml", name);
            char *ini_xmlpath = iniparser_getstring(ini, buffer, (char *)"");
            if (strlen(ini_xmlpath) >= (PATH_MAX - 1)){
                fprintf(stderr, "XML path too long: %s\n", ini_xmlpath);
                exit(7);
            }
            strcpy(maps[iconf].xmlfile, ini_xmlpath);

            sprintf(buffer, "%s:host", name);
            char *ini_hostname = iniparser_getstring(ini, buffer, (char *) "");
            if (strlen(ini_hostname) >= (PATH_MAX - 1)) {
                fprintf(stderr, "Host name too long: %s\n", ini_hostname);
                exit(7);
            }
            strcpy(maps[iconf].host, ini_hostname);

            sprintf(buffer, "%s:htcphost", name);
            char *ini_htcpip = iniparser_getstring(ini, buffer, (char *) "");
            if (strlen(ini_htcpip) >= (PATH_MAX - 1)) {
                fprintf(stderr, "HTCP host name too long: %s\n", ini_htcpip);
                exit(7);
            }
            strcpy(maps[iconf].htcpip, ini_htcpip);

            sprintf(buffer, "%s:tilesize", name);
            char *ini_tilesize = iniparser_getstring(ini, buffer, (char *) "256");
            maps[iconf].tile_px_size = atoi(ini_tilesize);
            if (maps[iconf].tile_px_size < 1) {
                fprintf(stderr, "Tile size is invalid: %s\n", ini_tilesize);
                exit(7);
            }

            sprintf(buffer, "%s:tiledir", name);
            char *ini_tiledir = iniparser_getstring(ini, buffer, (char *) config.tile_dir);
            if (strlen(ini_tiledir) >= (PATH_MAX - 1)) {
                fprintf(stderr, "Tiledir too long: %s\n", ini_tiledir);
                exit(7);
            }
            strcpy(maps[iconf].tile_dir, ini_tiledir);
        } else if (strncmp(name, "renderd", 7) == 0) {
            int render_sec = 0;
            if (sscanf(name, "renderd%i", &render_sec) != 1) {
                render_sec = 0;
            }
            syslog(LOG_INFO, "Parsing render section %i\n", render_sec);
            if (render_sec >= MAX_SLAVES) {
                syslog(LOG_ERR, "Can't handle more than %i render sections\n",
                        MAX_SLAVES);
                exit(7);
            }
            sprintf(buffer, "%s:socketname", name);
            config_slaves[render_sec].socketname = iniparser_getstring(ini,
                    buffer, (char *) RENDER_SOCKET);
            sprintf(buffer, "%s:iphostname", name);
            config_slaves[render_sec].iphostname = iniparser_getstring(ini,
                    buffer, "");
            sprintf(buffer, "%s:ipport", name);
            config_slaves[render_sec].ipport = iniparser_getint(ini, buffer, 0);
            sprintf(buffer, "%s:num_threads", name);
            config_slaves[render_sec].num_threads = iniparser_getint(ini,
                    buffer, NUM_THREADS);
            sprintf(buffer, "%s:tile_dir", name);
            config_slaves[render_sec].tile_dir = iniparser_getstring(ini,
                    buffer, (char *) HASH_PATH);
            sprintf(buffer, "%s:stats_file", name);
            config_slaves[render_sec].stats_filename = iniparser_getstring(ini,
                    buffer, NULL);

            if (render_sec == active_slave) {
                config.socketname = config_slaves[render_sec].socketname;
                config.iphostname = config_slaves[render_sec].iphostname;
                config.ipport = config_slaves[render_sec].ipport;
                config.num_threads = config_slaves[render_sec].num_threads;
                config.tile_dir = config_slaves[render_sec].tile_dir;
                config.stats_filename
                        = config_slaves[render_sec].stats_filename;
                config.mapnik_plugins_dir = iniparser_getstring(ini,
                        "mapnik:plugins_dir", (char *) MAPNIK_PLUGINS);
                config.mapnik_font_dir = iniparser_getstring(ini,
                        "mapnik:font_dir", (char *) FONT_DIR);
                config.mapnik_font_dir_recurse = iniparser_getboolean(ini,
                        "mapnik:font_dir_recurse", FONT_RECURSE);
            } else {
                noSlaveRenders += config_slaves[render_sec].num_threads;
            }
        }
    }

    if (config.ipport > 0) {
        syslog(LOG_INFO, "config renderd: ip socket=%s:%i\n", config.iphostname, config.ipport);
    } else {
        syslog(LOG_INFO, "config renderd: unix socketname=%s\n", config.socketname);
    }
    syslog(LOG_INFO, "config renderd: num_threads=%d\n", config.num_threads);
    if (active_slave == 0) {
        syslog(LOG_INFO, "config renderd: num_slaves=%d\n", noSlaveRenders);
    }
    syslog(LOG_INFO, "config renderd: tile_dir=%s\n", config.tile_dir);
    syslog(LOG_INFO, "config renderd: stats_file=%s\n", config.stats_filename);
    syslog(LOG_INFO, "config mapnik:  plugins_dir=%s\n", config.mapnik_plugins_dir);
    syslog(LOG_INFO, "config mapnik:  font_dir=%s\n", config.mapnik_font_dir);
    syslog(LOG_INFO, "config mapnik:  font_dir_recurse=%d\n", config.mapnik_font_dir_recurse);
    for (i = 0; i < MAX_SLAVES; i++) {
        if (config_slaves[i].num_threads == 0) {
            continue;
        }
        if (i == active_slave) {
            syslog(LOG_INFO, "config renderd(%i): Active\n", i);
        }
        if (config_slaves[i].ipport > 0) {
                syslog(LOG_INFO, "config renderd(%i): ip socket=%s:%i\n", i,
                        config_slaves[i].iphostname, config_slaves[i].ipport);
            } else {
                syslog(LOG_INFO, "config renderd(%i): unix socketname=%s\n", i,
                        config_slaves[i].socketname);
            }
        syslog(LOG_INFO, "config renderd(%i): num_threads=%d\n", i,
                config_slaves[i].num_threads);
        syslog(LOG_INFO, "config renderd(%i): tile_dir=%s\n", i,
                config_slaves[i].tile_dir);
        syslog(LOG_INFO, "config renderd(%i): stats_file=%s\n", i,
                config_slaves[i].stats_filename);
    }

    for(iconf = 0; iconf < XMLCONFIGS_MAX; ++iconf) {
        if (maps[iconf].xmlname[0] != 0) {
         syslog(LOG_INFO, "config map %d:   name(%s) file(%s) uri(%s) htcp(%s) host(%s)",
                 iconf, maps[iconf].xmlname, maps[iconf].xmlfile, maps[iconf].xmluri,
                 maps[iconf].htcpip, maps[iconf].host);
        }
    }

    fd = server_socket_init(&config);
#if 0
    if (fcntl(fd, F_SETFD, O_RDWR | O_NONBLOCK) < 0) {
        fprintf(stderr, "setting socket non-block failed\n");
        close(fd);
        exit(5);
    }
#endif

    //sigPipeAction.sa_handler = pipe_handler;
    sigPipeAction.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &sigPipeAction, NULL) < 0) {
        fprintf(stderr, "failed to register signal handler\n");
        close(fd);
        exit(6);
    }

    render_init(config.mapnik_plugins_dir, config.mapnik_font_dir, config.mapnik_font_dir_recurse);

    /* unless the command line said to run in foreground mode, fork and detach from terminal */
    if (foreground) {
        fprintf(stderr, "Running in foreground mode...\n");
    } else {
        if (daemon(0, 0) != 0) {
            fprintf(stderr, "can't daemonize: %s\n", strerror(errno));
        }
        /* write pid file */
        FILE *pidfile = fopen(PIDFILE, "w");
        if (pidfile) {
            (void) fprintf(pidfile, "%d\n", getpid());
            (void) fclose(pidfile);
        }
    }

    if (config.stats_filename != NULL) {
        if (pthread_create(&stats_thread, NULL, stats_writeout_thread, NULL)) {
            syslog(LOG_WARNING, "Could not create stats writeout thread");
        }
    } else {
        syslog(LOG_INFO, "No stats file specified in config. Stats reporting disabled");
    }

    render_threads = (pthread_t *) malloc(sizeof(pthread_t) * config.num_threads);

    for(i=0; i<config.num_threads; i++) {
        if (pthread_create(&render_threads[i], NULL, render_thread, (void *)maps)) {
            fprintf(stderr, "error spawning render thread\n");
            close(fd);
            exit(7);
        }
    }

    if (active_slave == 0) {
        //Only the master renderd opens connections to its slaves
        k = 0;
        slave_threads
                = (pthread_t *) malloc(sizeof(pthread_t) * noSlaveRenders);
        for (i = 1; i < MAX_SLAVES; i++) {
            for (j = 0; j < config_slaves[i].num_threads; j++) {
                if (pthread_create(&slave_threads[k++], NULL, slave_thread,
                        (void *) &config_slaves[i])) {
                    fprintf(stderr, "error spawning render thread\n");
                    close(fd);
                    exit(7);
                }
            }
        }
    }

    process_loop(fd);

    unlink(config.socketname);
    close(fd);
    return 0;
}
int main(int argc, char argv[])
{
	int ret = 0;
	struct sockaddr_in client_address;
	int client_fd = 0;
	printf("\n");
	printf("Welcome to Chat Server....\n"); 
	memset(&serverStats, 0, sizeof(struct ServerStats_t));
	serverStats.max_threads = MAX_THREADS;
	// start the main and make the server listen on port 12345
	if (server_socket_init() == -1)
	{
		printf("An error occured. Closing program \n");
		return 1 ;
	}

	//server_wait_client(server_fd);
	while(1)
	{
		//int rfd;
		int *arg; 
		char ipstr[INET6_ADDRSTRLEN];
        	int port;
        	int new_sd;
		int ret =0;
        	struct sockaddr_storage remote_info ;
		pthread_t threads[MAX_THREADS];
        	socklen_t addr_size;
        	addr_size = sizeof(addr_size);
        	new_sd = accept(server_fd, (struct sockaddr *) &remote_info, &addr_size);
        	getpeername(new_sd, (struct sockaddr*)&remote_info, &addr_size);

        	// deal with both IPv4 and IPv6:
        	if (remote_info.ss_family == AF_INET)
        	{
			struct sockaddr_in *s = (struct sockaddr_in *)&remote_info;
			port = ntohs(s->sin_port);
			inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
        	} 
		else
        	{
                // AF_INET6
                struct sockaddr_in6 *s = (struct sockaddr_in6 *)&remote_info;
                port = ntohs(s->sin6_port);
                inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
        	}	

	        printf("\n");
		if(new_sd >= 0)
		{
			printf("Server accepted new connection on socket id :%d\n", new_sd);
			/* A connection between a client and the server has been established.
			 * Now create a new thread and handover the client_sockfd
			 */
			pthread_mutex_lock(&curr_thread_count_mutex);
			if (curr_thread_count < MAX_THREADS)
			{
				/* Prepare client infos in handy structure */
				client_info *ci = (client_info *)malloc(sizeof(client_info));
				ci->sockfd = new_sd;
				ci->address = remote_info;
				sprintf(ci->nickname, "Client_%d\n", new_sd);

				/* Add client info to linked list */
				llist_insert(&list_start, ci);
				llist_show(&list_start);
				/* System Monitoring Statistics Counter : Increments the number of active_connections 
				   counter. Shows the number of active clients*/
				serverStats.num_of_active_connections++;

				/* Pass client info and invoke new thread */
				ret = pthread_create(&threads[curr_thread_count],
						NULL,
						(void *)&server_read_client,
						(void *)&new_sd); /* only pass socket id ? */
				if (ret == 0)
				{
					serverStats.num_of_clients_serviced++;
					pthread_detach(threads[curr_thread_count]);
					curr_thread_count++;

					/* Notify server and clients */
					printf("User %s joined the chat.\n", ci->nickname);
					printf("Connections used: %d of %d\n", curr_thread_count, MAX_THREADS);
				}
				else
				{
					serverStats.num_of_conn_dropped++;
					llist_remove_by_sockfd(&list_start, new_sd);
					serverStats.num_of_active_connections--;
					free(ci);
					close(new_sd);
				}
			}
			else
			{
				serverStats.num_of_conn_dropped++;
				printf("Max. connections reached. Connection limit is %d. Connection dropped.\n", MAX_THREADS);
				close(new_sd);
			}
			pthread_mutex_unlock(&curr_thread_count_mutex);
		}
		else
		{
			/* Connection could not be established. Post error and exit. */
			//perror(strerror(errno));
			printf("Error creating socket\n");
			exit(-1);
		}
	}

	return 0;
}