Initial commit

master
Avril 5 years ago
commit 211c14c5b5
Signed by: flanchan
GPG Key ID: 284488987C31F630

4
.gitignore vendored

@ -0,0 +1,4 @@
libsipc/test
*.o
*.so
*.socket

@ -0,0 +1,19 @@
TRANS:=src/sipc.c
INCLUDE:=include/
CFLAGS:= -c -Wall -pedantic -fPIC -I$(INCLUDE)
all: clean libsipc test
clean:
rm -f *.o
rm -f *.so
rm -f test
rm -f *.socket
libsipc:
gcc $(CFLAGS) $(TRANS)
gcc -shared -o $@.so *.o
test: libsipc
gcc -Wall -pedantic -I$(INCLUDE) -Wl,-rpath=./ src/test.c -o $@ -L./ -lsipc
./$@

@ -0,0 +1,56 @@
#ifndef _LIBSIPC_H
#define _LIBSIPC_H
#include <stddef.h>
#define SI_MAX_MESSAGE_SIZE 1024
#define SI_ERROR_STRING_SIZE 256
#define SI_TYPE_STRING_SIZE 256
#define SI_SEND_OKAY 0
#define SI_SEND_PARTIAL 1
#define SI_SEND_ERROR -1
#define SI_SEND_FAILURE -2
#define SIQ_PRINTF_BUFFER_SIZE 256
typedef enum {
SI_STRING = 0,
SI_BINARY,
SI_CLOSE,
_SI_ERROR,
} si_type;
typedef struct {
si_type type;
unsigned int data_len;
unsigned char data[];
} si_message;
typedef enum {
SIE_ACCEPT= 0, //Sock accept failure
SIE_READ, //Sock read failure
SIE_PCONCLS, //Sock closed before read complete
SIE_INVALID, //Invalid message
} si_error;
typedef int (*si_callback)(const si_message *msg);
typedef int (*si_error_callback)(si_error err);
int si_bind(const char* file); //Returns sd, or -1 on failure.
int si_listen(int sd, si_error_callback on_error, si_callback on_message); //Returns non-zero on clean exit, -1 on error.
void si_close(int sd); //Close sock (must be called after si_listen()
char* si_error_string(si_error err);
char* si_type_string(si_type ty);
int si_connect(const char* file); //Returns sd, or -1 on failure.
int si_sendmsg(int sd, const si_message *msg); //Returns 0 on okay, 1 if whole message could not be sent, -1 on send error, -2 on weird send error. (see SI_SEND_*)
//Quick funcs
int siqs_string(int sd, const char* string); //quick send string
int siqs_close(int sd); //quick send close
int siqs_binary(int sd, const unsigned char* buffer, size_t size); //quick send binary
int siqs_printf(int sd, const char* format, ...); //quick send string (printf format)
#endif /* _LIBSIPC_H */

