// Set default options that were not set by user..
static int set_undefined_options(ad_server_t *server) {
    int newentries = 0;
    char *default_options[][2] = AD_SERVER_OPTIONS;
    for (int i = 0; ! IS_EMPTY_STR(default_options[i][0]); i++) {
        if (! ad_server_get_option(server, default_options[i][0])) {
            ad_server_set_option(server, default_options[i][0], default_options[i][1]);
            newentries++;
        }
        DEBUG("%s=%s", default_options[i][0], ad_server_get_option(server, default_options[i][0]));
    }
    return newentries;
}
Exemple #2
0
/* Main HelpServ routine. */
void helpserv(const char *source, User *callerUser, char *buf) {

	TRACE_MAIN_FCLT(FACILITY_HELPSERV);

	if (IS_NULL(buf) || IS_EMPTY_STR(buf))
		send_notice_lang_to_user(s_HelpServ, callerUser, GetCallerLang(), ERROR_ACCESS_DENIED);

	else if (buf[0] == '\001') {

		if (IS_EMPTY_STR(buf + 1))
			LOG_SNOOP(s_HelpServ, "Invalid CTCP from \2%s\2", source);

		else if (str_equals_nocase(buf + 1, "PING")) {

			send_notice_to_user(s_HelpServ, callerUser, "\1%s", buf + 1);
			LOG_SNOOP(s_HelpServ, "CTCP: PING from \2%s\2", source);
		}
		else {

			if (buf[str_len(buf) - 1] == '\001')
				buf[str_len(buf) - 1] = '\0';

			LOG_SNOOP(s_HelpServ, "CTCP: %s from \2%s\2", buf + 1, source);
		}
	}
	else {

		ServiceCommandData data;

		data.commandName = buf;
		data.userLevel = ULEVEL_NOACCESS;
		data.operMatch = TRUE;
		data.operName = NULL;
		data.agent = &a_HelpServ;

		handle_help(source, callerUser, &data);
	}
}
Exemple #3
0
STR str_tokenize(CSTR string, STR token, size_t token_len, char delimiter) {

	STR		lim;

	if (IS_NULL(string) || IS_EMPTY_STR(string))
		return NULL;

	lim = token + token_len - 1;

	while (*string && (token < lim)) {

		if (*string == delimiter) {

			*token = 0;
			return (STR) (string + 1);
		}

		*token++ = *string++;
	}

	*token = 0;

	return (STR)string;
}
/**
 * Start server.
 *
 * @return 0 if successful, otherwise -1.
 */
int ad_server_start(ad_server_t *server) {
    DEBUG("Starting a server.");

    // Set default options that were not set by user..
    set_undefined_options(server);

    // Hookup libevent's log message.
    if (_ad_log_level >= AD_LOG_DEBUG) {
        event_set_log_callback(libevent_log_cb);
        if (_ad_log_level >= AD_LOG_DEBUG2) {
            event_enable_debug_mode();
        }
    }

    // Parse addr
    int port = ad_server_get_option_int(server, "server.port");
    char *addr = ad_server_get_option(server, "server.addr");
    struct sockaddr *sockaddr = NULL;
    size_t sockaddr_len = 0;
    if (addr[0] == '/') {  // Unix socket.
        struct sockaddr_un unixaddr;
        bzero((void *) &unixaddr, sizeof(struct sockaddr_un));
        if (strlen(addr) >= sizeof(unixaddr.sun_path)) {
            errno = EINVAL;
            DEBUG("Too long unix socket name. '%s'", addr);
            return -1;
        }
        unixaddr.sun_family = AF_UNIX;
        strcpy(unixaddr.sun_path, addr);  // no need of strncpy()
        sockaddr = (struct sockaddr *) &unixaddr;
        sockaddr_len = sizeof(unixaddr);
    } else if (strstr(addr, ":")) {  // IPv6
        struct sockaddr_in6 ipv6addr;
        bzero((void *) &ipv6addr, sizeof(struct sockaddr_in6));
        ipv6addr.sin6_family = AF_INET6;
        ipv6addr.sin6_port = htons(port);
        evutil_inet_pton(AF_INET6, addr, &ipv6addr.sin6_addr);
        sockaddr = (struct sockaddr *) &ipv6addr;
        sockaddr_len = sizeof(ipv6addr);
    } else {  // IPv4
        struct sockaddr_in ipv4addr;
        bzero((void *) &ipv4addr, sizeof(struct sockaddr_in));
        ipv4addr.sin_family = AF_INET;
        ipv4addr.sin_port = htons(port);
        ipv4addr.sin_addr.s_addr =
                (IS_EMPTY_STR(addr)) ? INADDR_ANY : inet_addr(addr);
        sockaddr = (struct sockaddr *) &ipv4addr;
        sockaddr_len = sizeof(ipv4addr);
    }

    // SSL
    if (!server->sslctx && ad_server_get_option_int(server, "server.enable_ssl")) {
        char *cert_path = ad_server_get_option(server, "server.ssl_cert");
        char *pkey_path = ad_server_get_option(server, "server.ssl_pkey");
        server->sslctx = init_ssl(cert_path, pkey_path);
        if (server->sslctx == NULL) {
            ERROR("Couldn't load certificate file(%s) or private key file(%s).",
                  cert_path, pkey_path);
            return -1;
        }
        DEBUG("SSL Initialized.");
    }

    // Bind
    if (! server->evbase) {
        server->evbase = event_base_new();
        if (! server->evbase) {
            ERROR("Failed to create a new event base.");
            return -1;
        }
    }

    // Create a eventfd for notification channel.
    int notifyfd = eventfd(0, 0);
    server->notify_buffer = bufferevent_socket_new(server->evbase, notifyfd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(server->notify_buffer, NULL, notify_cb, NULL, server);

    if (! server->listener) {
        server->listener = evconnlistener_new_bind(
                server->evbase, listener_cb, (void *)server,
                LEV_OPT_THREADSAFE | LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
                ad_server_get_option_int(server, "server.backlog"),
                sockaddr, sockaddr_len);
        if (! server->listener) {
            ERROR("Failed to bind on %s:%d", addr, port);
            return -1;
        }
    }

    // Listen
    INFO("Listening on %s:%d%s", addr, port, ((server->sslctx) ? " (SSL)" : ""));

    int exitstatus = 0;
    if (ad_server_get_option_int(server, "server.thread")) {
        DEBUG("Launching server as a thread.")
        server->thread = NEW_OBJECT(pthread_t);
        pthread_create(server->thread, NULL, &server_loop, (void *)server);
        //pthread_detach(server->thread);
    } else {
        int *retval = server_loop(server);
        exitstatus = *retval;
        free(retval);

        close_server(server);
        if (ad_server_get_option_int(server, "server.free_on_stop")) {
            ad_server_free(server);
        }
    }

    return exitstatus;
}