Handle shutdown

This commit is contained in:
James Booth
2015-05-24 00:55:39 +01:00
parent ed7e7e9670
commit 23cbdc9013
8 changed files with 48 additions and 27 deletions

View File

@@ -28,3 +28,9 @@ stbbr_for(char *id, char *stream)
prime_for(id, stream); prime_for(id, stream);
return 1; return 1;
} }
void
stbbr_stop(void)
{
server_stop();
}

View File

@@ -95,6 +95,7 @@ void
parser_close(void) parser_close(void)
{ {
XML_ParserFree(parser); XML_ParserFree(parser);
parser = NULL;
} }
void void

View File

@@ -17,9 +17,12 @@ void
prime_free_all(void) prime_free_all(void)
{ {
free(required_passwd); free(required_passwd);
required_passwd = NULL;
if (idstubs) { if (idstubs) {
g_hash_table_destroy(idstubs); g_hash_table_destroy(idstubs);
} }
idstubs = NULL;
} }
void void

View File

@@ -26,9 +26,9 @@
static XMPPClient *client; static XMPPClient *client;
static void _shutdown(void); static void _shutdown(void);
static void _signal_handler(int sig);
static int listen_socket; static int listen_socket;
static pthread_t server_thread;
void void
write_stream(const char * const stanza) write_stream(const char * const stanza)
@@ -50,7 +50,7 @@ write_stream(const char * const stanza)
} else { } else {
log_println(""); log_println("");
log_println("Error sending on connection: %s", strerror(errno)); log_println("Error sending on connection: %s", strerror(errno));
exit(0); return;
} }
} }
@@ -77,7 +77,7 @@ read_stream(void)
log_println(""); log_println("");
log_println("%s:%d - Client disconnected.", client->ip, client->port); log_println("%s:%d - Client disconnected.", client->ip, client->port);
g_string_free(stream, TRUE); g_string_free(stream, TRUE);
exit(0); return -1;
} }
// error // error
@@ -92,7 +92,7 @@ read_stream(void)
log_println(""); log_println("");
log_println("Error receiving on connection: %s", strerror(errno)); log_println("Error receiving on connection: %s", strerror(errno));
g_string_free(stream, TRUE); g_string_free(stream, TRUE);
exit(0); return -1;
} }
} }
@@ -104,7 +104,8 @@ read_stream(void)
log_print_chars("\n"); log_print_chars("\n");
log_println("--> Stream end callback fired"); log_println("--> Stream end callback fired");
write_stream(STREAM_END); write_stream(STREAM_END);
break; _shutdown();
return 0;
} }
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
} }
@@ -144,7 +145,7 @@ auth_callback(XMPPStanza *stanza)
if (g_strcmp0(client->password, expected_password) != 0) { if (g_strcmp0(client->password, expected_password) != 0) {
write_stream(AUTH_FAIL); write_stream(AUTH_FAIL);
write_stream(STREAM_END); write_stream(STREAM_END);
exit(0); return;
} }
write_stream(AUTH_RESP); write_stream(AUTH_RESP);
@@ -172,7 +173,7 @@ _start_server_cb(void* userdata)
int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK); int res = fcntl(listen_socket, F_SETFL, fcntl(listen_socket, F_GETFL, 0) | O_NONBLOCK);
if (res == -1) { if (res == -1) {
log_println("Error setting nonblocking on listen socket: %s", strerror(errno)); log_println("Error setting nonblocking on listen socket: %s", strerror(errno));
exit(0); return NULL;
} }
// listen socket read timeout // listen socket read timeout
@@ -183,7 +184,7 @@ _start_server_cb(void* userdata)
res = setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); res = setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
if (res < 0) { if (res < 0) {
log_println("Error setting listen socket options: %s", strerror(errno)); log_println("Error setting listen socket options: %s", strerror(errno));
exit(0); return NULL;
} }
// wait for connection // wait for connection
@@ -193,7 +194,7 @@ _start_server_cb(void* userdata)
while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) { while ((client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, (socklen_t*)&c)) == -1) {
if (errno != EAGAIN && errno != EWOULDBLOCK) { if (errno != EAGAIN && errno != EWOULDBLOCK) {
log_println("Accept failed: %s", strerror(errno)); log_println("Accept failed: %s", strerror(errno));
exit(0); return NULL;
} }
errno = 0; errno = 0;
} }
@@ -202,7 +203,7 @@ _start_server_cb(void* userdata)
res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK); res = fcntl(client_socket, F_SETFL, fcntl(client_socket, F_GETFL, 0) | O_NONBLOCK);
if (res == -1) { if (res == -1) {
log_println("Error setting nonblocking on client socket: %s", strerror(errno)); log_println("Error setting nonblocking on client socket: %s", strerror(errno));
exit(0); return NULL;
} }
// client socket read timeout // client socket read timeout
@@ -210,7 +211,7 @@ _start_server_cb(void* userdata)
res = setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); res = setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
if (res < 0) { if (res < 0) {
log_println("Error setting client socket options: %s", strerror(errno)); log_println("Error setting client socket options: %s", strerror(errno));
exit(0); return NULL;
} }
client = xmppclient_new(client_addr, client_socket); client = xmppclient_new(client_addr, client_socket);
@@ -229,16 +230,12 @@ server_run(int port)
log_init(); log_init();
log_println("Starting on port: %d...", port); log_println("Starting on port: %d...", port);
// signal handlers
signal(SIGSTOP, _signal_handler);
signal(SIGINT, _signal_handler);
atexit(_shutdown);
// create listen socket // create listen socket
errno = 0; errno = 0;
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if (listen_socket == -1) { if (listen_socket == -1) {
log_println("Could not create socket: %s", strerror(errno)); log_println("Could not create socket: %s", strerror(errno));
_shutdown();
return -1; return -1;
} }
@@ -247,11 +244,20 @@ server_run(int port)
server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port); server_addr.sin_port = htons(port);
int reuse = 1;
int ret = setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
if (ret == -1) {
log_println("Set socket options failed: %s", strerror(errno));
_shutdown();
return -1;
}
// bind socket to port // bind socket to port
errno = 0; errno = 0;
int ret = bind(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)); ret = bind(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (ret == -1) { if (ret == -1) {
log_println("Bind failed: %s", strerror(errno)); log_println("Bind failed: %s", strerror(errno));
_shutdown();
return -1; return -1;
} }
@@ -260,6 +266,7 @@ server_run(int port)
ret = listen(listen_socket, 5); ret = listen(listen_socket, 5);
if (ret == -1) { if (ret == -1) {
log_println("Listen failed: %s", strerror(errno)); log_println("Listen failed: %s", strerror(errno));
_shutdown();
return -1; return -1;
} }
@@ -268,32 +275,33 @@ server_run(int port)
prime_init(); prime_init();
// start client processor thread // start client processor thread
pthread_t server_thread;
int res = pthread_create(&server_thread, NULL, _start_server_cb, NULL); int res = pthread_create(&server_thread, NULL, _start_server_cb, NULL);
if (res != 0) { if (res != 0) {
_shutdown();
return -1; return -1;
} }
pthread_detach(server_thread);
return 0; return 0;
} }
void
server_stop(void)
{
pthread_join(server_thread, NULL);
}
static void static void
_shutdown(void) _shutdown(void)
{
_signal_handler(-1);
}
static void
_signal_handler(int sig)
{ {
log_println("SHUTDOWN"); log_println("SHUTDOWN");
// stanza_show_all(); // stanza_show_all();
xmppclient_end_session(client); xmppclient_end_session(client);
client = NULL;
parser_close(); parser_close();
while (recv(listen_socket, NULL, 1, 0) > 0) {}
shutdown(listen_socket, 2); shutdown(listen_socket, 2);
while (recv(listen_socket, NULL, 1, 0) > 0) {}
close(listen_socket); close(listen_socket);
prime_free_all(); prime_free_all();

View File

@@ -2,4 +2,5 @@
#define __H_SERVER #define __H_SERVER
int server_run(int port); int server_run(int port);
void server_stop(void);
#endif #endif

View File

@@ -192,4 +192,5 @@ void
stanza_free_all(void) stanza_free_all(void)
{ {
g_list_free_full(stanzas, (GDestroyNotify)_stanza_free); g_list_free_full(stanzas, (GDestroyNotify)_stanza_free);
stanzas = NULL;
} }

View File

@@ -28,8 +28,8 @@ xmppclient_end_session(XMPPClient *client)
{ {
if (client) { if (client) {
if (client->sock) { if (client->sock) {
while (recv(client->sock, NULL, 1, 0) > 0) {}
shutdown(client->sock, 2); shutdown(client->sock, 2);
while (recv(client->sock, NULL, 1, 0) > 0) {}
close(client->sock); close(client->sock);
} }
free(client->ip); free(client->ip);

View File

@@ -2,6 +2,7 @@
#define __H_STABBER #define __H_STABBER
int stbbr_start(int port); int stbbr_start(int port);
void stbbr_stop(void);
int stbbr_auth_passwd(char *password); int stbbr_auth_passwd(char *password);
void stbbr_for(char *id, char *stream); void stbbr_for(char *id, char *stream);