@ -0,0 +1,277 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <string.h>
#include <stdarg.h>
#include <sipc.h>
int si_bind(const char* file)
{
int sd, rc;
struct sockaddr_un server;
sd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sd<0)
{
return -1;
}
memset(&server,0,sizeof(server));
server.sun_family = AF_UNIX;
strncpy(server.sun_path, file, sizeof(server.sun_path));
rc = bind(sd, (struct sockaddr *)&server, SUN_LEN(&server));
if(rc<0)
{
close(sd);
return -1;
}
return sd;
}
static int _si_valid_header(const si_message *msg)
{
int kk = (int)msg->type;
return kk>=0 && kk<_SI_ERROR && msg->data_len < SI_MAX_MESSAGE_SIZE;
}
static int _si_read_rest(int sd, si_message *message)
{
int read = 0;
int rd=0;
while( (read += (rd = recv(sd, message->data, message->data_len, 0))) < message->data_len)
{
if(rd<0) return -1;
else if(rd==0) return 1;
}
return 0;
}
int si_listen(int sd, si_error_callback on_error, si_callback on_message)
{
int rc = listen(sd, 10);
if(rc<0) {
return -1;
}
while(1) {
int csd = accept(sd, NULL,NULL);
if(csd<0) {
rc = on_error(SIE_ACCEPT);
if(rc<0) break;
}
unsigned char buffer[sizeof(si_message)];
si_message *message = (si_message*)buffer;
int read=0;
int rd=0;
rc=0;
while( (read += (rd = recv(csd, buffer, sizeof(si_message), 0))) < sizeof(si_message))
{
if(rd<0)
{
rc = on_error(SIE_READ);
break;
} else if(rd==0)
{
rc = on_error(SIE_PCONCLS);
break;
}
}
if(rc<0) {
close(csd);
break;
} else {
//message header has been read.
si_message *full;
if(_si_valid_header(message))
{
full = malloc(sizeof(si_message)+message->data_len+1);
memset(full,0,sizeof(si_message)+message->data_len+1); //always have null-term
memcpy(full, message, sizeof(si_message));
rc = _si_read_rest(csd, full);
}
else {
rc = on_error(SIE_INVALID);
}
if(rc!=0) {
if(rc==-1)
rc = on_error(SIE_READ);
else
rc = on_error(SIE_PCONCLS);
if(rc<0) {
close(csd);
break;
}
} else {
//Message has been read.
rc = on_message(full);
free(full);
}
}
close(csd);
if(rc!=0) break;
}
return rc;
}
void si_close(int sd)
{
close(sd);
}
char *si_error_string(si_error err)
{
static char buffer[SI_ERROR_STRING_SIZE];
memset(buffer, 0, SI_ERROR_STRING_SIZE);
#define put(...) snprintf(buffer, SI_ERROR_STRING_SIZE-1, __VA_ARGS__)
switch(err) {
case SIE_ACCEPT:
put("SIE_ACCEPT: Socket accept error");
break;
case SIE_READ:
put("SIE_READ: Socket read error");
break;
case SIE_PCONCLS:
put("SIE_PCONCLS: Socket closed");
break;
case SIE_INVALID:
put("SIE_INVALID: Bad message");
default:
put("SIE_UNKNOWN: Unknown EC %d", (int)err);
break;
}
#undef put
return buffer;
}
char *si_type_string(si_type type)
{
static char buffer[SI_ERROR_STRING_SIZE];
memset(buffer, 0, SI_ERROR_STRING_SIZE);
#define put(...) snprintf(buffer, SI_ERROR_STRING_SIZE-1, __VA_ARGS__)
switch(type) {
case SI_STRING:
put("SI_STRING");
break;
case SI_BINARY:
put("SI_BINARY");
break;
case SI_CLOSE:
put("SI_CLOSE");
break;
default:
put("SI_UNKNWON");
break;
}
#undef put
return buffer;
}
int si_connect(const char *file)
{
int sd=-1, rc;
struct sockaddr_un server;
sd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sd<0) {
return -1;
}
memset(&server,0,sizeof(server));
server.sun_family = AF_UNIX;
strncpy(server.sun_path, file, sizeof(server.sun_path));
rc = connect(sd, (struct sockaddr*)&server, SUN_LEN(&server));
if(rc<0) {
close(sd);
return -1;
}
return sd;
}
int si_sendmsg(int sd, const si_message *msg)
{
int rc = send(sd, msg, sizeof(si_message)+msg->data_len, 0);
if(rc<0)
return SI_SEND_ERROR;
else if(rc==0)
return SI_SEND_FAILURE;
else if(rc != sizeof(si_message)+msg->data_len)
return SI_SEND_PARTIAL;
return SI_SEND_OKAY;
}
//Quick send functions
int siqs_string(int sd, const char* string)
{
si_message *msg = malloc(sizeof(si_message)+strlen(string));
memset(msg,0,sizeof(si_message)+strlen(string));
msg->type = SI_STRING;
msg->data_len = strlen(string);
memcpy(msg->data, string, msg->data_len);
int rc = si_sendmsg(sd, msg);
free(msg);
return rc;
}
int siqs_close(int sd)
{
si_message *msg = malloc(sizeof(si_message));
memset(msg,0,sizeof(si_message));
msg->type = SI_CLOSE;
msg->data_len=0;
int rc = si_sendmsg(sd, msg);
free(msg);
return rc;
}
int siqs_binary(int sd, const unsigned char* buffer, size_t size)
{
si_message *msg = malloc(sizeof(si_message)+size);
memset(msg,0,sizeof(si_message)+size);
msg->type = SI_BINARY;
msg->data_len = size;
memcpy(msg->data, buffer, msg->data_len);
int rc = si_sendmsg(sd, msg);
free(msg);
return rc;
}
int siqs_printf(int sd, const char* format, ...)
{
char buffer[SIQ_PRINTF_BUFFER_SIZE];
va_list list;
va_start(list, format);
memset(buffer,0,SIQ_PRINTF_BUFFER_SIZE);
vsnprintf(buffer, SIQ_PRINTF_BUFFER_SIZE-1, format, list);
int rc = siqs_string(sd, buffer);
va_end(list);
return rc;
}

