yasnd/daemon/yasnd-sock.c

150 lines
3.1 KiB
C
Raw Normal View History

#include <stdio.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <linux/un.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdbool.h>
#include "yasnd-log.h"
#include "yasnd-lpt.h"
2012-04-28 13:27:04 +04:00
const char sock_path[]="/var/run/yasnd.sock";
pthread_t server_thread_handle; // server socket thread handle
int socket_fd; // server socket descriptor
#define STATUS_OK (void*)0
#define STATUS_ERROR (void*)1
void* connection_handler(void* param)
{
// Get connection descriptor
int connection_fd=*(int*)param;
// Buffer for client command and command's actual length
char buffer[256];
int nbytes;
// Token for string splitting
char* token;
// Status of command parsing (default is OK)
void* thread_status = STATUS_OK;
while ( (nbytes = read(connection_fd, buffer, 256)) != -1 )
{
buffer[nbytes] = 0;
token = strtok(buffer, " ");
if (token == NULL)
{
// empty input from client
thread_status = STATUS_ERROR;
break;
}
// Exit function
if (strncmp(token, "exit", 4) == 0)
{
// just break loop and thus close client connection
break;
}
// Reset function
if (strncmp(token, "reset", 5) == 0)
{
// Get parameter for reset call and convert it to long
long value = strtol(strtok(NULL, " "), (char **) NULL, 10);
// Call reset_pin function
reset_pin((int)value);
// continue waiting client commands
continue;
}
}
// Close client connection descriptor
close(connection_fd);
// Exit client thread and return apropriate status
pthread_exit(thread_status);
}
void* server_socket(void* param)
{
struct sockaddr_un address;
int connection_fd;
socklen_t address_length;
pthread_t child_handle; // connection thread handle
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0)
{
log_event("socket creation failed");
return (void*)1;
}
// Remove old socket file
unlink(sock_path);
// start with a clean address structure
memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, sock_path);
// Set umask value for new socket file
mode_t old_umask = umask(077);
// Create(bind) socket
if(bind(socket_fd,
(struct sockaddr *) &address,
sizeof(struct sockaddr_un)) != 0)
{
log_event("bind() call failed");
return (void*)1;
}
// Return previous umask value
umask(old_umask);
if(listen(socket_fd, 5) != 0)
{
log_event("listen() call failed");
return (void*)1;
}
while((connection_fd = accept(socket_fd, (struct sockaddr *) &address, &address_length)) > -1)
{
if(pthread_create(&child_handle,NULL,connection_handler,&connection_fd) != 0)
{
log_event("Client connection thread creation failed");
}
else
pthread_detach(child_handle);
}
return (void*)0;
}
2012-03-23 14:06:39 +04:00
int sock_init()
{
if(pthread_create(&server_thread_handle,NULL,server_socket,NULL) != 0)
{
log_event("Server socket thread creation failed");
}
2012-03-23 14:06:39 +04:00
}
void sock_close()
{
// Terminate server socket handling thread
pthread_cancel(server_thread_handle);
// Close server socket
close(socket_fd);
// Remove unneeded socket file
unlink(sock_path);
2012-03-23 14:06:39 +04:00
}