Example of sending and receiving GWY objects over a network stream. This is the server part which listens to requests and answers them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
static void
ensure_buffer_size(char **buffer, size_t *bufsize, size_t len)
{
if (len <= *bufsize)
return;
if (2*(*bufsize) >= len)
*bufsize *= 2;
else
*bufsize = len;
*buffer = realloc(*buffer, *bufsize);
}
#ifdef __GNUC__
__attribute__((unused))
#endif
static GwyfileObject*
recv_gwyfile_message(int sock, char **buffer, size_t *bufsize, int *err)
{
GwyfileObject *message;
size_t objsize, len = 0;
ssize_t read_size;
if (!*bufsize || !*buffer)
ensure_buffer_size(buffer, bufsize, 16);
*err = -1;
printf("Trying to read %u bytes.\n", (unsigned)(*bufsize - len));
while ((read_size = read(sock, *buffer + len, *bufsize - len)) > 0) {
printf("Read %ld bytes from socket %d\n", (long int)read_size, sock);
len += read_size;
assert(error);
if (len == *bufsize) {
ensure_buffer_size(buffer, bufsize, 2*(*bufsize));
fprintf(stderr, "Enlarging buffer to %lu.\n", (unsigned long)(*bufsize));
}
continue;
}
else {
fprintf(stderr,
"Failed to read message. %s\n", error->
message);
fprintf(stderr, "Giving up.\n");
return NULL;
}
}
printf("Obtained message of %lu bytes\n", (unsigned long int)objsize);
*err = 0;
return message;
}
if (read_size < 0) {
fprintf(stderr, "recv() failed: %s.\n", strerror(errno));
return NULL;
}
else if (len > 0) {
fprintf(stderr, "Incomplete message.\n");
return NULL;
}
*err = 0;
return NULL;
}
#ifdef __GNUC__
__attribute__((unused))
#endif
static GwyfileObject*
recv_gwyfile_message2(int sock, char **buffer, size_t *bufsize, size_t *have_bytes, int *err)
{
GwyfileObject *message;
size_t objsize;
ssize_t read_size;
int first_try = 1;
if (!*bufsize || !*buffer)
ensure_buffer_size(buffer, bufsize, 16);
while (1) {
if (!first_try || !*have_bytes) {
printf("Trying to read %u bytes.\n", (unsigned)(*bufsize - *have_bytes));
if ((read_size = read(sock, *buffer + *have_bytes, *bufsize - *have_bytes)) <= 0)
break;
printf("Read %ld bytes from socket %d\n", (long int)read_size, sock);
*have_bytes += read_size;
}
else {
printf("Trying to use the %lu bytes left in buffer.\n", (unsigned long int)(*have_bytes));
}
printf("Obtained message of %lu bytes (%lu bytes remaining)\n",
(unsigned long int)objsize, (unsigned long int)(*have_bytes - objsize));
memmove(*buffer, *buffer + objsize, *have_bytes - objsize);
*have_bytes -= objsize;
*err = 0;
return message;
}
assert(error);
goto bad_message;
if (*have_bytes == *bufsize) {
ensure_buffer_size(buffer, bufsize, 2*(*bufsize));
fprintf(stderr, "Enlarging buffer to %lu.\n", (unsigned long)(*bufsize));
}
first_try = 0;
}
*err = errno;
if (read_size < 0) {
fprintf(stderr, "recv() failed: %s.\n", strerror(errno));
return NULL;
}
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
*err = EAGAIN;
fprintf(stderr, "Incomplete message so far.\n");
return NULL;
}
if (errno)
fprintf(stderr, "We got zero from recv() with unexpected error %s.\n", strerror(errno));
return NULL;
bad_message:
fprintf(stderr,
"Failed to read message. %s\n", error->
message);
fprintf(stderr, "Giving up.\n");
*err = EINVAL;
return NULL;
}
#ifdef __GNUC__
__attribute__((unused))
#endif
static int
send_gwyfile_message(GwyfileObject *message, int sock, char **buffer, size_t *bufsize)
{
ssize_t pos, write_size;
size_t len;
ensure_buffer_size(buffer, bufsize, len);
assert(len);
pos = 0;
while (len > 0) {
write_size = write(sock, *buffer + pos, len);
if (write_size < 0) {
int saved_errno = errno;
fprintf(stderr, "send() failed: %s.\n", strerror(errno));
errno = saved_errno;
return -1;
}
len -= write_size;
pos += write_size;
}
return 0;
}
void gwyfile_error_clear(GwyfileError **error)
Clears a GwyfileError.
Definition: gwyfile.c:8990
@ GWYFILE_ERROR_TRUNCATED
The top-level object is truncated.
Definition: gwyfile.h:128
@ GWYFILE_ERROR_DOMAIN_DATA
Libgwyfle data error domain: codes are equal to GwyfileErrorCode values. They represent data format e...
Definition: gwyfile.h:112
size_t gwyfile_object_size(const GwyfileObject *object)
Obtains the serialized size of a GWY file data object.
Definition: gwyfile.c:4615
GwyfileObject * gwyfile_object_read_memory(const void *buffer, size_t size, size_t *bytes_read, GwyfileError **error)
Reads a GWY file data object from a memory buffer.
Definition: gwyfile.c:5196
size_t gwyfile_object_write_memory(const GwyfileObject *object, void *buffer, size_t size, GwyfileError **error)
Writes a GWY file data object to a memory buffer.
Definition: gwyfile.c:5255
Detailed information about an error.
Definition: gwyfile.h:131
char * message
Text message describing the error. It is allocated when the error struct is created and freed with gw...
Definition: gwyfile.h:134
int code
Particular error code. For errors from the system domain it is equal to errno while for libgwyfile-sp...
Definition: gwyfile.h:133
GwyfileErrorDomain domain
Identifier of the class of errors.
Definition: gwyfile.h:132
#include "clientserver.h"
static void connection_handler(int sock);
static GwyfileObject* answer_to_message (GwyfileObject *message);
int
main(int argc, char *argv[])
{
int portno, socket_desc, client_sock, c = sizeof(struct sockaddr_in);
struct sockaddr_in server, client;
if (argc < 2) {
printf("Usage: server PORTNUMBER\n");
exit(EXIT_SUCCESS);
}
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Cannot create socket");
exit(EXIT_FAILURE);
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
portno = atoi(argv[1]);
server.sin_port = htons(portno);
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind() failed");
exit(EXIT_FAILURE);
}
listen(socket_desc, 3);
while ((client_sock = accept(socket_desc, (struct sockaddr*)&client, (socklen_t*)&c)) > 0) {
printf("Connection accepted.\n");
connection_handler(client_sock);
close(client_sock);
}
if (client_sock < 0) {
perror("accept() failed");
exit(EXIT_FAILURE);
}
return 0;
}
static void
connection_handler(int sock)
{
GwyfileObject *message, *answer;
char *recvbuffer = NULL, *sendbuffer = NULL;
size_t recvbufsize = 0, sendbufsize = 0, recvlen = 0;
int err;
while ((message = recv_gwyfile_message2(sock, &recvbuffer, &recvbufsize, &recvlen, &err)) || err == EAGAIN) {
if (err == EAGAIN)
continue;
answer = answer_to_message(message);
usleep(rand() % 1000000);
if ((err = send_gwyfile_message(answer, sock, &sendbuffer, &sendbufsize)) < 0) {
break;
}
}
if (err == 0)
printf("Communication finished successfully.\n\n");
else
fprintf(stderr, "Communication failed.\n\n");
free(sendbuffer);
free(recvbuffer);
}
static GwyfileObject*
answer_to_message(GwyfileObject *message)
{
const char *dont = "I thought I had told you a thousand times that I really do not like ";
GwyfileObject *answer;
GwyfileItem *item, *newitem;
unsigned int nitems, i, len, ll = strlen(dont);
const char *name, *s;
char *t;
for (i = 0; i < nitems; i++) {
newitem = NULL;
char hexbuf[8*2+3];
}
len = strlen(s);
t = malloc(len + ll + 1);
memcpy(t, dont, ll);
memcpy(t + ll, s, len+1);
}
for (j = 0; j < n; j++)
data[i] *= 2.0;
}
else {
fprintf(stderr, "Cannot take ownership of double array item %s.\n", name);
}
}
if (newitem)
}
return answer;
}
bool gwyfile_item_get_bool(const GwyfileItem *item)
Gets the boolean value contained in a GWY file data item.
Definition: gwyfile.c:5440
GwyfileItem * gwyfile_item_new_bool(const char *name, bool value)
Creates a new boolean GWY file item.
Definition: gwyfile.c:5406
double * gwyfile_item_take_double_array(GwyfileItem *item)
Takes the double array value contained in a GWY file data item.
Definition: gwyfile.c:6844
GwyfileItem * gwyfile_item_new_double_array(const char *name, double *value, uint32_t array_length)
Creates a new double array GWY file item.
Definition: gwyfile.c:6638
GwyfileItem * gwyfile_item_new_double(const char *name, double value)
Creates a new double GWY file item.
Definition: gwyfile.c:5606
double gwyfile_item_get_double(const GwyfileItem *item)
Gets the double value contained in a GWY file data item.
Definition: gwyfile.c:5640
int32_t gwyfile_item_get_int32(const GwyfileItem *item)
Gets the 32bit integer value contained in a GWY file data item.
Definition: gwyfile.c:5540
GwyfileItem * gwyfile_item_new_int32(const char *name, int32_t value)
Creates a new 32bit integer GWY file item.
Definition: gwyfile.c:5506
int64_t gwyfile_item_get_int64(const GwyfileItem *item)
Gets the 64bit integer value contained in a GWY file data item.
Definition: gwyfile.c:5590
GwyfileItem * gwyfile_item_new_string(const char *name, char *value)
Creates a new string GWY file item.
Definition: gwyfile.c:5660
GwyfileItem * gwyfile_item_new_string_copy(const char *name, const char *value)
Creates a new string GWY file item.
Definition: gwyfile.c:5712
const char * gwyfile_item_get_string(const GwyfileItem *item)
Gets the string value contained in a GWY file data item.
Definition: gwyfile.c:5814
uint32_t gwyfile_item_array_length(const GwyfileItem *item)
Obtains the array length of a GWY file data item.
Definition: gwyfile.c:7326
const char * gwyfile_item_name(const GwyfileItem *item)
Obtains the name of a GWY file data item.
Definition: gwyfile.c:7311
GwyfileItemType
Definition: gwyfile.h:87
bool gwyfile_item_owns_data(const GwyfileItem *item)
Reports if a GWY file item owns its data.
Definition: gwyfile.c:8082
GwyfileItemType gwyfile_item_type(const GwyfileItem *item)
Obtains the type of a GWY file data item.
Definition: gwyfile.c:7298
@ GWYFILE_ITEM_INT32
32bit integer.
Definition: gwyfile.h:90
@ GWYFILE_ITEM_DOUBLE_ARRAY
Array of IEEE double precision floating point numbers.
Definition: gwyfile.h:98
@ GWYFILE_ITEM_STRING
String of characters.
Definition: gwyfile.h:93
@ GWYFILE_ITEM_BOOL
Boolean (true or false).
Definition: gwyfile.h:88
@ GWYFILE_ITEM_INT64
64bit integer.
Definition: gwyfile.h:91
@ GWYFILE_ITEM_DOUBLE
IEEE double precision floating point number.
Definition: gwyfile.h:92
GwyfileObject * gwyfile_object_new(const char *name,...)
Creates a new GWY file object.
Definition: gwyfile.c:607
GwyfileItem * gwyfile_object_get_nth(const GwyfileObject *object, unsigned int n)
Gets n-th data item from a GWY file object.
Definition: gwyfile.c:4875
bool gwyfile_object_add(GwyfileObject *object, GwyfileItem *item)
Adds an data item to a GWY file data object.
Definition: gwyfile.c:4652
unsigned int gwyfile_object_nitems(const GwyfileObject *object)
Obtains the number of items in a GWY file data object.
Definition: gwyfile.c:4920
void gwyfile_object_free(GwyfileObject *object)
Frees a GWY file data object.
Definition: gwyfile.c:4577