@ -0,0 +1,158 @@
#include <sipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int on_error(si_error err)
{
printf("[E] <- %s\n", si_error_string(err));
return 0;
}
int on_message(const si_message *msg)
{
char* text;
const char* strty = si_type_string(msg->type);
int rc=0;
switch(msg->type)
{
case SI_CLOSE:
rc=1;
text = "...";
break;
case SI_STRING:
text = (char*) msg->data;
break;
case SI_BINARY:
text = "...";
break;
default:
text= "(unbound)";
break;
}
printf("<- (%s) %s\n", strty, text);
return rc;
}
int server(const char* bindto)
{
int sd = si_bind(bindto);
int rc=-1;
if(sd<0) {
printf("error binding\n");
} else {
rc = si_listen(sd, &on_error, &on_message);
printf("listen stopped with rc %d\n", rc);
if(rc>=0) //positive rc is okay
rc=0;
}
si_close(sd);
return rc;
}
int cli_return(int rrc)
{
int rc=-1;
switch(rrc) {
case SI_SEND_OKAY:
printf("send okay\n");
rc=0;
break;
case SI_SEND_ERROR:
printf("send error\n");
break;
case SI_SEND_FAILURE:
printf("send failure\n");
break;
case SI_SEND_PARTIAL:
printf("partial send failure\n");
break;
default:
printf("unknown send error");
break;
}
return rc;
}
int client(const char* conto, const char* string)
{
si_message *msg = malloc(sizeof(si_message)+strlen(string));
memset(msg,0,sizeof(si_message)+strlen(string));
msg->type = SI_STRING;
msg->data_len = strlen(string);
memcpy(msg->data, string, msg->data_len);
int rc=-1;
int sd = si_connect(conto);
if(sd<0) {
printf("connect error\n");
} else {
int rrc = si_sendmsg(sd, msg);
rc = cli_return(rrc);
si_close(sd);
}
free(msg);
return rc;
}
int client_close(const char* conto)
{
si_message *msg = malloc(sizeof(si_message));
memset(msg,0,sizeof(si_message));
msg->type = SI_CLOSE;
msg->data_len=0;
int rc=-1;
int sd = si_connect(conto);
if(sd<0) {
printf("connect error\n");
} else {
int rrc = si_sendmsg(sd, msg);
rc = cli_return(rrc);
si_close(sd);
}
free(msg);
return rc;
}
int main(int argc, char** argv)
{
int rc=0;
if(argv[1] && argv[2] && argv[1][0]=='-') {
switch(argv[1][1]) {
case 'l':
//Listen
rc = server(argv[2]);
break;
case 'p':
//Write
if(argv[3])
{
rc = client(argv[2], argv[3]);
printf("client rc %d\n", rc);
} else printf("no message\n");
break;
case 'c':
//Close
client_close(argv[2]);
break;
default:
printf("i don't know how to do that\n");
break;
}
} else printf("usage: %s -l <socket>\nusage: %s -p <socket> <message>\nusage: %s -c <socket>\n", argv[0], argv[0], argv[0]);
return rc;
}
Loading…
Cancel
Save