#include "helper.h"
#include <socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <stdarg.h>
DebugLevel _debugLevel = DEBUG_WARNING;
int _autoRestart = 0;
void bail(char *args, ...)
{
printf("ERROR: ");
va_list argList;
va_start(argList, args);
vprintf(args, argList);
va_end(argList);
printf("\n");
fflush(stdout);
fflush(stderr);
exit(1);
}
/**
* 0 = SUCCESS, -1 = ERROR
* on success, memory pointer and size variable will be updated.
*/
int helper_realloc(char **memory, size_t *curSize, const size_t newSize, const char *location)
{
void *newBlock = realloc(*memory, newSize);
if (newBlock == NULL) {
printf("OUT OF MEMORY when trying to realloc to %d bytes at %s\n", (int)newSize, location);
return -1;
}
*memory = newBlock;
if (curSize != NULL) *curSize = newSize;
return 0;
}
int helper_connect4(char *address, int port, char *ip)
{
if (sizeof(struct in_addr) != 4) bail("Ach nöö ach nöö");
if (inet_pton(AF_INET, address, ip) == 1) {
const int sock = helper_newSocket();
if (sock == -1) return -1;
if (socket_connect4(sock, ip, port) == 0) {
return sock;
}
close(sock);
return -1;
}
struct addrinfo hints;
struct addrinfo *result, *rp;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
const int ret = getaddrinfo(address, NULL, &hints, &result);
if (ret != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
const int sock = helper_newSocket();
if (sock == -1) continue;
if (rp->ai_addr != NULL) {
memcpy(ip, &((struct sockaddr_in*)rp->ai_addr)->sin_addr, 4);
if (socket_connect4(sock, ip, port) == 0) {
freeaddrinfo(result);
return sock; // Success
}
}
close(sock);
}
freeaddrinfo(result);
return -1;
}
int helper_newSocket()
{
struct timeval tv;
int sock = socket_tcp4b();
if (sock == -1) return -1;
tv.tv_sec = 4;
tv.tv_usec = 0;
setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv) );
setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv) );
return sock;
}
void helper_nonblock(const int fd)
{
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
}
static void helper_printavaInt(struct AttributeValueAssertion* a,const char* rel)
{
printf("(%.*s%s", (int)a->desc.l, a->desc.s, rel);
if (a->value.l != 0 && a->value.s != NULL) {
printf("%.*s)", (int)a->value.l,a->value.s);
} else {
putchar(')');
}
}
void helper_printava(struct AttributeValueAssertion* a,const char* rel)
{
helper_printavaInt(a, rel);
putchar('\n');
}
void helper_printal(struct AttributeDescriptionList* a)
{
while (a) {
if (a->a.s && a->a.l) printf("%.*s", (int)a->a.l,a->a.s);
a=a->next;
if (a) {
putchar(',');
}
}
putchar('\n');
}
void helper_printpal(struct PartialAttributeList *pal)
{
printf("-- PAL --\n");
while (pal) {
printf("entry (");
if (pal->type.l && pal->type.s) printf("%.*s", (int)pal->type.l, pal->type.s);
printf("): ");
helper_printal(pal->values);
pal = pal->next;
}
}
static void helper_printfilterInt(struct Filter* f)
{
if (f == NULL) {
printf("(nullfilter)");
return;
}
while (f != NULL) {
switch (f->type) {
case AND:
printf("(&");
mergesub:
helper_printfilterInt(f->x);
putchar(')');
break;
case OR:
printf("(|");
goto mergesub;
case NOT:
printf("(!");
goto mergesub;
case EQUAL:
helper_printavaInt(&f->ava,"=");
break;
case SUBSTRING: {
struct Substring* s=f->substrings;
int first=1;
printf("(%.*s",(int)f->ava.desc.l,f->ava.desc.s);
printf(" has ");
while (s) {
if (!first) {
printf(" and ");
}
first=0;
switch(s->substrtype) {
case prefix:
printf("prefix \"");
break;
case any:
printf("substr \"");
break;
case suffix:
printf("suffix \"");
break;
}
printf("%.*s\"",(int)s->s.l,s->s.s);
s=s->next;
}
putchar(')');
}
break;
case GREATEQUAL:
helper_printavaInt(&f->ava,">=");
break;
case LESSEQUAL:
helper_printavaInt(&f->ava,"<=");
break;
case PRESENT:
f->ava.value.l = 0;
helper_printavaInt(&f->ava,"=*");
break;
case APPROX:
helper_printavaInt(&f->ava,"~=");
break;
case EXTENSIBLE:
printf("[extensible]");
break;
default:
printf("????????");
}
f = f->next;
}
}
void helper_printfilter(struct Filter* f)
{
helper_printfilterInt(f);
putchar('\n');
}
void plog(const DebugLevel messageLevel, char *args, ...)
{
if (messageLevel > _debugLevel) return;
va_list argList;
va_start(argList, args);
vprintf(args, argList);
va_end(argList);
putchar('\n');
fflush(stdout);
}