version 0.3.2

This commit is contained in:
Edward Emelianov 2024-12-16 11:41:33 +03:00
parent 19c14db40b
commit 9e2bfe4456
9 changed files with 223 additions and 93 deletions

View File

@ -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}")

1
TODO
View File

@ -1 +0,0 @@
BUG in commandline options: '?' don't work!

View File

@ -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");

View File

@ -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 ""

View File

@ -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

View File

@ -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
View File

@ -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;
}

View File

@ -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);