blob: 9f0502c155c78795dd355bdba9281857f547b6f1 [file] [log] [blame] [raw]
/*
* Copyright 2015-2018 Rivoreo
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include "common.h"
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
//#include <syslog.h>
int get_local_packet(int fd, struct local_packet **packet, struct private_buffer *buffer) {
struct local_packet **p = buffer ? (struct local_packet **)&buffer->buffer : packet;
size_t skip = 0;
size_t length;
int s;
if(buffer && buffer->buffer) {
//syslog(LOG_DEBUG, "get_local_packet: continue from last packet: buffer = %p, total_length = %zu, read_length = %zu",
// buffer->buffer, buffer->total_length, buffer->read_length);
length = buffer->total_length;
skip = buffer->read_length;
} else {
do {
s = read(fd, &length, sizeof length);
} while(s < 0 && errno == EINTR);
if(s < 0) return GET_PACKET_ERROR;
if(!s) return GET_PACKET_EOF;
if(s < sizeof length) return GET_PACKET_SHORT_READ;
if(length > LOCAL_PACKET_MAX_LENGTH) {
*(unsigned int *)packet = length;
return GET_PACKET_TOO_LARGE;
}
*p = malloc(sizeof length + length);
if(!*p) {
*(unsigned int *)packet = length;
return GET_PACKET_OUT_OF_MEMORY;
}
//((struct local_packet *)*p)->length = length;
(*p)->length = length;
if(buffer) {
buffer->total_length = length;
buffer->read_length = 0;
}
}
do {
s = read(fd, (char *)*p + sizeof length + skip, length - skip);
} while(s < 0 && errno == EINTR);
int r = 0;
if(s < 0) r = GET_PACKET_ERROR;
else if(!s) r = GET_PACKET_EOF;
else if(skip + s < length) {
if(buffer) {
buffer->read_length += s;
return GET_PACKET_INCOMPLETE;
}
r = GET_PACKET_SHORT_READ;
}
if(r) free(*p);
if(buffer) {
*packet = (struct local_packet *)buffer->buffer;
buffer->buffer = NULL;
buffer->total_length = 0;
buffer->read_length = 0;
}
return r;
}