/* End playing and cleanup. */ static void server_shutdown () { logit ("Server exiting..."); audio_exit (); tags_cache_free (tags_cache); tags_cache = NULL; unlink (socket_name()); unlink (create_file_name(PID_FILE)); close (wake_up_pipe[0]); close (wake_up_pipe[1]); logit ("Server exited"); log_close (); }
/* End playing and cleanup. */ static void server_shutdown () { logit ("Server exiting..."); audio_exit (); tags_cache_save (&tags_cache, create_file_name("tags_cache")); tags_cache_destroy (&tags_cache); unlink (socket_name()); unlink (create_file_name(PID_FILE)); close (wake_up_pipe[0]); close (wake_up_pipe[1]); logit ("Server exited"); log_close (); }
/* Connect to the server, return fd of the socket or -1 on error. */ static int server_connect () { struct sockaddr_un sock_name; int sock; /* Create a socket */ if ((sock = socket (PF_LOCAL, SOCK_STREAM, 0)) == -1) return -1; sock_name.sun_family = AF_LOCAL; strcpy (sock_name.sun_path, socket_name()); if (connect(sock, (struct sockaddr *)&sock_name, SUN_LEN(&sock_name)) == -1) { close (sock); return -1; } return sock; }
/* Connect to the server, return fd of the socket or -1 on error. */ static int server_connect () { struct sockaddr_un sock_name; int sock; /* Create a socket. * For reasons why AF_UNIX is the correct constant to use in both * cases, see the commentary the SVN log for commit r2833. */ if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) return -1; sock_name.sun_family = AF_UNIX; strcpy (sock_name.sun_path, socket_name()); if (connect(sock, (struct sockaddr *)&sock_name, SUN_LEN(&sock_name)) == -1) { close (sock); return -1; } return sock; }
/* Initialize the server - return fd of the listening socket or -1 on error */ void server_init (int debugging, int foreground) { struct sockaddr_un sock_name; pid_t pid; logit ("Starting MOC Server"); assert (server_sock == -1); pid = check_pid_file (); if (pid && valid_pid(pid)) { fprintf (stderr, "\nIt seems that the server is already running" " with pid %d.\n", pid); fprintf (stderr, "If it is not true, remove the pid file (%s)" " and try again.\n", create_file_name(PID_FILE)); fatal ("Exiting!"); } if (foreground) log_init_stream (stdout, "stdout"); else { FILE *logfp; logfp = NULL; if (debugging) { logfp = fopen (SERVER_LOG, "a"); if (!logfp) fatal ("Can't open server log file: %s", xstrerror (errno)); } log_init_stream (logfp, SERVER_LOG); } if (pipe(wake_up_pipe) < 0) fatal ("pipe() failed: %s", xstrerror (errno)); unlink (socket_name()); /* Create a socket. * For reasons why AF_UNIX is the correct constant to use in both * cases, see the commentary the SVN log for commit r9999. */ server_sock = socket (AF_UNIX, SOCK_STREAM, 0); if (server_sock == -1) fatal ("Can't create socket: %s", xstrerror (errno)); sock_name.sun_family = AF_UNIX; strcpy (sock_name.sun_path, socket_name()); /* Bind to socket */ if (bind(server_sock, (struct sockaddr *)&sock_name, SUN_LEN(&sock_name)) == -1) fatal ("Can't bind() to the socket: %s", xstrerror (errno)); if (listen(server_sock, 1) == -1) fatal ("listen() failed: %s", xstrerror (errno)); /* Log stack sizes so stack overflows can be debugged. */ log_process_stack_size (); log_pthread_stack_size (); clients_init (); audio_initialize (); tags_cache = tags_cache_new (options_get_int("TagsCacheSize")); tags_cache_load (tags_cache, create_file_name("cache")); server_tid = pthread_self (); xsignal (SIGTERM, sig_exit); xsignal (SIGINT, foreground ? sig_exit : SIG_IGN); xsignal (SIGHUP, SIG_IGN); xsignal (SIGQUIT, sig_exit); xsignal (SIGPIPE, SIG_IGN); xsignal (SIGCHLD, sig_chld); write_pid_file (); if (!foreground) { setsid (); redirect_output (stdin); redirect_output (stdout); redirect_output (stderr); } return; }
/* Initialize the server - return fd of the listening socket or -1 on error */ int server_init (int debugging, int foreground) { struct sockaddr_un sock_name; int server_sock; int pid; logit ("Starting MOC Server"); pid = check_pid_file (); if (pid && valid_pid(pid)) { fprintf (stderr, "\nIt seems that the server is already running" " with pid %d.\n", pid); fprintf (stderr, "If it is not true, remove the pid file (%s)" " and try again.\n", create_file_name(PID_FILE)); fatal ("Exiting!"); } if (foreground) log_init_stream (stdout, "stdout"); else { FILE *logfp; logfp = NULL; if (debugging) { logfp = fopen (SERVER_LOG, "a"); if (!logfp) fatal ("Can't open server log file: %s", strerror (errno)); } log_init_stream (logfp, SERVER_LOG); } if (pipe(wake_up_pipe) < 0) fatal ("pipe() failed: %s", strerror(errno)); unlink (socket_name()); /* Create a socket */ if ((server_sock = socket (PF_LOCAL, SOCK_STREAM, 0)) == -1) fatal ("Can't create socket: %s", strerror(errno)); sock_name.sun_family = AF_LOCAL; strcpy (sock_name.sun_path, socket_name()); /* Bind to socket */ if (bind(server_sock, (struct sockaddr *)&sock_name, SUN_LEN(&sock_name)) == -1) fatal ("Can't bind() to the socket: %s", strerror(errno)); if (listen(server_sock, 1) == -1) fatal ("listen() failed: %s", strerror(errno)); audio_initialize (); tags_cache_init (&tags_cache, options_get_int("TagsCacheSize")); tags_cache_load (&tags_cache, create_file_name("cache")); clients_init (); server_tid = pthread_self (); thread_signal (SIGTERM, sig_exit); thread_signal (SIGINT, foreground ? sig_exit : SIG_IGN); thread_signal (SIGHUP, SIG_IGN); thread_signal (SIGQUIT, sig_exit); thread_signal (SIGPIPE, SIG_IGN); write_pid_file (); if (!foreground) { setsid (); redirect_output (stdin); redirect_output (stdout); redirect_output (stderr); } return server_sock; }
int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags) { char *passive[] = {"::", "0.0.0.0"}; int sock = -1, pfamily, try_ok; sockname_t dest_name, src_name; /* If no source ip address is given, try :: and 0.0.0.0 (passive). */ for (try_ok = 0; try_ok < 2; try_ok++) { /* Resolve the ip addresses. */ socket_name(&dest_name, dest_ip ? dest_ip : passive[try_ok], dest_port); socket_name(&src_name, src_ip ? src_ip : passive[try_ok], src_port); if (src_ip || src_port) flags |= SOCKET_BIND; if (flags & SOCKET_CLIENT) pfamily = dest_name.family; else if (flags & SOCKET_SERVER) pfamily = src_name.family; else { errno = EADDRNOTAVAIL; return(-1); } /* Create the socket. */ if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0); else sock = socket(pfamily, SOCK_STREAM, 0); if (sock >= 0) break; } if (sock < 0) return(-2); allocsock(sock, 0); if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1); /* Do the bind if necessary. */ if (flags & (SOCKET_SERVER|SOCKET_BIND)) { int yes = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(sock, &src_name.u.addr, src_name.len) != 0) { killsock(sock); return(-3); } if (flags & SOCKET_SERVER) listen(sock, 50); } if (flags & SOCKET_CLIENT) { int i = -1; if ((i = findanysnum(sock)) != -1) { socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS; socklist[i].host = strdup(dest_ip); socklist[i].port = dest_port; } if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) { if (errno != EINPROGRESS) { killsock(sock); return(-4); } } } errno = 0; /* Yay, we're done. */ return(sock); }