mirror of
https://github.com/eddyem/snippets_library.git
synced 2026-03-20 08:40:55 +03:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b5d5396167 | |||
| b20e669d93 | |||
| 56ee64dd78 |
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
set(PROJ usefull_macros)
|
||||
set(MINOR_VERSION "3")
|
||||
set(MINOR_VERSION "4")
|
||||
set(MID_VERSION "3")
|
||||
set(MAJOR_VERSION "0")
|
||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||
@@ -8,7 +8,7 @@ set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||
project(${PROJ} VERSION ${VERSION} LANGUAGES C)
|
||||
|
||||
# default flags
|
||||
set(CMAKE_C_FLAGS "${CFLAGS} -O2")
|
||||
set(CMAKE_C_FLAGS "${CFLAGS} -O2 -pedantic-errors")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -Wextra -Wall -Werror -W")
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
Thu Nov 6 11:25:07 MSK 2025
|
||||
VERSION 0.3.4:
|
||||
add data type:
|
||||
- sl_sock_keyno_t - number of key (like key[keyno] = val) using in sl_sock_hitem_t.data
|
||||
add functions:
|
||||
- sl_sock_keyno_init - init keyno (or use macro SL_SOCK_KEYNO_DEFAUL in assignment)
|
||||
- sl_sock_keyno_check - return -1 if there's no keyno, else return its value
|
||||
New functional listed in examples/clientserver.c introducing key `flags` that allows to work with bit flags as a whole or by bits like flags[1]=1, flags21=0, flags{31} or flags(14)...
|
||||
|
||||
Wed Sep 10 14:19:24 MSK 2025
|
||||
(still version 0.3.3: I forgot to add changelog last commits)
|
||||
- fixed minor bugs and memory leaks
|
||||
|
||||
@@ -122,6 +122,7 @@ static void runclient(sl_sock_t *s){
|
||||
static sl_sock_int_t iflag = {0};
|
||||
static sl_sock_double_t dflag = {0};
|
||||
static sl_sock_string_t sflag = {0};
|
||||
static uint32_t bitflags = 0;
|
||||
|
||||
static sl_sock_hresult_e dtimeh(sl_sock_t _U_ *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){
|
||||
char buf[32];
|
||||
@@ -169,6 +170,7 @@ static void disconnected(sl_sock_t *c){
|
||||
if(c->type == SOCKT_UNIX) LOGMSG("Disconnected client fd=%d", c->fd);
|
||||
else LOGMSG("Disconnected client fd=%d, IP=%s", c->fd, c->IP);
|
||||
}
|
||||
// default (unknown key) handler
|
||||
static sl_sock_hresult_e defhandler(struct sl_sock *s, const char *str){
|
||||
if(!s || !str) return RESULT_FAIL;
|
||||
sl_sock_sendstrmessage(s, "You entered wrong command:\n```\n");
|
||||
@@ -176,6 +178,33 @@ static sl_sock_hresult_e defhandler(struct sl_sock *s, const char *str){
|
||||
sl_sock_sendstrmessage(s, "\n```\nTry \"help\"\n");
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
// if we use this macro, there's no need to run `sl_sock_keyno_init` later
|
||||
static sl_sock_keyno_t kph_number = SL_SOCK_KEYNO_DEFAULT;
|
||||
// handler for key with optional parameter number
|
||||
static sl_sock_hresult_e keyparhandler(struct sl_sock *s, sl_sock_hitem_t *item, const char *req){
|
||||
if(!item->data) return RESULT_FAIL;
|
||||
char buf[1024];
|
||||
int no = sl_sock_keyno_check((sl_sock_keyno_t*)item->data);
|
||||
long long newval = -1;
|
||||
if(req){
|
||||
if(!sl_str2ll(&newval, req) || newval < 0 || newval > 0xffffffff) return RESULT_BADVAL;
|
||||
}
|
||||
printf("no = %d\n", no);
|
||||
if(no < 0){ // flags as a whole
|
||||
if(req) bitflags = (uint32_t)newval;
|
||||
snprintf(buf, 1023, "flags = 0x%08X\n", bitflags);
|
||||
sl_sock_sendstrmessage(s, buf);
|
||||
}else if(no < 32){ // bit access
|
||||
int bitmask = 1 << no;
|
||||
if(req){
|
||||
if(newval) bitflags |= bitmask;
|
||||
else bitflags &= ~bitmask;
|
||||
}
|
||||
snprintf(buf, 1023, "flags[%d] = %d\n", no, bitflags & bitmask ? 1 : 0);
|
||||
sl_sock_sendstrmessage(s, buf);
|
||||
}else return RESULT_BADKEY;
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
|
||||
static sl_sock_hitem_t handlers[] = {
|
||||
{sl_sock_inthandler, "int", "set/get integer flag", (void*)&iflag},
|
||||
@@ -183,6 +212,7 @@ static sl_sock_hitem_t handlers[] = {
|
||||
{sl_sock_strhandler, "str", "set/get string variable", (void*)&sflag},
|
||||
{show, "show", "show current flags @ server console", NULL},
|
||||
{dtimeh, "dtime", "get server's UNIX time for all clients connected", NULL},
|
||||
{keyparhandler, "flags", "set/get bit flags as whole (flags=val) or by bits (flags[bit]=val)", (void*)&kph_number},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -193,10 +223,13 @@ int main(int argc, char **argv){
|
||||
if(!G.node) ERRX("Point node");
|
||||
sl_socktype_e type = (G.isunix) ? SOCKT_UNIX : SOCKT_NET;
|
||||
if(G.isserver){
|
||||
//sl_sock_keyno_init(&kph_number); // don't forget to init first or use macro in initialisation
|
||||
s = sl_sock_run_server(type, G.node, -1, handlers);
|
||||
DBG("Server started");
|
||||
} else {
|
||||
sl_setup_con();
|
||||
s = sl_sock_run_client(type, G.node, -1);
|
||||
DBG("Client started");
|
||||
}
|
||||
if(!s) ERRX("Can't create socket and/or run threads");
|
||||
if(G.isserver){
|
||||
|
||||
Binary file not shown.
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 12:08+0300\n"
|
||||
"POT-Creation-Date: 2026-03-04 09:05+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -77,79 +77,79 @@ msgstr ""
|
||||
msgid "Can't use multiple args with arg_none!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:267
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:268
|
||||
#, c-format
|
||||
msgid "double long arguments: --%s"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:273
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:274
|
||||
#, c-format
|
||||
msgid "double short arguments: -%c"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:343
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:347
|
||||
#, c-format
|
||||
msgid "Need argument with %s type\n"
|
||||
msgstr ""
|
||||
|
||||
#. print only one message
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:435
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:439
|
||||
msgid "sl_showhelp(): option index out of range"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:441
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:445
|
||||
#, c-format
|
||||
msgid "Usage: %s [arguments]\n"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:528
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:535
|
||||
#, c-format
|
||||
msgid "Wrong parameter: %s"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:532
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:539
|
||||
#, c-format
|
||||
msgid "%s: need argument!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:536
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:543
|
||||
#, c-format
|
||||
msgid "Wrong argument \"%s\" of parameter \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:147
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:154
|
||||
msgid "Server disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:385
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:441
|
||||
msgid "Can't start server handlers thread"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:454
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:513
|
||||
msgid "Limit of connections reached"
|
||||
msgstr ""
|
||||
|
||||
#. check for RB overflow
|
||||
#. -1 - buffer empty (can't be), -2 - buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:498
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:499
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:557
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:558
|
||||
#, c-format
|
||||
msgid "Server thread: ring buffer overflow for fd=%d"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:513
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:572
|
||||
#, c-format
|
||||
msgid "Server thread: can't write data to ringbuffer: overflow from fd=%d"
|
||||
msgstr ""
|
||||
|
||||
#. buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:525
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:584
|
||||
#, c-format
|
||||
msgid "Server thread: buffer overflow from fd=%d"
|
||||
msgstr ""
|
||||
|
||||
#. never reached
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:615
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:681
|
||||
#, c-format
|
||||
msgid "Unsupported socket type %d"
|
||||
msgstr ""
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
msgid ""
|
||||
msgstr "Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 12:08+0300\n"
|
||||
"POT-Creation-Date: 2026-03-04 09:01+0300\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -33,7 +33,7 @@ msgstr "sl_conf_showhelp():
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:322
|
||||
#, c-format
|
||||
msgid "Configuration file options (format: key=value):\n"
|
||||
msgstr ""
|
||||
msgstr "ïÐÃÉÉ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÆÁÊÌÁ (ÆÏÒÍÁÔ: ËÌÀÞ=ÚÎÁÞÅÎÉÅ):\n"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:69
|
||||
#, c-format
|
||||
@@ -76,80 +76,80 @@ msgstr "
|
||||
msgid "Can't use multiple args with arg_none!"
|
||||
msgstr "íÁÓÓÉ× ÐÁÒÁÍÅÔÒÏ× ÎÅ ÍÏÖÅÔ ÉÍÅÔØ ÔÉÐ arg_none!"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:267
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:268
|
||||
#, c-format
|
||||
msgid "double long arguments: --%s"
|
||||
msgstr "ÄÕÂÌÉÒÕÀÝÉÊÓÑ ÄÌÉÎÎÙÊ ÐÁÒÁÍÅÔÒ: --%s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:273
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:274
|
||||
#, c-format
|
||||
msgid "double short arguments: -%c"
|
||||
msgstr "ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÏÒÏÔËÉÊ ÐÁÒÁÍÅÔÒ: -%c"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:343
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:347
|
||||
#, c-format
|
||||
msgid "Need argument with %s type\n"
|
||||
msgstr "îÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ Ó ÔÉÐÏÍ %s\n"
|
||||
|
||||
#. print only one message
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:435
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:439
|
||||
msgid "sl_showhelp(): option index out of range"
|
||||
msgstr "sl_showhelp(): ÉÎÄÅËÓ ÏÐÃÉÉ ×ÎÅ ÄÏÐÕÓÔÉÍÏÇÏ ÄÉÁÐÁÚÏÎÁ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:441
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:445
|
||||
#, c-format
|
||||
msgid "Usage: %s [arguments]\n"
|
||||
msgstr "éÓÐÏÌØÚÏ×ÁÎÉÅ: %s [ÁÒÇÕÍÅÎÔÙ]\n"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:528
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:535
|
||||
#, c-format
|
||||
msgid "Wrong parameter: %s"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÐÁÒÁÍÅÔÒ: %s"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:532
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:539
|
||||
#, c-format
|
||||
msgid "%s: need argument!"
|
||||
msgstr "%s: ÎÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ!"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:536
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:543
|
||||
#, c-format
|
||||
msgid "Wrong argument \"%s\" of parameter \"%s\""
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÁÒÇÕÍÅÎÔ \"%s\" ÐÁÒÁÍÅÔÒÁ \"%s\""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:147
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:154
|
||||
msgid "Server disconnected"
|
||||
msgstr "óÅÒ×ÅÒ ÏÔËÌÀÞÅÎ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:385
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:441
|
||||
msgid "Can't start server handlers thread"
|
||||
msgstr "îÅ ÍÏÇÕ ÚÁÐÕÓÔÉÔØ ÐÏÔÏË-ÏÂÒÁÂÏÔÞÉË ÓÅÒ×ÅÒÁ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:454
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:513
|
||||
msgid "Limit of connections reached"
|
||||
msgstr "äÏÓÔÉÇÎÕÔ ÐÒÅÄÅÌ ÓÏÅÄÉÎÅÎÉÊ"
|
||||
|
||||
#. check for RB overflow
|
||||
#. -1 - buffer empty (can't be), -2 - buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:498
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:499
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:557
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:558
|
||||
#, c-format
|
||||
msgid "Server thread: ring buffer overflow for fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÂÕÆÅÒÁ ÏÔ fd=%d"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:513
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:572
|
||||
#, c-format
|
||||
msgid "Server thread: can't write data to ringbuffer: overflow from fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÎÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÄÁÎÎÙÅ × ËÏÌØÃÅ×ÏÍ ÂÕÆÅÒÅ, "
|
||||
"ÐÅÒÅÐÏÌÎÅÎÉÅ ÏÔ fd=%d"
|
||||
|
||||
#. buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:525
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:584
|
||||
#, c-format
|
||||
msgid "Server thread: buffer overflow from fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÂÕÆÅÒÁ ÏÔ fd=%d"
|
||||
|
||||
#. never reached
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:615
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:681
|
||||
#, c-format
|
||||
msgid "Unsupported socket type %d"
|
||||
msgstr "îÅÐÏÄÄÅÒÖÉ×ÁÅÍÙÊ ÔÉÐ ÓÏËÅÔÁ %d"
|
||||
|
||||
109
parseargs.c
109
parseargs.c
@@ -191,6 +191,18 @@ void *get_aptr(void *paptr, sl_argtype_e type){
|
||||
return aptr[i - 1];
|
||||
}
|
||||
|
||||
static int cmpstringp(const void *p1, const void *p2){
|
||||
if(!p1 || !p2) return 0;
|
||||
const char *str1 = * (char * const *) p1, *str2 = * (char * const *) p2;
|
||||
if(!str1 && !str2) return 0;
|
||||
else if(!str1) return 1;
|
||||
else if(!str2) return -1;
|
||||
return strcmp(str1, str2);
|
||||
}
|
||||
static int cmpcharp(const void *p1, const void *p2){
|
||||
return (int)(*(char * const)p1 - *(char *const)p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_parseargs_hf - parse arguments with user help funtion
|
||||
* @param argc - amount of arguments
|
||||
@@ -246,17 +258,6 @@ void sl_parseargs_hf(int *argc, char ***argv, sl_option_t *options, void (*helpf
|
||||
}
|
||||
}
|
||||
// sort all lists & check for repeating
|
||||
int cmpstringp(const void *p1, const void *p2){
|
||||
if(!p1 || !p2) return 0;
|
||||
const char *str1 = * (char * const *) p1, *str2 = * (char * const *) p2;
|
||||
if(!str1 && !str2) return 0;
|
||||
else if(!str1) return 1;
|
||||
else if(!str2) return -1;
|
||||
return strcmp(str1, str2);
|
||||
}
|
||||
int cmpcharp(const void *p1, const void *p2){
|
||||
return (int)(*(char * const)p1 - *(char *const)p2);
|
||||
}
|
||||
qsort(longlist, optsize, sizeof(char *), cmpstringp);
|
||||
qsort(shortlist,optsize, sizeof(char), cmpcharp);
|
||||
char *prevl = longlist[0], prevshrt = shortlist[0];
|
||||
@@ -336,7 +337,10 @@ void sl_parseargs_hf(int *argc, char ***argv, sl_option_t *options, void (*helpf
|
||||
type = "string";
|
||||
break;
|
||||
case arg_function:
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
result = ((sl_argfn_t)aptr)(optarg);
|
||||
#pragma GCC diagnostic pop
|
||||
break;
|
||||
}
|
||||
if(!result){
|
||||
@@ -460,6 +464,49 @@ void sl_showhelp(int oindex, sl_option_t *options){
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static int findsubopt(char *par, sl_suboption_t *so){
|
||||
int idx = 0;
|
||||
if(!par) return -1;
|
||||
while(so[idx].name){
|
||||
if(strcasecmp(par, so[idx].name) == 0) return idx;
|
||||
++idx;
|
||||
}
|
||||
return -1; // badarg
|
||||
}
|
||||
static int opt_setarg(sl_suboption_t *so, int idx, char *val){
|
||||
sl_suboption_t *soptr = &so[idx];
|
||||
int result = FALSE;
|
||||
void *aptr = soptr->argptr;
|
||||
switch(soptr->type){
|
||||
default:
|
||||
case arg_none:
|
||||
if(soptr->argptr) *((int*)aptr) += 1; // increment value
|
||||
result = TRUE;
|
||||
break;
|
||||
case arg_int:
|
||||
result = myatoll(aptr, val, arg_int);
|
||||
break;
|
||||
case arg_longlong:
|
||||
result = myatoll(aptr, val, arg_longlong);
|
||||
break;
|
||||
case arg_double:
|
||||
result = myatod(aptr, val, arg_double);
|
||||
break;
|
||||
case arg_float:
|
||||
result = myatod(aptr, val, arg_float);
|
||||
break;
|
||||
case arg_string:
|
||||
result = (*((void**)aptr) = (void*)strdup(val)) != NULL;
|
||||
break;
|
||||
case arg_function:
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
result = ((sl_argfn_t)aptr)(val);
|
||||
#pragma GCC diagnostic pop
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* @brief sl_get_suboption - get suboptions from parameter string
|
||||
* @param str - parameter string
|
||||
@@ -467,46 +514,6 @@ void sl_showhelp(int oindex, sl_option_t *options){
|
||||
* @return TRUE if all OK
|
||||
*/
|
||||
int sl_get_suboption(char *str, sl_suboption_t *opt){
|
||||
int findsubopt(char *par, sl_suboption_t *so){
|
||||
int idx = 0;
|
||||
if(!par) return -1;
|
||||
while(so[idx].name){
|
||||
if(strcasecmp(par, so[idx].name) == 0) return idx;
|
||||
++idx;
|
||||
}
|
||||
return -1; // badarg
|
||||
}
|
||||
int opt_setarg(sl_suboption_t *so, int idx, char *val){
|
||||
sl_suboption_t *soptr = &so[idx];
|
||||
int result = FALSE;
|
||||
void *aptr = soptr->argptr;
|
||||
switch(soptr->type){
|
||||
default:
|
||||
case arg_none:
|
||||
if(soptr->argptr) *((int*)aptr) += 1; // increment value
|
||||
result = TRUE;
|
||||
break;
|
||||
case arg_int:
|
||||
result = myatoll(aptr, val, arg_int);
|
||||
break;
|
||||
case arg_longlong:
|
||||
result = myatoll(aptr, val, arg_longlong);
|
||||
break;
|
||||
case arg_double:
|
||||
result = myatod(aptr, val, arg_double);
|
||||
break;
|
||||
case arg_float:
|
||||
result = myatod(aptr, val, arg_float);
|
||||
break;
|
||||
case arg_string:
|
||||
result = (*((void**)aptr) = (void*)strdup(val)) != NULL;
|
||||
break;
|
||||
case arg_function:
|
||||
result = ((sl_argfn_t)aptr)(val);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
char *tok;
|
||||
int ret = FALSE;
|
||||
char *tmpbuf;
|
||||
|
||||
128
socket.c
128
socket.c
@@ -16,8 +16,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
@@ -25,7 +26,6 @@
|
||||
#include <strings.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/un.h> // unix socket
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "usefull_macros.h"
|
||||
@@ -81,17 +81,24 @@ const char *sl_sock_hresult2str(sl_sock_hresult_e r){
|
||||
}
|
||||
|
||||
// convert UNIX socket name for unaddr; result should be free'd
|
||||
static char *convunsname(const char *path){
|
||||
char *apath = MALLOC(char, 106);
|
||||
static char *convunsname(const char *path, socklen_t *nbytes){
|
||||
char *apath = MALLOC(char, UNIX_SOCK_PATH_MAX);
|
||||
socklen_t len = 0;
|
||||
if(*path == 0){
|
||||
DBG("convert name starting from 0");
|
||||
apath[0] = 0;
|
||||
strncpy(apath+1, path+1, 104);
|
||||
strncpy(apath+1, path+1, UNIX_SOCK_PATH_MAX-2);
|
||||
len = 1 + strlen(path+1);
|
||||
}else if(strncmp("\\0", path, 2) == 0){
|
||||
DBG("convert name starting from \\0");
|
||||
apath[0] = 0;
|
||||
strncpy(apath+1, path+2, 104);
|
||||
}else strncpy(apath, path, 105);
|
||||
strncpy(apath+1, path+2, UNIX_SOCK_PATH_MAX-2);
|
||||
len = 1 + strlen(path+2);
|
||||
}else{
|
||||
strncpy(apath, path, UNIX_SOCK_PATH_MAX-1);
|
||||
len = strlen(path);
|
||||
}
|
||||
if(nbytes) *nbytes = len + sizeof(sa_family_t); // amount of bytes for `bind()` (parameter `len`)
|
||||
return apath;
|
||||
}
|
||||
|
||||
@@ -345,10 +352,59 @@ static sl_sock_hresult_e msgparser(sl_sock_t *client, char *str){
|
||||
sl_sock_sendbyte(client, '\n');
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
// check for strict params like `key=val`
|
||||
for(sl_sock_hitem_t *h = client->handlers; h->handler; ++h){
|
||||
if(strcmp(h->key, key)) continue;
|
||||
if(h->data){
|
||||
sl_sock_keyno_t *kn = (sl_sock_keyno_t*)h->data;
|
||||
if(-1 == isinf(kn->magick)) kn->n = -1; // no value number
|
||||
}
|
||||
return h->handler(client, h, valptr);
|
||||
}
|
||||
// now check for optional key's number like key0=val, key[1]=val, key(2)=val or key{3}=val
|
||||
int keylen = strlen(key);
|
||||
char *numstart = NULL;
|
||||
const char *bra = "([{", *ket = ")]}";
|
||||
char *found = strchr((char*)ket, key[keylen - 1]);
|
||||
DBG("found=%s", found);
|
||||
if(found){
|
||||
char *keyend = strchr(key, bra[found - ket]); // find starting bracket
|
||||
DBG("keyend=%s", keyend);
|
||||
if(keyend){
|
||||
numstart = keyend + 1;
|
||||
keylen = keyend - key;
|
||||
}
|
||||
}else{ // maybe this is key123=val ?
|
||||
numstart = &key[keylen-1];
|
||||
while(numstart > key && isdigit(*numstart)) --numstart;
|
||||
if(numstart == &key[keylen-1]) numstart = NULL;
|
||||
else{
|
||||
keylen = (++numstart) - key;
|
||||
DBG("numstart=%s", numstart);
|
||||
}
|
||||
}
|
||||
if(numstart){
|
||||
char *eptr;
|
||||
long long LL = strtoll(numstart, &eptr, 0);
|
||||
DBG("LL=%lld, len=%d", LL, keylen);
|
||||
if(eptr != numstart && LL >= 0 && LL <= INT_MAX){
|
||||
int parno = (int)LL;
|
||||
for(sl_sock_hitem_t *h = client->handlers; h->handler; ++h){
|
||||
if(strncmp(h->key, key, keylen)) continue; // now search only in first `keylen` bytes
|
||||
DBG("found %s", h->key);
|
||||
if(h->data){
|
||||
sl_sock_keyno_t *kn = (sl_sock_keyno_t*)h->data;
|
||||
if(-1 == isinf(kn->magick)){
|
||||
kn->n = parno;
|
||||
DBG("run handler, parno=%d", parno);
|
||||
return h->handler(client, h, valptr);
|
||||
}
|
||||
}
|
||||
DBG("NO data");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(client->defmsg_handler) return client->defmsg_handler(client, str);
|
||||
return RESULT_BADKEY;
|
||||
}
|
||||
@@ -413,7 +469,9 @@ static void *serverthread(void _U_ *d){
|
||||
// ZERO - listening server socket
|
||||
poll_set[0].fd = sockfd;
|
||||
poll_set[0].events = POLLIN;
|
||||
// disconnect client
|
||||
// disconnect client (no way to make this function non-nested)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
void disconnect_(sl_sock_t *c, int N){
|
||||
DBG("Disconnect client \"%s\" (fd=%d)", c->IP, c->fd);
|
||||
if(s->disconnect_handler) s->disconnect_handler(c);
|
||||
@@ -440,6 +498,7 @@ static void *serverthread(void _U_ *d){
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
--nfd;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
// allocate buffer with size not less than RB size
|
||||
size_t bufsize = s->buffer->length; // as RB should be 1 byte less, this is OK
|
||||
uint8_t *buf = MALLOC(uint8_t, bufsize);
|
||||
@@ -588,28 +647,35 @@ errex:
|
||||
*/
|
||||
static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hitem_t *handlers, int bufsiz, int isserver){
|
||||
if(!path || type >= SOCKT_AMOUNT) return NULL;
|
||||
printf("OPen\n");
|
||||
FNAME();
|
||||
if(bufsiz < 256) bufsiz = 256;
|
||||
int sock = -1;
|
||||
struct addrinfo ai = {0}, *res = &ai;
|
||||
struct sockaddr_un unaddr = {0};
|
||||
char *str = NULL;
|
||||
ai.ai_socktype = SOCK_STREAM;
|
||||
switch(type){
|
||||
case SOCKT_UNIX:
|
||||
str = convunsname(path);
|
||||
DBG("SOCKT_UNIX");
|
||||
{
|
||||
char *str = convunsname(path, &ai.ai_addrlen);
|
||||
DBG("path+1: %s", str+1);
|
||||
if(!str) return NULL;
|
||||
unaddr.sun_family = AF_UNIX;
|
||||
ai.ai_addr = (struct sockaddr*) &unaddr;
|
||||
ai.ai_addrlen = sizeof(unaddr);
|
||||
memcpy(unaddr.sun_path, str, 106);
|
||||
memcpy(unaddr.sun_path, str, UNIX_SOCK_PATH_MAX);
|
||||
FREE(str); // don't forget!
|
||||
ai.ai_family = AF_UNIX;
|
||||
//ai.ai_socktype = SOCK_SEQPACKET;
|
||||
}
|
||||
break;
|
||||
case SOCKT_NET:
|
||||
case SOCKT_NETLOCAL:
|
||||
//ai.ai_socktype = SOCK_DGRAM; // = SOCK_STREAM;
|
||||
ai.ai_family = AF_INET;
|
||||
if(isserver) ai.ai_flags = AI_PASSIVE;
|
||||
if(isserver){
|
||||
ai.ai_flags = AI_PASSIVE;
|
||||
//ai.ai_family = AF_INET;
|
||||
}// else
|
||||
ai.ai_family = AF_UNSPEC; // not AF_INET for client as there maybe problems with IPv6
|
||||
break;
|
||||
default: // never reached
|
||||
WARNX(_("Unsupported socket type %d"), type);
|
||||
@@ -626,9 +692,9 @@ static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hit
|
||||
sl_sock_delete(&s);
|
||||
return NULL;
|
||||
}else{ // fill node/service
|
||||
if(type == SOCKT_UNIX) s->node = strdup(str); // str now is converted path
|
||||
if(type == SOCKT_UNIX) s->node = strdup(path); // str now is path copy
|
||||
else{
|
||||
char *delim = strchr(path, ':');
|
||||
char *delim = strchr((char*)path, ':');
|
||||
if(!delim) s->service = strdup(path); // only port
|
||||
else{
|
||||
if(delim == path) s->service = strdup(path+1);
|
||||
@@ -667,7 +733,7 @@ static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hit
|
||||
}
|
||||
for(struct addrinfo *p = res; p; p = p->ai_next){
|
||||
if((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) continue;
|
||||
DBG("Try proto %d, type %d", p->ai_protocol, p->ai_socktype);
|
||||
DBG("Try proto %d, type %d, socktype %d", p->ai_protocol, p->ai_socktype, p->ai_socktype);
|
||||
if(isserver){
|
||||
int reuseaddr = 1;
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int)) == -1){
|
||||
@@ -688,10 +754,12 @@ static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hit
|
||||
if(connect(sock, p->ai_addr, p->ai_addrlen) == -1){
|
||||
WARN("connect()");
|
||||
close(sock); sock = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(type != SOCKT_UNIX) freeaddrinfo(res); // don't forget to free memory allocated with getaddrinfo
|
||||
if(sock < 0) sl_sock_delete(&s);
|
||||
else{
|
||||
s->fd = sock;
|
||||
@@ -826,6 +894,7 @@ ssize_t sl_sock_readline(sl_sock_t *sock, char *str, size_t len){
|
||||
sl_sock_hresult_e sl_sock_inthandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str){
|
||||
char buf[128];
|
||||
sl_sock_int_t *i = (sl_sock_int_t *)hitem->data;
|
||||
if(!i) return RESULT_FAIL;
|
||||
if(!str){ // getter
|
||||
snprintf(buf, 127, "%s=%" PRId64 "\n", hitem->key, i->val);
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
@@ -841,6 +910,7 @@ sl_sock_hresult_e sl_sock_inthandler(sl_sock_t *client, sl_sock_hitem_t *hitem,
|
||||
sl_sock_hresult_e sl_sock_dblhandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str){
|
||||
char buf[128];
|
||||
sl_sock_double_t *d = (sl_sock_double_t *)hitem->data;
|
||||
if(!d) return RESULT_FAIL;
|
||||
if(!str){ // getter
|
||||
snprintf(buf, 127, "%s=%g\n", hitem->key, d->val);
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
@@ -855,6 +925,7 @@ sl_sock_hresult_e sl_sock_dblhandler(sl_sock_t *client, sl_sock_hitem_t *hitem,
|
||||
sl_sock_hresult_e sl_sock_strhandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str){
|
||||
char buf[SL_VAL_LEN + SL_KEY_LEN + 3];
|
||||
sl_sock_string_t *s = (sl_sock_string_t*) hitem->data;
|
||||
if(!s) return RESULT_FAIL;
|
||||
if(!str){ // getter
|
||||
snprintf(buf, SL_VAL_LEN + SL_KEY_LEN + 2, "%s=%s\n", hitem->key, s->val);
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
@@ -868,3 +939,24 @@ sl_sock_hresult_e sl_sock_strhandler(sl_sock_t *client, sl_sock_hitem_t *hitem,
|
||||
s->val[l] = 0;
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sl_sock_keyno_init - init k->magick and k-> to default values
|
||||
* @param k - key's number value
|
||||
*/
|
||||
void sl_sock_keyno_init(sl_sock_keyno_t* k){
|
||||
if(!k) return;
|
||||
k->magick = -INFINITY;
|
||||
k->n = -1;
|
||||
}
|
||||
/**
|
||||
* @brief sl_sock_keyno_check - check if this is a really `sl_sock_keyno_t`
|
||||
* @param k - pointer to check
|
||||
* @return k.n or -1 if failed
|
||||
*/
|
||||
int sl_sock_keyno_check(sl_sock_keyno_t* k){
|
||||
DBG("magick=%g (%d)", k->magick, isinf(k->magick));
|
||||
if(!k || -1 != isinf(k->magick)) return -1;
|
||||
DBG("k->n=%d", k->n);
|
||||
return k->n;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <unistd.h> // pid_t
|
||||
// just for different purposes
|
||||
#include <limits.h>
|
||||
#include <math.h> // inf/isinf
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined GETTEXT
|
||||
@@ -417,6 +418,8 @@ size_t sl_RB_writestr(sl_ringbuffer_t *b, char *s);
|
||||
/******************************************************************************\
|
||||
The original socket.h
|
||||
\******************************************************************************/
|
||||
// max length (including trailing '\0') of UNIX socket path
|
||||
#define UNIX_SOCK_PATH_MAX 108
|
||||
|
||||
// handler result: what to send to client
|
||||
typedef enum{
|
||||
@@ -445,6 +448,15 @@ typedef struct{
|
||||
int len; // strlen of `val`
|
||||
} sl_sock_string_t;
|
||||
|
||||
// optional keyword number like key[12] = 500
|
||||
typedef struct{
|
||||
double magick; // -Inf - to distinguish it from sl_sock_*_t
|
||||
int n; // if n < 0 there was no any number in `key`
|
||||
} sl_sock_keyno_t;
|
||||
#define SL_SOCK_KEYNO_DEFAULT {.magick = -INFINITY, .n = -1}
|
||||
void sl_sock_keyno_init(sl_sock_keyno_t*);
|
||||
int sl_sock_keyno_check(sl_sock_keyno_t*);
|
||||
|
||||
struct sl_sock_hitem;
|
||||
struct sl_sock;
|
||||
|
||||
@@ -468,6 +480,9 @@ typedef enum{
|
||||
|
||||
struct sl_sock;
|
||||
|
||||
// opent socket and return its file descriptor
|
||||
int sl_sock_getfd(sl_socktype_e type, const char *path);
|
||||
|
||||
// default max clients amount
|
||||
#define SL_DEF_MAXCLIENTS (32)
|
||||
// custom socket handlers: connect/disconnect/etc
|
||||
@@ -535,4 +550,3 @@ int sl_sock_sendall(sl_sock_t *sock, uint8_t *data, size_t len);
|
||||
sl_sock_hresult_e sl_sock_inthandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str);
|
||||
sl_sock_hresult_e sl_sock_dblhandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str);
|
||||
sl_sock_hresult_e sl_sock_strhandler(sl_sock_t *client, sl_sock_hitem_t *hitem, const char *str);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user