26#include <sys/socket.h>
56 debug ( 3,
"Forgeting clsyncsock #%u", i );
98 [
SOCKCMD_REPLY_INFO] =
"config_block == \"%s\"; label == \"%s\"; flags == %x; flags_set == %x.",
111 socklen_t error_code_len =
sizeof ( error_code );
113 if ( ( ret = getsockopt ( sock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_len ) ) ) {
132 clsyncsock_t *clsyncsock_p = xmalloc (
sizeof ( *clsyncsock_p ) );
133 debug ( 2,
"sock == %i.", clsyncsock_sock );
134 clsyncsock_p->
sock = clsyncsock_sock;
142 int clsyncsock_sock = clsyncsock_p->
sock;
143 debug ( 2,
"sock == %i.", clsyncsock_sock );
146 free ( clsyncsock_p );
152 close ( clsyncsock_p->
sock );
160 thread_id = threaddata_p->
id;
182 int clsyncsock_sock = accept ( sock, NULL, NULL );
184 if ( clsyncsock_sock == -1 ) {
185 error (
"socket_accept(%i): Cannot accept()", sock );
196 s = socket ( AF_UNIX, SOCK_STREAM, 0 );
200 if ( !access ( socket_path, F_OK ) )
201 if ( unlink ( socket_path ) ) {
202 error (
"Cannot unlink() \"%s\".",
210 struct sockaddr_un addr;
211 memset ( &addr, 0,
sizeof ( addr ) );
212 addr.sun_family = AF_UNIX;
213 strncpy ( addr.sun_path, socket_path, sizeof ( addr.sun_path ) - 1 );
215 if ( bind ( s, (
struct sockaddr * ) &addr,
sizeof ( addr ) ) ) {
216 error (
"Cannot bind() on address \"%s\".",
225 error (
"Cannot listen() on address \"%s\".",
234#ifdef SOCKET_PROVIDER_LIBCLSYNC
239 s = socket ( AF_UNIX, SOCK_STREAM, 0 );
245 if ( access ( socket_path, F_OK ) ) {
246 error (
"Cannot access() to \"%s\".",
254 struct sockaddr_un addr;
255 memset ( &addr, 0,
sizeof ( addr ) );
256 addr.sun_family = AF_UNIX;
257 strncpy ( addr.sun_path, socket_path, sizeof ( addr.sun_path ) - 1 );
259 if ( connect ( s, (
struct sockaddr * ) &addr,
sizeof ( addr ) ) ) {
260 error (
"Cannot connect() to address \"%s\".",
273 # define PREBUF0_SIZE ((SOCKET_BUFSIZ >> 1) - 128)
274 # define PREBUF1_SIZE (SOCKET_BUFSIZ >> 1)
286 va_copy ( ap_copy, ap );
291 va_copy ( ap_copy, ap );
297 size_t sendlen = snprintf (
301 cmd_id, prebuf0, prebuf1
306 debug ( 5,
"send(): \"%s\"", sendbuf );
316 goto l_socket_send_end;
324 goto l_socket_send_end;
335 uint64_t cmd_num = sockcmd_p->
cmd_num;
336 va_start ( ap, cmd_id );
337 ret =
_socket_send ( clsyncsock_p, &cmd_num, cmd_id, ap );
346 va_start ( ap, cmd_id );
356 error (
"Callback queue overflowed. Closing the socket." );
364 uint64_t cmd_num = clsyncsock_p->
cmd_num;
365 va_start ( ap, cb_arg );
389 debug ( 3,
"buf==%p; data_start==%p; data_end==%p", buf, *data_start_p, *data_end_p );
391 if ( buf == *data_start_p )
394 size_t ptr_diff = *data_start_p - buf;
396 if ( *data_start_p != *data_end_p ) {
402 size_t data_length = *data_end_p - *data_start_p;
403 memmove ( buf, *data_start_p, data_length );
405 *data_end_p = &buf[data_length];
409#define PARSE_TEXT_DATA_SSCANF(dat_t, ...) {\
410 sockcmd_p->data = xmalloc(sizeof(dat_t));\
411 dat_t *d = (dat_t *)sockcmd_p->data;\
412 if (sscanf(args, textmessage_args[sockcmd_p->cmd_id], __VA_ARGS__) < min_args)\
418 debug ( 6,
"(%p, %p, %u)", sockcmd_p, args, args_len );
439 switch ( sockcmd_p->
cmd_id ) {
462 if ( args_len >
sizeof ( 1 << 8 ) )
463 args[args_len = 1 << 8] = 0;
469 if ( args_len >
sizeof ( 1 << 8 ) )
470 args[args_len = 1 << 8] = 0;
492 sockcmd_p->
data = xmalloc ( args_len + 1 );
493 memcpy ( sockcmd_p->
data, args, args_len );
494 ( (
char * ) sockcmd_p->
data ) [args_len] = 0;
504 char *buf, *ptr, *start, *end;
506 size_t filled_length, rest_length, filled_length_new;
510 buf = bufs[clsyncsock_sock];
512 start = ( start == NULL ? buf : start );
514 ptr = ( ptr == NULL ? buf : ptr );
515 debug ( 3,
"buf==%p; start==%p; ptr==%p", buf, start, ptr );
518 filled_length = ptr - buf;
521 if ( rest_length <= 0 ) {
523 debug ( 1,
"Got too big message. Ignoring." );
530 recv_length = recv ( clsyncsock_sock, ptr, rest_length, 0 );
531 filled_length_new = filled_length + recv_length;
532 debug ( 5,
"recv_length == %u; filled_length_new == %u", recv_length, filled_length_new );
534 if ( recv_length == 0 )
537 if ( recv_length < 0 )
543 uint16_t cmd_id_binary = * ( uint16_t * ) buf;
553 if ( ( end = strchr ( ptr,
'\n' ) ) != NULL ) {
554 if ( sscanf ( start,
"%lu %u", &sockcmd_p->
cmd_num, (
unsigned int * ) &sockcmd_p->
cmd_id ) != 2 ) {
556 error (
"It's expected to parse \"%%lu %%u\" from \"%s\"", start );
558 return errno = ENOMSG;
561 char *str_args = start;
564 while ( *str_args >=
'0' && *str_args <=
'9' ) str_args++;
570 while ( *str_args >=
'0' && *str_args <=
'9' ) str_args++;
576 if ( end > str_args )
580 goto l_socket_recv_end;
586 return errno = ENOPROTOOPT;
593 return errno = ENOPROTOOPT;
604 ptr = &buf[filled_length_new];
608 if ( start == ptr ) {
616 debug ( 3,
"sockcmd_p->cmd_num == %lu; sockcmd_p->cmd_id == %i; buf==%p; ptr==%p; end==%p, filled=%p, buf_end==%p",
623 if ( sockcmd_p->
cmd_id >= 1000 )
637 AUTHFLAG_ENTERED_LOGIN = 0x01,
639 typedef enum auth_flags auth_flags_t;
640 auth_flags_t auth_flags = 0;
641 debug ( 3,
"Started new thread for new connection." );
646 debug ( 3,
"Iteration." );
650 if ( ( ret =
socket_recv ( clsyncsock_p, sockcmd_p ) ) ) {
651 debug ( 2,
"Got error while receiving a message from clsyncsock with sock %u. Ending the thread.",
658 uint64_t cmd_num = sockcmd_p->
cmd_num;
678 if ( procfunct ( arg, sockcmd_p ) )
679 switch ( sockcmd_p->
cmd_id ) {
684 switch ( data->
prot ) {
729 if ( sockcmd_p->
data != NULL ) {
730 free ( sockcmd_p->
data );
731 sockcmd_p->
data = NULL;
736 debug ( 1,
"clsyncsock socket error: %s", strerror ( errno ) );
741 switch ( arg->
state ) {
743 if ( ! ( auth_flags & AUTHFLAG_ENTERED_LOGIN ) )
753 debug ( 3,
"Ending a connection thread." );
764 error (
"Warning: socket_thread_new(): Too many connection threads." );
781 error (
"Internal-Error: socket_newconnarg(): connproc_arg->state != CLSTATE_NONE" );
789 debug ( 3,
"clsyncsockthreads_count == %u;\tclsyncsockthreads_last == %u;\tclsyncsockthreads_num == %u",
801 if ( threaddata_p == NULL )
811 error (
"Cannot create a thread for connection" );
#define CLSYNCSOCK_WINDOW
#define debug(debug_level,...)
socket_sockthreaddata_t sockthreaddata[8+1]
int socket_send(clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id,...)
clsyncsock_t * socket_listen_unix(const char *const socket_path)
char clsyncsockthread_busy[8+1]
int clsyncsockthreads_count
int clsyncsockthreads_num
static int socket_check(clsyncsock_t *clsyncsock_p)
int clsyncsockthreads_last
int socket_sendinvalid(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p)
socket_sockthreaddata_t * socket_thread_attach(clsyncsock_t *clsyncsock_p)
static int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_len)
static int socket_overflow_fix(char *buf, char **data_start_p, char **data_end_p)
socket_sockthreaddata_t * socket_thread_new()
int socket_close(clsyncsock_t *clsyncsock_p)
int socket_procclsyncsock(socket_sockthreaddata_t *arg)
int socket_check_bysock(int sock)
clsyncsock_t * socket_new(int clsyncsock_sock)
static char * recv_stps[8]
int socket_reply(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, sockcmd_id_t cmd_id,...)
clsyncsock_t * socket_accept(int sock)
static char * recv_ptrs[8]
#define PARSE_TEXT_DATA_SSCANF(dat_t,...)
int socket_thread_delete(socket_sockthreaddata_t *threaddata_p)
int socket_thread_start(socket_sockthreaddata_t *threaddata_p)
const char *const textmessage_descr[SOCKCMD_MAXID]
pthread_mutex_t socket_thread_mutex
const char *const textmessage_args[SOCKCMD_MAXID]
int socket_send_cb(clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id, clsyncsock_cb_funct_t cb, void *cb_arg,...)
int socket_cleanup(clsyncsock_t *clsyncsock_p)
int socket_recv(clsyncsock_t *clsyncsock, sockcmd_t *sockcmd_p)
int _socket_send(clsyncsock_t *clsyncsock, uint64_t *cmd_num_p, sockcmd_id_t cmd_id, va_list ap)
#define SOCKET_DEFAULT_PROT
int(* clsyncsock_cb_funct_t)(struct socket_sockthreaddata *thread, struct sockcmd *sockcmd_p, void *arg)
@ SOCKCMD_REPLY_NEGOTIATION
@ SOCKCMD_REPLY_UNEXPECTEDEND
@ SOCKCMD_REPLY_UNKNOWNCMD
@ SOCKCMD_REQUEST_NEGOTIATION
@ SOCKCMD_REQUEST_VERSION
@ SOCKCMD_REPLY_INVALIDCMDID
#define sockcmd_dat_einval_t
clsyncsock_t * socket_connect_unix(const char *const socket_path)
enum sockcmd_id sockcmd_id_t
#define SOCKET_DEFAULT_SUBPROT
#define sockcmd_dat_unknowncmd_t
int(* clsyncsock_procfunct_t)(struct socket_sockthreaddata *, sockcmd_t *)
clsyncsock_cb_funct_t callback_funct
clsynccbqueue_t * cbqueue_cache[4 *CLSYNCSOCK_WINDOW+1]
clsynccbqueue_t cbqueue[CLSYNCSOCK_WINDOW+1]
clsyncsock_t * clsyncsock_p
clsyncsock_procfunct_t procfunct
freefunct_t freefunct_arg