diff options
Diffstat (limited to '')
| -rw-r--r-- | src/libmdsserver/mds-message.c | 122 | 
1 files changed, 69 insertions, 53 deletions
| diff --git a/src/libmdsserver/mds-message.c b/src/libmdsserver/mds-message.c index ea4e458..c70bb15 100644 --- a/src/libmdsserver/mds-message.c +++ b/src/libmdsserver/mds-message.c @@ -26,6 +26,9 @@  #include <sys/socket.h> +#define try(INSTRUCTION)   if ((r = INSTRUCTION) < 0)  return r + +  /**   * Initialise a message slot so that it can   * be used by `mds_message_read` @@ -272,10 +275,52 @@ static int store_header(mds_message_t* restrict this, size_t length)  /** - * Read the next message from a file descriptor + * Continue reading from the socket into the buffer + *  + * @param   this  The message + * @param   fd    The file descriptor of the socekt + * @return        The return value follows the rules of `mds_message_read` + */ +static int continue_read(mds_message_t* restrict this, int fd) +{ +  size_t n; +  ssize_t got; +  int r; +   +  /* Figure out how much space we have left in the read buffer. */ +  n = this->buffer_size - this->buffer_ptr; +   +  /* If we do not have too much left, */ +  if (n < 128) +    { +      /* grow the buffer, */ +      try (mds_message_extend_buffer(this)); +	   +      /* and recalculate how much space we have left. */ +      n = this->buffer_size - this->buffer_ptr; +    } +   +  /* Then read from the socket. */ +  errno = 0; +  got = recv(fd, this->buffer + this->buffer_ptr, n, 0); +  this->buffer_ptr += (size_t)(got < 0 ? 0 : got); +  if (errno) +    return -1; +  if (got == 0) +    { +      errno = ECONNRESET; +      return -1; +    } +   +  return 0; +} + + +/** + * Read the next message from a file descriptor of the socekt   *    * @param   this  Memory slot in which to store the new message - * @param   fd    The file descriptor + * @param   fd    The file descriptor of the socekt   * @return        Non-zero on error or interruption, errno will be   *                set accordingly. Destroy the message on error,   *                be aware that the reading could have been @@ -289,8 +334,6 @@ int mds_message_read(mds_message_t* restrict this, int fd)    size_t header_commit_buffer = 0;    int r; -#define try(INSTRUCTION)   if ((r = INSTRUCTION) < 0)  return r -      /* If we are at stage 2, we are done and it is time to start over.       This is important because the function could have been interrupted. */    if (this->stage == 2) @@ -302,8 +345,6 @@ int mds_message_read(mds_message_t* restrict this, int fd)    /* Read from file descriptor until we have a full message. */    for (;;)      { -      size_t n; -      ssize_t got;        char* p;        size_t length; @@ -337,12 +378,8 @@ int mds_message_read(mds_message_t* restrict this, int fd)  	    this->stage = 1;  	  } +              /* Stage 1: payload. */ -      if ((this->stage == 1) && (this->payload_size == 0)) -	{ -	  this->stage = 2; -	  return 0; -	}        if ((this->stage == 1) && (this->payload_size > 0))  	{  	  /* How much of the payload that has not yet been filled. */ @@ -356,45 +393,22 @@ int mds_message_read(mds_message_t* restrict this, int fd)  	  /* Keep track of how much we have read. */  	  this->payload_ptr += move; -	   -	  /* If we have filled the payload, make the end of this stage, -	     i.e. that the message is complete, and return with success. */ -	  if (this->payload_ptr == this->payload_size) -	    { -	      this->stage = 2; -	      return 0; -	    }  	} -       -      /* If stage 1 was not completed. */ -       -      /* Figure out how much space we have left in the read buffer. */ -      n = this->buffer_size - this->buffer_ptr; -       -      /* If we do not have too much left, */ -      if (n < 128) +      if ((this->stage == 1) && (this->payload_ptr == this->payload_size))  	{ -	  /* grow the buffer, */ -	  try (mds_message_extend_buffer(this)); -	   -	  /* and recalculate how much space we have left. */ -	  n = this->buffer_size - this->buffer_ptr; +	  /* If we have filled the payload (or there was no payload), +	     mark the end of this stage, i.e. that the message is +	     complete, and return with success. */ +	  this->stage = 2; +	  return 0;  	} -      /* Then read from the socket. */ -      errno = 0; -      got = recv(fd, this->buffer + this->buffer_ptr, n, 0); -      this->buffer_ptr += (size_t)(got < 0 ? 0 : got); -      if (errno) -	return -1; -      if (got == 0) -	{ -	  errno = ECONNRESET; -	  return -1; -	} +       +      /* If stage 1 was not completed. */ +       +      /* Continue reading from the socket into the buffer. */ +      try (continue_read(this, fd));      } -   -#undef try  } @@ -501,23 +515,19 @@ int mds_message_unmarshal(mds_message_t* restrict this, char* restrict data)    /* Allocate header list, payload and read buffer. */    if (header_count > 0) -    if (xmalloc(this->headers, header_count, char*)) -      return -1; +    fail_if (xmalloc(this->headers, header_count, char*));    if (this->payload_size > 0) -    if (xmalloc(this->payload, this->payload_size, char)) -      return -1; +    fail_if (xmalloc(this->payload, this->payload_size, char)); -  if (xmalloc(this->buffer, this->buffer_size, char)) -    return -1; +  fail_if (xmalloc(this->buffer, this->buffer_size, char));    /* Fill the header list, payload and read buffer. */    for (i = 0; i < this->header_count; i++)      {        n = strlen(data) + 1; -      if (xmalloc(this->headers[i], n, char)) -	return -1; +      fail_if (xmalloc(this->headers[i], n, char));        memcpy(this->headers[i], data, n * sizeof(char));        buf_next(data, char, n);        this->header_count++; @@ -529,6 +539,9 @@ int mds_message_unmarshal(mds_message_t* restrict this, char* restrict data)    memcpy(this->buffer, data, this->buffer_ptr * sizeof(char));    return 0; +   + pfail: +  return -1;  } @@ -572,3 +585,6 @@ void mds_message_compose(const mds_message_t* restrict this, char* restrict data      memcpy(data, this->payload, this->payload_size * sizeof(char));  } +   +#undef try + | 
