mirror of
https://github.com/eddyem/snippets_library.git
synced 2025-12-06 02:35:20 +03:00
version 0.3.2
This commit is contained in:
parent
19c14db40b
commit
9e2bfe4456
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
set(PROJ usefull_macros)
|
||||
set(MINOR_VERSION "1")
|
||||
set(MINOR_VERSION "2")
|
||||
set(MID_VERSION "3")
|
||||
set(MAJOR_VERSION "0")
|
||||
set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}")
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <usefull_macros.h>
|
||||
|
||||
static sl_sock_t *s = NULL;
|
||||
@ -48,38 +50,70 @@ static sl_option_t cmdlnopts[] = {
|
||||
end_option
|
||||
};
|
||||
|
||||
static sl_ringbuffer_t *rb = NULL;
|
||||
static char rbuf[BUFSIZ], tbuf[BUFSIZ];
|
||||
|
||||
void signals(int sig){
|
||||
if(sig){
|
||||
signal(sig, SIG_IGN);
|
||||
DBG("Get signal %d, quit.\n", sig);
|
||||
}
|
||||
LOGERR("Exit with status %d", sig);
|
||||
}else LOGERR("Exit");
|
||||
if(rb){
|
||||
while(sl_RB_readline(rb, rbuf, BUFSIZ-1)){ // show all recent messages from server
|
||||
printf("server > %s\n", rbuf);
|
||||
}
|
||||
sl_RB_delete(&rb);
|
||||
}
|
||||
sl_restore_con();
|
||||
if(s) sl_sock_delete(&s);
|
||||
exit(sig);
|
||||
}
|
||||
|
||||
static void runclient(sl_sock_t *s){
|
||||
char buf[300];
|
||||
rb = sl_RB_new(BUFSIZ * 4);
|
||||
if(!s) return;
|
||||
do{
|
||||
printf("send > ");
|
||||
char *r = fgets(buf, 300, stdin);
|
||||
if(r){
|
||||
while(sl_RB_readline(rb, rbuf, BUFSIZ-1)){ // show all recent messages from server
|
||||
printf("server > %s\n", rbuf);
|
||||
}
|
||||
printf("send > "); fflush(stdout);
|
||||
int c, k = 0;
|
||||
while (k < BUFSIZ-1){
|
||||
ssize_t got = sl_sock_readline(s, rbuf, BUFSIZ);
|
||||
if(got > 0){
|
||||
DBG("GOT %zd", got);
|
||||
if(k == 0){ printf("\nserver > %s\nsend > ", rbuf); fflush(stdout); }// user didn't type anything -> show server messages
|
||||
else sl_RB_writestr(rb, rbuf);
|
||||
} else if(got < 0){ DBG("disc"); signals(0);}
|
||||
if(!s || !s->connected){ DBG("DISC"); signals(0); }
|
||||
c = sl_read_con();
|
||||
if(!c) continue;
|
||||
if(c == '\b' || c == 127){ // use DEL and BACKSPACE to erase previous symbol
|
||||
if(k){
|
||||
--k;
|
||||
printf("\b \b");
|
||||
}
|
||||
}else{
|
||||
if(c == EOF) break;
|
||||
tbuf[k++] = c;
|
||||
printf("%c", c);
|
||||
}
|
||||
fflush(stdout);
|
||||
if(c == '\n') break;
|
||||
}
|
||||
tbuf[k] = 0;
|
||||
DBG("Your str: _%s_", tbuf);
|
||||
if(c == EOF) break;
|
||||
if(k >= BUFSIZ-1) ERRX("Congrats! You caused buffer overflow!");
|
||||
if(k){
|
||||
DBG("try");
|
||||
if(-1 == sl_sock_sendstrmessage(s, buf)){
|
||||
if(-1 == sl_sock_sendstrmessage(s, tbuf)){
|
||||
WARNX("Error send");
|
||||
return;
|
||||
}
|
||||
DBG("OK");
|
||||
}else break;
|
||||
ssize_t got = 0;
|
||||
double t0 = sl_dtime();
|
||||
do{
|
||||
got = sl_sock_readline(s, buf, 299);
|
||||
if(got > 0) printf("server > %s\n", buf);
|
||||
}while(s && s->connected && (got > 0 || sl_dtime() - t0 < 0.3));
|
||||
if(got < 0) break;
|
||||
} while(s && s->connected);
|
||||
WARNX("Ctrl+D or disconnected");
|
||||
}
|
||||
@ -87,11 +121,12 @@ static void runclient(sl_sock_t *s){
|
||||
// flags for standard handlers
|
||||
static sl_sock_int_t iflag = {0};
|
||||
static sl_sock_double_t dflag = {0};
|
||||
static sl_sock_string_t sflag = {0};
|
||||
|
||||
static sl_sock_hresult_e dtimeh(sl_sock_t *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){
|
||||
static sl_sock_hresult_e dtimeh(sl_sock_t _U_ *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){
|
||||
char buf[32];
|
||||
snprintf(buf, 31, "UNIXT=%.2f\n", sl_dtime());
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
sl_sock_sendall((uint8_t*)buf, strlen(buf));
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
|
||||
@ -105,17 +140,41 @@ static sl_sock_hresult_e show(sl_sock_t *client, _U_ sl_sock_hitem_t *item, _U_
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
// Too much clients handler
|
||||
static void toomuch(int fd){
|
||||
const char *m = "Try later: too much clients connected\n";
|
||||
send(fd, m, sizeof(m+1), MSG_NOSIGNAL);
|
||||
const char m[] = "Try later: too much clients connected\n";
|
||||
send(fd, m, sizeof(m)-1, MSG_NOSIGNAL);
|
||||
shutdown(fd, SHUT_WR);
|
||||
DBG("shutdown, wait");
|
||||
double t0 = sl_dtime();
|
||||
uint8_t buf[8];
|
||||
while(sl_dtime() - t0 < 11.){
|
||||
if(sl_canread(fd)){
|
||||
ssize_t got = read(fd, buf, 8);
|
||||
DBG("Got=%zd", got);
|
||||
if(got < 1) break;
|
||||
}
|
||||
}
|
||||
DBG("Disc after %gs", sl_dtime() - t0);
|
||||
LOGWARN("Client fd=%d tried to connect after MAX reached", fd);
|
||||
}
|
||||
// new connections handler
|
||||
static void connected(sl_sock_t *c){
|
||||
if(c->type == SOCKT_UNIX) LOGMSG("New client fd=%d connected", c->fd);
|
||||
else LOGMSG("New client fd=%d, IP=%s connected", c->fd, c->IP);
|
||||
}
|
||||
// disconnected handler
|
||||
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);
|
||||
}
|
||||
|
||||
static sl_sock_hitem_t handlers[] = {
|
||||
{sl_sock_inthandler, "int", "set/get integer flag", (void*)&iflag},
|
||||
{sl_sock_dblhandler, "dbl", "set/get double flag", (void*)&dflag},
|
||||
{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", NULL},
|
||||
{dtimeh, "dtime", "get server's UNIX time for all clients connected", NULL},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@ -128,8 +187,11 @@ int main(int argc, char **argv){
|
||||
if(G.isserver){
|
||||
sl_sock_changemaxclients(G.maxclients);
|
||||
sl_sock_maxclhandler(toomuch);
|
||||
sl_sock_connhandler(connected);
|
||||
sl_sock_dischandler(disconnected);
|
||||
s = sl_sock_run_server(type, G.node, -1, handlers);
|
||||
} else {
|
||||
sl_setup_con();
|
||||
s = sl_sock_run_client(type, G.node, -1);
|
||||
}
|
||||
if(!s) ERRX("Can't create socket and/or run threads");
|
||||
|
||||
Binary file not shown.
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-12-10 17:44+0300\n"
|
||||
"POT-Creation-Date: 2024-12-16 11:25+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"
|
||||
@ -105,26 +105,38 @@ msgstr ""
|
||||
msgid "Wrong argument \"%s\" of parameter \"%s\""
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:133
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:148
|
||||
msgid "Server disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:208
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:223
|
||||
msgid "Can't start server handlers thread"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:245
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:285
|
||||
msgid "Limit of connections reached"
|
||||
msgstr ""
|
||||
|
||||
#. buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:319
|
||||
#. check for RB overflow
|
||||
#. -1 - buffer empty (can't be), -2 - buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:325
|
||||
#, c-format
|
||||
msgid "Server thread: buffer overflow from \"%s\""
|
||||
msgid "Server thread: ring buffer overflow for fd=%d"
|
||||
msgstr ""
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:339
|
||||
#, 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:351
|
||||
#, c-format
|
||||
msgid "Server thread: buffer overflow from fd=%d"
|
||||
msgstr ""
|
||||
|
||||
#. never reached
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:381
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:416
|
||||
#, 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: 2024-12-10 17:44+0300\n"
|
||||
"POT-Creation-Date: 2024-12-13 09:10+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"
|
||||
@ -85,7 +85,7 @@ msgstr "
|
||||
msgid "Can't setup console"
|
||||
msgstr "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:208
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:223
|
||||
msgid "Can't start server handlers thread"
|
||||
msgstr "îÅ ÍÏÇÕ ÚÁÐÕÓÔÉÔØ ÐÏÔÏË-ÏÂÒÁÂÏÔÞÉË ÓÅÒ×ÅÒÁ"
|
||||
|
||||
@ -117,7 +117,7 @@ msgstr "
|
||||
msgid "Key '%s' need value"
|
||||
msgstr "ëÌÀÞ '%s' ÔÒÅÂÕÅÔ ÚÎÁÞÅÎÉÑ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:245
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:285
|
||||
msgid "Limit of connections reached"
|
||||
msgstr "äÏÓÔÉÇÎÕÔ ÐÒÅÄÅÌ ÓÏÅÄÉÎÅÎÉÊ"
|
||||
|
||||
@ -146,22 +146,29 @@ msgstr "
|
||||
msgid "Port name is missing"
|
||||
msgstr "ïÔÓÕÔÓÔ×ÕÅÔ ÉÍÑ ÐÏÒÔÁ"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:133
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:148
|
||||
msgid "Server disconnected"
|
||||
msgstr "óÅÒ×ÅÒ ÏÔËÌÀÞÅÎ"
|
||||
|
||||
#. buffer overflow
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:319
|
||||
#, c-format
|
||||
msgid "Server thread: buffer overflow from \"%s\""
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÂÕÆÅÒÁ ÏÔ \"%s\""
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:351
|
||||
msgid "Server thread: buffer overflow from fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÂÕÆÅÒÁ ÏÔ fd=%d"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:339
|
||||
msgid "Server thread: can't write data to ringbuffer, overflow from fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÎÅ ÍÏÇÕ ÓÏÈÒÁÎÉÔØ ÄÁÎÎÙÅ × ËÏÌØÃÅ×ÏÍ ÂÕÆÅÒÅ, ÐÅÒÅÐÏÌÎÅÎÉÅ ÏÔ fd=%d"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:325
|
||||
msgid "Server thread: ring buffer overflow for fd=%d"
|
||||
msgstr "ðÏÔÏË ÓÅÒ×ÅÒÁ: ÐÅÒÅÐÏÌÎÅÎÉÅ ÂÕÆÅÒÁ ÏÔ fd=%d"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/config.c:226
|
||||
msgid "Unsupported option type"
|
||||
msgstr "îÅÐÏÄÄÅÒÖÉ×ÁÅÍÙÊ ÔÉÐ ÏÐÃÉÉ"
|
||||
|
||||
#. never reached
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:381
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/socket.c:416
|
||||
#, c-format
|
||||
msgid "Unsupported socket type %d"
|
||||
msgstr "îÅÐÏÄÄÅÒÖÉ×ÁÅÍÙÊ ÔÉÐ ÓÏËÅÔÁ %d"
|
||||
@ -170,8 +177,8 @@ msgstr "
|
||||
#, c-format
|
||||
msgid "Wrong USART format \"%s\"; use NPS, where N: 5..8; P: N/E/O/1/0, S: "
|
||||
"1/2"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ USART \"%s\"; ÎÕÖÅÎ NPS, ÇÄÅ N: 5..8; P: N/E/"
|
||||
"O/1/0, S: 1/2"
|
||||
msgstr "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ USART \"%s\"; ÎÕÖÅÎ NPS, ÇÄÅ N: 5..8; P: N/E/O/"
|
||||
"1/0, S: 1/2"
|
||||
|
||||
#: /home/eddy/Docs/SAO/C_diff/snippets_library/parseargs.c:494
|
||||
#, c-format
|
||||
|
||||
18
ringbuffer.c
18
ringbuffer.c
@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "usefull_macros.h"
|
||||
|
||||
@ -67,7 +68,7 @@ size_t sl_RB_datalen(sl_ringbuffer_t *b){
|
||||
// size of free space in buffer
|
||||
size_t sl_RB_freesize(sl_ringbuffer_t *b){
|
||||
pthread_mutex_lock(&b->busy);
|
||||
size_t l = b->length - datalen(b);
|
||||
size_t l = b->length - datalen(b) - 1;
|
||||
pthread_mutex_unlock(&b->busy);
|
||||
return l;
|
||||
}
|
||||
@ -76,7 +77,7 @@ size_t sl_RB_freesize(sl_ringbuffer_t *b){
|
||||
* @brief hasbyte - check if RB have given byte
|
||||
* @param b - rb
|
||||
* @param byte - what to find
|
||||
* @return index of byte or -1 if not found or no data
|
||||
* @return index of byte, -2 if not found or -1 if no data in buffer
|
||||
*/
|
||||
static ssize_t hasbyte(sl_ringbuffer_t *b, uint8_t byte){
|
||||
if(b->head == b->tail) return -1; // no data in buffer
|
||||
@ -88,7 +89,7 @@ static ssize_t hasbyte(sl_ringbuffer_t *b, uint8_t byte){
|
||||
}
|
||||
for(size_t found = startidx; found < b->tail; ++found)
|
||||
if(b->data[found] == byte) return found;
|
||||
return -1;
|
||||
return -2;
|
||||
}
|
||||
|
||||
// hasbyte with block
|
||||
@ -163,14 +164,18 @@ ret:
|
||||
* @param b - rb
|
||||
* @param s - string buffer
|
||||
* @param len - length of `s`
|
||||
* @return amount of characters read or -1 if buffer too small
|
||||
* @return amount of characters read or -2 if buffer overflow
|
||||
* !!! this function changes '\n' to 0 in `s`; `len` should include trailing '\0' too
|
||||
*/
|
||||
ssize_t sl_RB_readline(sl_ringbuffer_t *b, char *s, size_t len){
|
||||
ssize_t got = 0;
|
||||
pthread_mutex_lock(&b->busy);
|
||||
ssize_t idx = hasbyte(b, '\n');
|
||||
if(idx < 0) goto ret;
|
||||
if(idx < 0){
|
||||
if(idx == -1) idx = 0; // buffer is empty - return 0; else return error
|
||||
goto ret;
|
||||
}
|
||||
DBG("Got newline -> read");
|
||||
size_t partlen = idx + 1 - b->head;
|
||||
// now calculate length of new data portion
|
||||
if((size_t)idx < b->head) partlen += b->length;
|
||||
@ -179,6 +184,7 @@ ssize_t sl_RB_readline(sl_ringbuffer_t *b, char *s, size_t len){
|
||||
got = rbread(b, (uint8_t*)s, partlen);
|
||||
s[partlen - 1] = 0; // substitute '\n' with trailing zero
|
||||
}
|
||||
DBG("read: '%s'", s);
|
||||
ret:
|
||||
pthread_mutex_unlock(&b->busy);
|
||||
return got;
|
||||
@ -213,6 +219,7 @@ ret:
|
||||
size_t sl_RB_write(sl_ringbuffer_t *b, const uint8_t *str, size_t len){
|
||||
pthread_mutex_lock(&b->busy);
|
||||
size_t r = b->length - 1 - datalen(b); // rest length
|
||||
DBG("rest: %zd, need: %zd", r, len);
|
||||
if(len > r) len = r;
|
||||
if(!len) goto ret;
|
||||
size_t _1st = b->length - b->tail;
|
||||
@ -248,6 +255,7 @@ size_t sl_RB_writestr(sl_ringbuffer_t *b, char *s){
|
||||
size_t len = strlen(s);
|
||||
pthread_mutex_lock(&b->busy);
|
||||
size_t r = b->length - 1 - datalen(b); // rest length
|
||||
if(s[len-1] != '\n') s[len++] = '\n';
|
||||
if(len > r){ len = 0; goto ret; } // insufficient space - don't even try to write a part
|
||||
size_t _1st = b->length - b->tail;
|
||||
if(_1st > len) _1st = len;
|
||||
|
||||
124
socket.c
124
socket.c
@ -32,7 +32,11 @@
|
||||
// max clients amount
|
||||
static int maxclients = 32;
|
||||
// too much clients handler; it is running for client connected with number>maxclients (before closing its fd)
|
||||
static sl_sock_maxclh_t toomuchclients = NULL;
|
||||
static sl_sock_maxclh_t toomuch_handler = NULL;
|
||||
// new client connected handler; it will be run each new connection
|
||||
static sl_sock_connh_t newconnect_handler = NULL;
|
||||
// client disconnected handler
|
||||
static sl_sock_disch_t disconnect_handler = NULL;
|
||||
|
||||
/**
|
||||
* @brief sl_sock_changemaxclients - change amount of max simultaneously connected clients
|
||||
@ -44,9 +48,18 @@ void sl_sock_changemaxclients(int val){
|
||||
}
|
||||
int sl_sock_getmaxclients(){ return maxclients; }
|
||||
|
||||
// setter of "too much clients handler"
|
||||
// in each next function changed default handlers you can set h to NULL to remove your handler
|
||||
// setter of "too much clients" handler
|
||||
void sl_sock_maxclhandler(sl_sock_maxclh_t h){
|
||||
toomuchclients = h;
|
||||
toomuch_handler = h;
|
||||
}
|
||||
// setter of "new client connected" handler
|
||||
void sl_sock_connhandler(sl_sock_connh_t h){
|
||||
newconnect_handler = h;
|
||||
}
|
||||
// setter of "client disconnected" handler
|
||||
void sl_sock_dischandler(sl_sock_disch_t h){
|
||||
disconnect_handler = h;
|
||||
}
|
||||
|
||||
// text messages for `hresult`
|
||||
@ -116,8 +129,9 @@ void sl_sock_delete(sl_sock_t **sock){
|
||||
* @return NULL
|
||||
*/
|
||||
static void *clientrbthread(void *d){
|
||||
char buf[512];
|
||||
sl_sock_t *s = (sl_sock_t*) d;
|
||||
size_t buflen = s->buffer->length;
|
||||
char *buf = MALLOC(char, buflen);
|
||||
DBG("Start client read buffer thread");
|
||||
while(s && s->connected){
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
@ -126,8 +140,9 @@ static void *clientrbthread(void *d){
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
ssize_t n = read(s->fd, buf, 511);
|
||||
DBG("read %zd from %d, unlock", n, s->fd);
|
||||
ssize_t n = read(s->fd, buf, buflen);
|
||||
//DBG("read %zd from fd=%d, unlock", n, s->fd);
|
||||
//DBG("buf=%s", buf);
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
if(n < 1){
|
||||
WARNX(_("Server disconnected"));
|
||||
@ -233,6 +248,32 @@ static void *serverthread(void _U_ *d){
|
||||
// ZERO - listening server socket
|
||||
poll_set[0].fd = sockfd;
|
||||
poll_set[0].events = POLLIN;
|
||||
// disconnect client
|
||||
void disconnect_(sl_sock_t *c, int N){
|
||||
DBG("client \"%s\" (fd=%d) disconnected", c->IP, c->fd);
|
||||
if(disconnect_handler) disconnect_handler(c);
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
DBG("close fd %d", c->fd);
|
||||
c->connected = 0;
|
||||
close(c->fd);
|
||||
sl_RB_clearbuf(c->buffer);
|
||||
// now move all data of last client to disconnected
|
||||
if(nfd > 2 && N != nfd - 1){ // don't move the only or the last
|
||||
DBG("lock fd=%d", clients[nfd-1]->fd);
|
||||
pthread_mutex_lock(&clients[nfd-1]->mutex);
|
||||
clients[N] = clients[nfd-1];
|
||||
clients[nfd-1] = c;
|
||||
DBG("unlock fd=%d", clients[N]->fd);
|
||||
pthread_mutex_unlock(&clients[N]->mutex); // now N is nfd-1
|
||||
poll_set[N] = poll_set[nfd - 1];
|
||||
}
|
||||
DBG("unlock fd=%d", c->fd);
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
--nfd;
|
||||
}
|
||||
// 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);
|
||||
while(s && s->connected){
|
||||
poll(poll_set, nfd, 1);
|
||||
if(poll_set[0].revents & POLLIN){ // check main for accept()
|
||||
@ -240,10 +281,9 @@ static void *serverthread(void _U_ *d){
|
||||
socklen_t len = sizeof(struct sockaddr);
|
||||
int client = accept(sockfd, &a, &len);
|
||||
DBG("New connection, nfd=%d, len=%d", nfd, len);
|
||||
LOGMSG("SERVER got connection, fd=%d", client);
|
||||
if(nfd == maxclients + 1){
|
||||
WARNX(_("Limit of connections reached"));
|
||||
if(toomuchclients) toomuchclients(client);
|
||||
if(toomuch_handler) toomuch_handler(client);
|
||||
close(client);
|
||||
}else{
|
||||
memset(&poll_set[nfd], 0, sizeof(struct pollfd));
|
||||
@ -262,6 +302,7 @@ static void *serverthread(void _U_ *d){
|
||||
*c->IP = 0;
|
||||
}
|
||||
DBG("got IP:%s", c->IP);
|
||||
if(newconnect_handler) newconnect_handler(c);
|
||||
if(!c->buffer){ // allocate memory for client's ringbuffer
|
||||
DBG("allocate ringbuffer");
|
||||
c->buffer = sl_RB_new(s->buffer->length); // the same size as for master
|
||||
@ -269,55 +310,47 @@ static void *serverthread(void _U_ *d){
|
||||
++nfd;
|
||||
}
|
||||
}
|
||||
#define SBUFSZ (SL_KEY_LEN+SL_VAL_LEN+2)
|
||||
uint8_t buf[SBUFSZ];
|
||||
// scan connections
|
||||
for(int fdidx = 1; fdidx < nfd; ++fdidx){
|
||||
if((poll_set[fdidx].revents & POLLIN) == 0) continue;
|
||||
int fd = poll_set[fdidx].fd;
|
||||
sl_sock_t *c = clients[fdidx];
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
int nread = sl_RB_freesize(c->buffer);
|
||||
if(nread > SBUFSZ) nread = SBUFSZ;
|
||||
else if(nread < 1){
|
||||
size_t nread = sl_RB_freesize(c->buffer);
|
||||
if(nread > bufsize) nread = bufsize;
|
||||
else if(nread < 1){ // no space in ringbuffer
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
// check for RB overflow
|
||||
if(sl_RB_hasbyte(c->buffer, '\n') < 0){ // -1 - buffer empty (can't be), -2 - buffer overflow
|
||||
WARNX(_("Server thread: ring buffer overflow for fd=%d"), fd);
|
||||
disconnect_(c, fdidx);
|
||||
--fdidx;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
ssize_t got = read(fd, buf, nread);
|
||||
DBG("can read %zd bytes, got %zd bytes, buf=_%s_", nread, got, buf);
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
if(got <= 0){ // client disconnected
|
||||
DBG("client \"%s\" (fd=%d) disconnected", c->IP, fd);
|
||||
pthread_mutex_lock(&c->mutex);
|
||||
DBG("close fd %d", fd);
|
||||
c->connected = 0;
|
||||
close(fd);
|
||||
sl_RB_clearbuf(c->buffer);
|
||||
// now move all data of last client to disconnected
|
||||
if(nfd > 2 && fdidx != nfd - 1){ // don't move the only or the last
|
||||
DBG("lock fd=%d", clients[nfd-1]->fd);
|
||||
pthread_mutex_lock(&clients[nfd-1]->mutex);
|
||||
clients[fdidx] = clients[nfd-1];
|
||||
clients[nfd-1] = c;
|
||||
DBG("unlock fd=%d", clients[fdidx]->fd);
|
||||
pthread_mutex_unlock(&clients[fdidx]->mutex); // now fdidx is nfd-1
|
||||
poll_set[fdidx] = poll_set[nfd - 1];
|
||||
}
|
||||
DBG("unlock fd=%d", c->fd);
|
||||
pthread_mutex_unlock(&c->mutex);
|
||||
--nfd;
|
||||
disconnect_(c, fdidx);
|
||||
--fdidx;
|
||||
}else{
|
||||
sl_RB_write(c->buffer, buf, got);
|
||||
if(sl_RB_write(c->buffer, buf, got) < (size_t) got){
|
||||
WARNX(_("Server thread: can't write data to ringbuffer: overflow from fd=%d"), fd);
|
||||
disconnect_(c, fdidx);
|
||||
--fdidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
// and now check all incoming buffers
|
||||
for(int fdidx = 1; fdidx < nfd; ++fdidx){
|
||||
sl_sock_t *c = clients[fdidx];
|
||||
if(!c->connected) continue;
|
||||
ssize_t got = sl_RB_readline(c->buffer, (char*)buf, SBUFSZ);
|
||||
ssize_t got = sl_RB_readline(c->buffer, (char*)buf, bufsize);
|
||||
if(got < 0){ // buffer overflow
|
||||
ERRX(_("Server thread: buffer overflow from \"%s\""), c->IP);
|
||||
sl_RB_clearbuf(c->buffer);
|
||||
WARNX(_("Server thread: buffer overflow from fd=%d"), c->fd);
|
||||
disconnect_(c, fdidx);
|
||||
--fdidx;
|
||||
continue;
|
||||
}else if(got == 0) continue;
|
||||
sl_sock_hresult_e r = msgparser(c, (char*)buf);
|
||||
@ -325,6 +358,7 @@ static void *serverthread(void _U_ *d){
|
||||
}
|
||||
}
|
||||
// clear memory
|
||||
FREE(buf);
|
||||
FREE(poll_set);
|
||||
for(int i = maxclients; i > 0; --i){
|
||||
DBG("Clear %dth client data", i);
|
||||
@ -360,6 +394,7 @@ static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hit
|
||||
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);
|
||||
@ -369,7 +404,7 @@ static sl_sock_t *sl_sock_open(sl_socktype_e type, const char *path, sl_sock_hit
|
||||
ai.ai_addrlen = sizeof(unaddr);
|
||||
memcpy(unaddr.sun_path, str, 106);
|
||||
ai.ai_family = AF_UNIX;
|
||||
ai.ai_socktype = SOCK_SEQPACKET;
|
||||
//ai.ai_socktype = SOCK_SEQPACKET;
|
||||
break;
|
||||
case SOCKT_NET:
|
||||
case SOCKT_NETLOCAL:
|
||||
@ -514,10 +549,18 @@ ssize_t sl_sock_sendbinmessage(sl_sock_t *socket, const uint8_t *msg, size_t l){
|
||||
DBG("lock");
|
||||
pthread_mutex_lock(&socket->mutex);
|
||||
DBG("SEND");
|
||||
ssize_t r = send(socket->fd, msg, l, MSG_NOSIGNAL);
|
||||
ssize_t sent = 0;
|
||||
do{
|
||||
ssize_t r = send(socket->fd, msg+sent, l, MSG_NOSIGNAL);
|
||||
if(r < 0){
|
||||
sent = -1;
|
||||
break;
|
||||
}else sent += r;
|
||||
DBG("sent %zd bytes", r);
|
||||
} while((size_t)sent != l);
|
||||
DBG("unlock");
|
||||
pthread_mutex_unlock(&socket->mutex);
|
||||
return r;
|
||||
return sent;
|
||||
}
|
||||
|
||||
ssize_t sl_sock_sendstrmessage(sl_sock_t *socket, const char *msg){
|
||||
@ -589,7 +632,7 @@ sl_sock_hresult_e sl_sock_strhandler(sl_sock_t *client, sl_sock_hitem_t *hitem,
|
||||
char buf[SL_VAL_LEN + SL_KEY_LEN + 3];
|
||||
sl_sock_string_t *s = (sl_sock_string_t*) hitem->data;
|
||||
if(!str){ // getter
|
||||
sprintf(buf, "%s=%s\n", hitem->key, s->val);
|
||||
snprintf(buf, SL_VAL_LEN + SL_KEY_LEN + 2, "%s=%s\n", hitem->key, s->val);
|
||||
sl_sock_sendstrmessage(client, buf);
|
||||
return RESULT_SILENCE;
|
||||
}
|
||||
@ -598,5 +641,6 @@ sl_sock_hresult_e sl_sock_strhandler(sl_sock_t *client, sl_sock_hitem_t *hitem,
|
||||
s->len = l;
|
||||
s->timestamp = sl_dtime();
|
||||
memcpy(s->val, str, l);
|
||||
s->val[l] = 0;
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@ -478,23 +478,21 @@ typedef struct sl_sock{
|
||||
sl_sock_hitem_t *handlers; // if non-NULL, run handler's thread when opened
|
||||
} sl_sock_t;
|
||||
|
||||
#if 0
|
||||
// connected client descriptor
|
||||
typedef struct sl_sock_client{
|
||||
sl_sock_t *socket; // socket file descriptor
|
||||
const char *IP; // IP address formatted string
|
||||
void *res; // user data
|
||||
} sl_sock_client_t;
|
||||
#endif
|
||||
|
||||
const char *sl_sock_hresult2str(sl_sock_hresult_e r);
|
||||
void sl_sock_delete(sl_sock_t **sock);
|
||||
sl_sock_t *sl_sock_run_client(sl_socktype_e type, const char *path, int bufsiz);
|
||||
sl_sock_t *sl_sock_run_server(sl_socktype_e type, const char *path, int bufsiz, sl_sock_hitem_t *handlers);
|
||||
void sl_sock_changemaxclients(int val);
|
||||
int sl_sock_getmaxclients();
|
||||
// max clients handler
|
||||
typedef void (*sl_sock_maxclh_t)(int fd);
|
||||
void sl_sock_maxclhandler(sl_sock_maxclh_t h);
|
||||
// new client connected handler
|
||||
typedef void (*sl_sock_connh_t)(sl_sock_t *s);
|
||||
void sl_sock_connhandler(sl_sock_connh_t h);
|
||||
// client disconnected handler
|
||||
typedef void (*sl_sock_disch_t)(sl_sock_t *s);
|
||||
void sl_sock_dischandler(sl_sock_disch_t h);
|
||||
|
||||
ssize_t sl_sock_sendbinmessage(sl_sock_t *socket, const uint8_t *msg, size_t l);
|
||||
ssize_t sl_sock_sendbyte(sl_sock_t *socket, uint8_t byte);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user