clsync
Loading...
Searching...
No Matches
socket.c
Go to the documentation of this file.
1/*
2 clsync - file tree sync utility based on inotify
3
4 Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <stdarg.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <errno.h>
25#include <sys/param.h>
26#include <sys/socket.h>
27#include <sys/un.h> // for "struct sockaddr_un"
28#include <unistd.h>
29
30
31#include "configuration.h"
32#include "error.h"
33#include "malloc.h"
34#include "program.h"
35#include "socket.h"
36
37pthread_mutex_t socket_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
38
42
44
46
48{
49 int i = clsyncsockthreads_last + 1;
50
51 while ( i ) {
52 i--;
53
54 switch ( sockthreaddata[i].state ) {
55 case CLSTATE_DIED:
56 debug ( 3, "Forgeting clsyncsock #%u", i );
57 pthread_join ( sockthreaddata[i].thread, NULL );
59 break;
60
61 default:
62 break;
63 }
64 }
65
66 return 0;
67}
68
69static char *recv_stps[SOCKET_MAX];
70static char *recv_ptrs[SOCKET_MAX];
71
72const char *const textmessage_args[SOCKCMD_MAXID] = {
74 [SOCKCMD_REQUEST_DUMP] = "%s",
75 [SOCKCMD_REQUEST_SET] = "%s\003/ %s\003/",
77 [SOCKCMD_REPLY_ACK] = "%u %lu",
78 [SOCKCMD_REPLY_EINVAL] = "%u %lu",
79 [SOCKCMD_REPLY_VERSION] = "%u %u %s",
80 [SOCKCMD_REPLY_INFO] = "%s\003/ %s\003/ %x %x",
81 [SOCKCMD_REPLY_UNKNOWNCMD] = "%u %lu",
83 [SOCKCMD_REPLY_EEXIST] = "%s\003/",
84 [SOCKCMD_REPLY_EPERM] = "%s\003/",
85 [SOCKCMD_REPLY_ECUSTOM] = "%s\003/ %s\003/ %u %s\003/",
86};
87
88const char *const textmessage_descr[SOCKCMD_MAXID] = {
89 [SOCKCMD_REQUEST_NEGOTIATION] = "Protocol version is %u.",
90 [SOCKCMD_REPLY_NEGOTIATION] = "Protocol version is %u.",
91 [SOCKCMD_REPLY_ACK] = "Acknowledged command: id == %u; num == %lu.",
92 [SOCKCMD_REPLY_EINVAL] = "Rejected command: id == %u; num == %lu. Invalid arguments: %s.",
93 [SOCKCMD_REPLY_LOGIN] = "Enter your login and password, please.",
94 [SOCKCMD_REPLY_UNEXPECTEDEND] = "Need to go, sorry. :)",
95 [SOCKCMD_REPLY_DIE] = "Okay :(",
96 [SOCKCMD_REPLY_BYE] = "Bye.",
97 [SOCKCMD_REPLY_VERSION] = "clsync v%u.%u%s",
98 [SOCKCMD_REPLY_INFO] = "config_block == \"%s\"; label == \"%s\"; flags == %x; flags_set == %x.",
99 [SOCKCMD_REPLY_SET] = "Set",
100 [SOCKCMD_REPLY_DUMP] = "Ready",
101 [SOCKCMD_REPLY_UNKNOWNCMD] = "Unknown command.",
102 [SOCKCMD_REPLY_INVALIDCMDID] = "Invalid command id. Required: 0 <= cmd_id < 1000.",
103 [SOCKCMD_REPLY_EEXIST] = "File exists: \"%s\".",
104 [SOCKCMD_REPLY_EPERM] = "Permission denied: \"%s\".",
105 [SOCKCMD_REPLY_ECUSTOM] = "%s(%s): Error #%u: \"%s\".",
106};
107
108int socket_check_bysock ( int sock )
109{
110 int error_code, ret;
111 socklen_t error_code_len = sizeof ( error_code );
112
113 if ( ( ret = getsockopt ( sock, SOL_SOCKET, SO_ERROR, &error_code, &error_code_len ) ) ) {
114 return errno;
115 }
116
117 if ( error_code ) {
118 errno = error_code;
119 return error_code;
120 }
121
122 return 0;
123}
124
125static inline int socket_check ( clsyncsock_t *clsyncsock_p )
126{
127 return socket_check_bysock ( clsyncsock_p->sock );
128}
129
130clsyncsock_t *socket_new ( int clsyncsock_sock )
131{
132 clsyncsock_t *clsyncsock_p = xmalloc ( sizeof ( *clsyncsock_p ) );
133 debug ( 2, "sock == %i.", clsyncsock_sock );
134 clsyncsock_p->sock = clsyncsock_sock;
135 clsyncsock_p->prot = SOCKET_DEFAULT_PROT;
136 clsyncsock_p->subprot = SOCKET_DEFAULT_SUBPROT;
137 return clsyncsock_p;
138}
139
140int socket_cleanup ( clsyncsock_t *clsyncsock_p )
141{
142 int clsyncsock_sock = clsyncsock_p->sock;
143 debug ( 2, "sock == %i.", clsyncsock_sock );
144 recv_ptrs[clsyncsock_sock] = NULL;
145 recv_stps[clsyncsock_sock] = NULL;
146 free ( clsyncsock_p );
147 return 0;
148}
149
150int socket_close ( clsyncsock_t *clsyncsock_p )
151{
152 close ( clsyncsock_p->sock );
153 return socket_cleanup ( clsyncsock_p );
154}
155
157{
158 int thread_id;
159 pthread_mutex_lock ( &socket_thread_mutex );
160 thread_id = threaddata_p->id;
161 socket_close ( threaddata_p->clsyncsock_p );
163
164 if ( clsyncsockthreads_last == thread_id )
165 clsyncsockthreads_last = thread_id - 1;
166
167 clsyncsockthread_busy[thread_id] = 0;
168 threaddata_p->state = CLSTATE_DIED;
169
170 if ( threaddata_p->freefunct_arg != NULL )
171 threaddata_p->freefunct_arg ( threaddata_p->arg );
172
173 pthread_mutex_unlock ( &socket_thread_mutex );
174 return 0;
175}
176
178{
179 // Cleaning up after died connections (getting free space for new connection)
180 socket_gc();
181 // Getting new connection
182 int clsyncsock_sock = accept ( sock, NULL, NULL );
183
184 if ( clsyncsock_sock == -1 ) {
185 error ( "socket_accept(%i): Cannot accept()", sock );
186 return NULL;
187 }
188
189 return socket_new ( clsyncsock_sock );
190}
191
192clsyncsock_t *socket_listen_unix ( const char *const socket_path )
193{
194 // creating a simple unix socket
195 int s;
196 s = socket ( AF_UNIX, SOCK_STREAM, 0 );
197
198 // checking the path
199 // already exists? - unlink
200 if ( !access ( socket_path, F_OK ) )
201 if ( unlink ( socket_path ) ) {
202 error ( "Cannot unlink() \"%s\".",
203 socket_path );
204 close ( s );
205 return NULL;
206 }
207
208 // binding
209 {
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 );
214
215 if ( bind ( s, ( struct sockaddr * ) &addr, sizeof ( addr ) ) ) {
216 error ( "Cannot bind() on address \"%s\".",
217 socket_path );
218 close ( s );
219 return NULL;
220 }
221 }
222
223 // starting to listening
224 if ( listen ( s, SOCKET_BACKLOG ) ) {
225 error ( "Cannot listen() on address \"%s\".",
226 socket_path );
227 close ( s );
228 return NULL;
229 }
230
231 return socket_new ( s );
232}
233
234#ifdef SOCKET_PROVIDER_LIBCLSYNC
235clsyncsock_t *socket_connect_unix ( const char *const socket_path )
236{
237 // creating a simple unix socket
238 int s;
239 s = socket ( AF_UNIX, SOCK_STREAM, 0 );
240
241 if ( s == -1 )
242 return NULL;
243
244 // checking the path
245 if ( access ( socket_path, F_OK ) ) {
246 error ( "Cannot access() to \"%s\".",
247 socket_path );
248 close ( s );
249 return NULL;
250 }
251
252 // connecting
253 {
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 );
258
259 if ( connect ( s, ( struct sockaddr * ) &addr, sizeof ( addr ) ) ) {
260 error ( "Cannot connect() to address \"%s\".",
261 socket_path );
262 close ( s );
263 return NULL;
264 }
265 }
266 return socket_new ( s );
267}
268#endif
269
270int _socket_send ( clsyncsock_t *clsyncsock, uint64_t *cmd_num_p, sockcmd_id_t cmd_id, va_list ap )
271{
272 int ret;
273 # define PREBUF0_SIZE ((SOCKET_BUFSIZ >> 1) - 128)
274 # define PREBUF1_SIZE (SOCKET_BUFSIZ >> 1)
275 char prebuf0[PREBUF0_SIZE], prebuf1[PREBUF1_SIZE], sendbuf[SOCKET_BUFSIZ];
276 ret = 0;
277
278 switch ( clsyncsock->prot ) {
279 case 0:
280 switch ( clsyncsock->subprot ) {
281 case SUBPROT0_TEXT: {
282 va_list ap_copy;
283 debug ( 3, "%p %p %p", prebuf0, textmessage_args[cmd_id], ap_copy );
284
285 if ( textmessage_args[cmd_id] ) {
286 va_copy ( ap_copy, ap );
287 vsnprintf ( prebuf0, PREBUF0_SIZE, textmessage_args[cmd_id], ap_copy );
288 } else
289 *prebuf0 = 0;
290
291 va_copy ( ap_copy, ap );
292 vsnprintf ( prebuf1, PREBUF1_SIZE, textmessage_descr[cmd_id], ap );
293#ifdef PARANOID
294 prebuf0[PREBUF0_SIZE-1] = 0;
295 prebuf1[PREBUF1_SIZE-1] = 0;
296#endif
297 size_t sendlen = snprintf (
298 sendbuf, SOCKET_BUFSIZ,
299 "%lu %u %s :%s\n",
300 ( *cmd_num_p )++,
301 cmd_id, prebuf0, prebuf1
302 );
303#ifdef PARANOID
304 sendbuf[SOCKET_BUFSIZ-1] = 0;
305#endif
306 debug ( 5, "send(): \"%s\"", sendbuf );
307 send ( clsyncsock->sock, sendbuf, sendlen, 0 );
308 break;
309 }
310
311 /* case SUBPROT0_BINARY:
312 break;*/
313 default:
314 error ( "Unknown subprotocol with id %u.", clsyncsock->subprot );
315 ret = EINVAL;
316 goto l_socket_send_end;
317 }
318
319 break;
320
321 default:
322 error ( "Unknown protocol with id %u.", clsyncsock->prot );
323 ret = EINVAL;
324 goto l_socket_send_end;
325 }
326
327l_socket_send_end:
328 return ret;
329}
330
331int socket_reply ( clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, sockcmd_id_t cmd_id, ... )
332{
333 va_list ap;
334 int ret;
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 );
338 va_end ( ap );
339 return ret;
340}
341
342int socket_send ( clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id, ... )
343{
344 va_list ap;
345 int ret;
346 va_start ( ap, cmd_id );
347 ret = _socket_send ( clsyncsock_p, &clsyncsock_p->cmd_num, cmd_id, ap );
348 va_end ( ap );
349 return ret;
350}
351
352int socket_send_cb ( clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id, clsyncsock_cb_funct_t cb, void *cb_arg, ... )
353{
354 if ( clsyncsock_p->cbqueue_len >= CLSYNCSOCK_WINDOW ) {
355 errno = EOVERFLOW;
356 error ( "Callback queue overflowed. Closing the socket." );
357 socket_close ( clsyncsock_p );
358 return errno;
359 }
360
361 {
362 va_list ap;
363 int ret;
364 uint64_t cmd_num = clsyncsock_p->cmd_num;
365 va_start ( ap, cb_arg );
366 ret = _socket_send ( clsyncsock_p, &clsyncsock_p->cmd_num, cmd_id, ap );
367 va_end ( ap );
368
369 if ( !ret ) {
370 clsynccbqueue_t *cbq = &clsyncsock_p->cbqueue[clsyncsock_p->cbqueue_len];
371 int id;
372 cbq->cmd_num = cmd_num;
373 cbq->callback_funct = cb;
374 cbq->callback_arg = cb_arg;
375 id = cmd_num % ( 2 * CLSYNCSOCK_WINDOW );
376
377 while ( clsyncsock_p->cbqueue_cache[id] != NULL ) id++;
378
379 clsyncsock_p->cbqueue_cache[id] = cbq;
380 clsyncsock_p->cbqueue_len++;
381 }
382
383 return ret;
384 }
385}
386
387static inline int socket_overflow_fix ( char *buf, char **data_start_p, char **data_end_p )
388{
389 debug ( 3, "buf==%p; data_start==%p; data_end==%p", buf, *data_start_p, *data_end_p );
390
391 if ( buf == *data_start_p )
392 return 0;
393
394 size_t ptr_diff = *data_start_p - buf;
395
396 if ( *data_start_p != *data_end_p ) {
397 *data_start_p = buf;
398 *data_end_p = buf;
399 return ptr_diff;
400 }
401
402 size_t data_length = *data_end_p - *data_start_p;
403 memmove ( buf, *data_start_p, data_length );
404 *data_start_p = buf;
405 *data_end_p = &buf[data_length];
406 return ptr_diff;
407}
408
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)\
413 return EINVAL;\
414 }
415
416static inline int parse_text_data ( sockcmd_t *sockcmd_p, char *args, size_t args_len )
417{
418 debug ( 6, "(%p, %p, %u)", sockcmd_p, args, args_len );
419
420 if ( !args_len )
421 return 0;
422
423 int min_args = 0;
424 const char *ptr = ( const char * ) textmessage_args[sockcmd_p->cmd_id];
425
426 if ( ptr != NULL ) {
427 while ( *ptr ) {
428 if ( *ptr == '%' ) {
429 if ( ptr[1] == '%' )
430 ptr++;
431 else
432 min_args++;
433 }
434
435 ptr++;
436 }
437 }
438
439 switch ( sockcmd_p->cmd_id ) {
443 break;
444
447 break;
448
450 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_set_t, &d->key, &d->value );
451 break;
452
454 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_ack_t, &d->cmd_id, &d->cmd_num );
455 break;
456
458 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_einval_t, &d->cmd_id, &d->cmd_num );
459 break;
460
462 if ( args_len > sizeof ( 1 << 8 ) )
463 args[args_len = 1 << 8] = 0;
464
465 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_version_t, &d->major, &d->minor, &d->revision );
466 break;
467
469 if ( args_len > sizeof ( 1 << 8 ) )
470 args[args_len = 1 << 8] = 0;
471
472 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_info_t, &d->config_block, &d->label, &d->flags, &d->flags_set );
473 break;
474
476 PARSE_TEXT_DATA_SSCANF ( sockcmd_dat_unknowncmd_t, &d->cmd_id, &d->cmd_num );
477 break;
478
481 break;
482
485 break;
486
489 break;
490
491 default:
492 sockcmd_p->data = xmalloc ( args_len + 1 );
493 memcpy ( sockcmd_p->data, args, args_len );
494 ( ( char * ) sockcmd_p->data ) [args_len] = 0;
495 break;
496 }
497
498 return 0;
499}
500
502{
503 static char bufs[SOCKET_MAX][SOCKET_BUFSIZ];
504 char *buf, *ptr, *start, *end;
505 int clsyncsock_sock;
506 size_t filled_length, rest_length, filled_length_new;
507 ssize_t recv_length;
508 errno = 0;
509 clsyncsock_sock = clsyncsock->sock;
510 buf = bufs[clsyncsock_sock];
511 start = recv_stps[clsyncsock_sock];
512 start = ( start == NULL ? buf : start );
513 ptr = recv_ptrs[clsyncsock_sock];
514 ptr = ( ptr == NULL ? buf : ptr );
515 debug ( 3, "buf==%p; start==%p; ptr==%p", buf, start, ptr );
516
517 while ( 1 ) {
518 filled_length = ptr - buf;
519 rest_length = SOCKET_BUFSIZ - filled_length - 16;
520
521 if ( rest_length <= 0 ) {
522 if ( !socket_overflow_fix ( buf, &start, &ptr ) ) {
523 debug ( 1, "Got too big message. Ignoring." );
524 ptr = buf;
525 }
526
527 continue;
528 }
529
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 );
533
534 if ( recv_length == 0 )
535 return ECONNRESET;
536
537 if ( recv_length < 0 )
538 return errno;
539
540 switch ( clsyncsock->prot ) {
541 case 0: {
542 // Checking if binary
543 uint16_t cmd_id_binary = * ( uint16_t * ) buf;
545 cmd_id_binary == SOCKCMD_REQUEST_NEGOTIATION ||
546 cmd_id_binary == SOCKCMD_REPLY_NEGOTIATION
547 )
549
550 // Processing
551 switch ( clsyncsock->subprot ) {
552 case SUBPROT0_TEXT:
553 if ( ( end = strchr ( ptr, '\n' ) ) != NULL ) {
554 if ( sscanf ( start, "%lu %u", &sockcmd_p->cmd_num, ( unsigned int * ) &sockcmd_p->cmd_id ) != 2 ) {
555 *end = 0;
556 error ( "It's expected to parse \"%%lu %%u\" from \"%s\"", start );
557 *end = '\n';
558 return errno = ENOMSG;
559 }
560
561 char *str_args = start;
562
563 // Skipping the first number
564 while ( *str_args >= '0' && *str_args <= '9' ) str_args++;
565
566 // Skipping the space
567 str_args++;
568
569 // Skipping the second number
570 while ( *str_args >= '0' && *str_args <= '9' ) str_args++;
571
572 // Skipping the space
573 str_args++;
574
575 // Parsing the arguments
576 if ( end > str_args )
577 parse_text_data ( sockcmd_p, str_args, end - str_args );
578
579 // TODO Process message here
580 goto l_socket_recv_end;
581 }
582
583 break;
584
585 default:
586 return errno = ENOPROTOOPT;
587 }
588
589 break;
590 }
591
592 default:
593 return errno = ENOPROTOOPT;
594 }
595 }
596
597l_socket_recv_end:
598 // ----------------------------------
599 // buf ptr end filled
600 // cut: ---------------
601 // start ptr
602 // new new
603 start = &end[1];
604 ptr = &buf[filled_length_new];
605
606 // No data buffered. Reset "start" and "ptr".
607
608 if ( start == ptr ) {
609 start = buf;
610 ptr = buf;
611 }
612
613 // Remembering the values
614 recv_stps[clsyncsock_sock] = start;
615 recv_ptrs[clsyncsock_sock] = 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",
617 sockcmd_p->cmd_num, sockcmd_p->cmd_id, buf, ptr, end, &buf[filled_length_new], &buf[SOCKET_BUFSIZ] );
618 return 0;
619}
620
621int socket_sendinvalid ( clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p )
622{
623 if ( sockcmd_p->cmd_id >= 1000 )
624 return socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_INVALIDCMDID, sockcmd_p->cmd_num );
625 else
626 return socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_UNKNOWNCMD, sockcmd_p->cmd_id, sockcmd_p->cmd_num );
627}
628
630{
631 char _sockcmd_buf[SOCKET_BUFSIZ] = {0};
632 sockcmd_t *sockcmd_p = ( sockcmd_t * ) _sockcmd_buf;
633 clsyncsock_t *clsyncsock_p = arg->clsyncsock_p;
634 clsyncsock_procfunct_t procfunct = arg->procfunct;
635 //sockprocflags_t flags = arg->flags;
636 enum auth_flags {
637 AUTHFLAG_ENTERED_LOGIN = 0x01,
638 };
639 typedef enum auth_flags auth_flags_t;
640 auth_flags_t auth_flags = 0;
641 debug ( 3, "Started new thread for new connection." );
643 socket_send ( clsyncsock_p, SOCKCMD_REQUEST_NEGOTIATION, clsyncsock_p->prot, clsyncsock_p->subprot );
644
645 while ( ( arg->running && *arg->running ) && ( arg->state == CLSTATE_AUTH || arg->state == CLSTATE_MAIN ) ) {
646 debug ( 3, "Iteration." );
647 // Receiving message
648 int ret;
649
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.",
652 arg->clsyncsock_p->sock );
653 break;
654 }
655
656 // Checking for a callback for this answer
657 {
658 uint64_t cmd_num = sockcmd_p->cmd_num;
659 int i;
660 i = cmd_num % ( 2 * CLSYNCSOCK_WINDOW );
661
662 while ( clsyncsock_p->cbqueue_cache[i] != NULL ) {
663 if ( clsyncsock_p->cbqueue_cache[i]->cmd_num == cmd_num ) { // Found!
664 clsynccbqueue_t *cbq;
665 cbq = clsyncsock_p->cbqueue_cache[i];
666 // Calling the callback function
667 cbq->callback_funct ( arg, sockcmd_p, cbq->callback_arg );
668 // Removing from queue
669 memcpy ( cbq, &clsyncsock_p->cbqueue[--clsyncsock_p->cbqueue_len], sizeof ( *cbq ) );
670 clsyncsock_p->cbqueue_cache[i] = NULL;
671 }
672
673 i++;
674 }
675 }
676
677 // Processing the message
678 if ( procfunct ( arg, sockcmd_p ) )
679 switch ( sockcmd_p->cmd_id ) {
683
684 switch ( data->prot ) {
685 case 0:
686 switch ( data->subprot ) {
687 case SUBPROT0_TEXT:
688 case SUBPROT0_BINARY:
689 clsyncsock_p->subprot = data->subprot;
690
691 if ( sockcmd_p->cmd_id == SOCKCMD_REQUEST_NEGOTIATION )
692 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_NEGOTIATION, data->prot, data->subprot );
693 else {
694 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_ACK, sockcmd_p->cmd_id, sockcmd_p->cmd_num );
695 debug ( 1, "Negotiated proto: %u %u", data->prot, data->subprot );
696 }
697
698 break;
699
700 default:
701 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_EINVAL, sockcmd_p->cmd_id, sockcmd_p->cmd_num, "Incorrect subprotocol id" );
702 }
703
704 break;
705
706 default:
707 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_EINVAL, sockcmd_p->cmd_id, sockcmd_p->cmd_num, "Incorrect protocol id" );
708 }
709
710 break;
711 }
712
714 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_VERSION, VERSION_MAJ, VERSION_MIN, REVISION );
715 break;
716 }
717
719 socket_reply ( clsyncsock_p, sockcmd_p, SOCKCMD_REPLY_BYE );
720 arg->state = CLSTATE_DYING;
721 break;
722 }
723
724 default:
725 socket_sendinvalid ( clsyncsock_p, sockcmd_p );
726 break;
727 }
728
729 if ( sockcmd_p->data != NULL ) {
730 free ( sockcmd_p->data );
731 sockcmd_p->data = NULL;
732 }
733
734 // Check if the socket is still alive
735 if ( socket_check ( clsyncsock_p ) ) {
736 debug ( 1, "clsyncsock socket error: %s", strerror ( errno ) );
737 break;
738 }
739
740 // Sending prompt
741 switch ( arg->state ) {
742 case CLSTATE_AUTH:
743 if ( ! ( auth_flags & AUTHFLAG_ENTERED_LOGIN ) )
744 socket_send ( clsyncsock_p, SOCKCMD_REQUEST_LOGIN );
745
746 break;
747
748 default:
749 break;
750 }
751 }
752
753 debug ( 3, "Ending a connection thread." );
754 socket_thread_delete ( arg );
755 return 0;
756}
757
759{
760 pthread_mutex_lock ( &socket_thread_mutex );
762
764 error ( "Warning: socket_thread_new(): Too many connection threads." );
765 errno = EUSERS;
766 pthread_mutex_unlock ( &socket_thread_mutex );
767 return NULL;
768 }
769
770 threaddata_p->id = clsyncsockthreads_num;
772
773 // TODO: SECURITY: Possible DoS-attack on huge "SOCKET_MAX" value. Fix it.
775
776#ifdef PARANOID
777 // Processing the events: checking if previous check were been made right
778
779 if ( threaddata_p->state != CLSTATE_NONE ) {
780 // This's not supposed to be
781 error ( "Internal-Error: socket_newconnarg(): connproc_arg->state != CLSTATE_NONE" );
782 pthread_mutex_unlock ( &socket_thread_mutex );
783 errno = EILSEQ;
784 return NULL;
785 }
786
787#endif
788 // Processing the events: creating a thread for new connection
789 debug ( 3, "clsyncsockthreads_count == %u;\tclsyncsockthreads_last == %u;\tclsyncsockthreads_num == %u",
793 pthread_mutex_unlock ( &socket_thread_mutex );
794 return threaddata_p;
795}
796
798{
800
801 if ( threaddata_p == NULL )
802 return NULL;
803
804 threaddata_p->clsyncsock_p = clsyncsock_p;
805 return threaddata_p;
806}
807
809{
810 if ( pthread_create ( &threaddata_p->thread, NULL, ( void * ( * ) ( void * ) ) socket_procclsyncsock, threaddata_p ) ) {
811 error ( "Cannot create a thread for connection" );
812 return errno;
813 }
814
815 return 0;
816}
817
819{
820 return 0;
821}
822
824{
825 return 0;
826}
827
828
#define SOCKET_BACKLOG
#define CLSYNCSOCK_WINDOW
#define error(...)
Definition error.h:36
#define debug(debug_level,...)
Definition error.h:50
#define VERSION_MIN
Definition program.h:23
#define VERSION_MAJ
Definition program.h:21
int socket_init()
Definition socket.c:818
socket_sockthreaddata_t sockthreaddata[8+1]
Definition socket.c:45
int socket_send(clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id,...)
Definition socket.c:342
clsyncsock_t * socket_listen_unix(const char *const socket_path)
Definition socket.c:192
char clsyncsockthread_busy[8+1]
Definition socket.c:43
int clsyncsockthreads_count
Definition socket.c:40
int clsyncsockthreads_num
Definition socket.c:41
static int socket_check(clsyncsock_t *clsyncsock_p)
Definition socket.c:125
int clsyncsockthreads_last
Definition socket.c:39
int socket_sendinvalid(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p)
Definition socket.c:621
socket_sockthreaddata_t * socket_thread_attach(clsyncsock_t *clsyncsock_p)
Definition socket.c:797
static int parse_text_data(sockcmd_t *sockcmd_p, char *args, size_t args_len)
Definition socket.c:416
#define PREBUF1_SIZE
static int socket_overflow_fix(char *buf, char **data_start_p, char **data_end_p)
Definition socket.c:387
socket_sockthreaddata_t * socket_thread_new()
Definition socket.c:758
int socket_close(clsyncsock_t *clsyncsock_p)
Definition socket.c:150
int socket_gc()
Definition socket.c:47
int socket_procclsyncsock(socket_sockthreaddata_t *arg)
Definition socket.c:629
int socket_check_bysock(int sock)
Definition socket.c:108
int socket_deinit()
Definition socket.c:823
clsyncsock_t * socket_new(int clsyncsock_sock)
Definition socket.c:130
static char * recv_stps[8]
Definition socket.c:69
int socket_reply(clsyncsock_t *clsyncsock_p, sockcmd_t *sockcmd_p, sockcmd_id_t cmd_id,...)
Definition socket.c:331
clsyncsock_t * socket_accept(int sock)
Definition socket.c:177
static char * recv_ptrs[8]
Definition socket.c:70
#define PARSE_TEXT_DATA_SSCANF(dat_t,...)
Definition socket.c:409
int socket_thread_delete(socket_sockthreaddata_t *threaddata_p)
Definition socket.c:156
int socket_thread_start(socket_sockthreaddata_t *threaddata_p)
Definition socket.c:808
const char *const textmessage_descr[SOCKCMD_MAXID]
Definition socket.c:88
pthread_mutex_t socket_thread_mutex
Definition socket.c:37
const char *const textmessage_args[SOCKCMD_MAXID]
Definition socket.c:72
int socket_send_cb(clsyncsock_t *clsyncsock_p, sockcmd_id_t cmd_id, clsyncsock_cb_funct_t cb, void *cb_arg,...)
Definition socket.c:352
int socket_cleanup(clsyncsock_t *clsyncsock_p)
Definition socket.c:140
int socket_recv(clsyncsock_t *clsyncsock, sockcmd_t *sockcmd_p)
Definition socket.c:501
#define PREBUF0_SIZE
int _socket_send(clsyncsock_t *clsyncsock, uint64_t *cmd_num_p, sockcmd_id_t cmd_id, va_list ap)
Definition socket.c:270
@ CLSTATE_DIED
Definition socket.h:96
@ CLSTATE_MAIN
Definition socket.h:94
@ CLSTATE_NONE
Definition socket.h:92
@ CLSTATE_AUTH
Definition socket.h:93
@ CLSTATE_DYING
Definition socket.h:95
@ SUBPROT0_TEXT
Definition socket.h:86
@ SUBPROT0_BINARY
Definition socket.h:87
#define SOCKET_DEFAULT_PROT
Definition socket.h:34
int(* clsyncsock_cb_funct_t)(struct socket_sockthreaddata *thread, struct sockcmd *sockcmd_p, void *arg)
Definition socket.h:56
@ SOCKCMD_REQUEST_QUIT
Definition socket.h:116
@ SOCKCMD_REPLY_EPERM
Definition socket.h:108
@ SOCKCMD_REPLY_NEGOTIATION
Definition socket.h:102
@ SOCKCMD_REPLY_UNEXPECTEDEND
Definition socket.h:124
@ SOCKCMD_REPLY_LOGIN
Definition socket.h:120
@ SOCKCMD_REPLY_VERSION
Definition socket.h:117
@ SOCKCMD_REPLY_INFO
Definition socket.h:118
@ SOCKCMD_REPLY_ECUSTOM
Definition socket.h:109
@ SOCKCMD_REQUEST_SET
Definition socket.h:114
@ SOCKCMD_MAXID
Definition socket.h:125
@ SOCKCMD_REPLY_SET
Definition socket.h:121
@ SOCKCMD_REPLY_UNKNOWNCMD
Definition socket.h:104
@ SOCKCMD_REQUEST_NEGOTIATION
Definition socket.h:101
@ SOCKCMD_REPLY_ACK
Definition socket.h:103
@ SOCKCMD_REPLY_EINVAL
Definition socket.h:106
@ SOCKCMD_REPLY_DUMP
Definition socket.h:119
@ SOCKCMD_REQUEST_VERSION
Definition socket.h:110
@ SOCKCMD_REPLY_DIE
Definition socket.h:122
@ SOCKCMD_REPLY_EEXIST
Definition socket.h:107
@ SOCKCMD_REPLY_INVALIDCMDID
Definition socket.h:105
@ SOCKCMD_REPLY_BYE
Definition socket.h:123
@ SOCKCMD_REQUEST_LOGIN
Definition socket.h:113
@ SOCKCMD_REQUEST_DUMP
Definition socket.h:112
#define sockcmd_dat_einval_t
Definition socket.h:141
clsyncsock_t * socket_connect_unix(const char *const socket_path)
#define SOCKET_MAX
Definition socket.h:50
enum sockcmd_id sockcmd_id_t
Definition socket.h:127
#define SOCKET_DEFAULT_SUBPROT
Definition socket.h:35
#define sockcmd_dat_unknowncmd_t
Definition socket.h:143
@ SOCKAUTH_NULL
Definition socket.h:201
#define SOCKET_BUFSIZ
Definition socket.h:38
int(* clsyncsock_procfunct_t)(struct socket_sockthreaddata *, sockcmd_t *)
Definition socket.h:207
uint64_t cmd_num
Definition socket.h:58
void * callback_arg
Definition socket.h:61
clsyncsock_cb_funct_t callback_funct
Definition socket.h:60
uint64_t cmd_num
Definition socket.h:70
size_t cbqueue_len
Definition socket.h:72
clsynccbqueue_t * cbqueue_cache[4 *CLSYNCSOCK_WINDOW+1]
Definition socket.h:74
uint16_t subprot
Definition socket.h:68
uint16_t prot
Definition socket.h:67
int sock
Definition socket.h:66
clsynccbqueue_t cbqueue[CLSYNCSOCK_WINDOW+1]
Definition socket.h:73
uint16_t cmd_id
Definition socket.h:137
char dir_path[PATH_MAX]
Definition socket.h:166
char file_path[PATH_MAX]
Definition socket.h:171
char descr[BUFSIZ]
Definition socket.h:176
char config_block[1<< 8]
Definition socket.h:158
char key[BUFSIZ]
Definition socket.h:181
uint16_t cmd_id
Definition socket.h:188
uint64_t cmd_num
Definition socket.h:187
void * data
Definition socket.h:190
clsyncsock_t * clsyncsock_p
Definition socket.h:213
clsyncsock_state_t state
Definition socket.h:215
clsyncsock_procfunct_t procfunct
Definition socket.h:211
sockauth_id_t authtype
Definition socket.h:216
freefunct_t freefunct_arg
Definition socket.h:212