/** Sends or receives a string to or from the current network package.
 *  \param str    When encoding a packet this is the (NUL-terminated string to
 *                be sent in the current network package. When decoding this
 *                is the buffer to decode the string from the network package
 *                into. When decoding this string is guaranteed to be
 *                NUL-terminated provided that this buffer is at least 1 byte
 *                large.
 *  \param maxlen The buffer size of \c str. For static buffers this means
 *                sizeof(\c str), for dynamically allocated buffers this is
 *                whatever number you passed to malloc().
 *  \note If while decoding \c maxlen is smaller than the actual length of the
 *        string being decoded, the resulting string (in \c str) will be
 *        truncated.
 */
BOOL NETstring(char *str, uint16_t maxlen)
{
	/*
	 * Strings sent over the network are prefixed with their length, sent as an
	 * unsigned 16-bit integer.
	 */

	// Work out the length of the string if we are encoding
	uint16_t len = (NETgetPacketDir() == PACKET_ENCODE) ? strnlen1(str, maxlen) : 0;
	char *store;

	// Add/fetch the length from the packet
	NETuint16_t(&len);

	// Map store to the message buffer
	store = (char *) &NetMsg.body[NetMsg.size];

	// Make sure there is enough data/space left in the packet
	if (len + NetMsg.size > sizeof(NetMsg.body) || !NetMsg.status)
	{
		return NetMsg.status = false;
	}

	if (NETgetPacketDir() == PACKET_ENCODE)
	{
		memcpy(store, str, len);
	}
	else if (NETgetPacketDir() == PACKET_DECODE)
	{
		// Truncate length if necessary
		if (len > maxlen)
		{
			debug(LOG_ERROR, "NETstring: Decoding packet type %d from %d, buffer size %u truncated at %u", 
			      NetMsg.type, NetMsg.source, len, maxlen);
			len = maxlen;
		}
		memcpy(str, store, len);
		// Guarantee NUL-termination
		str[len - 1] = '\0';
	}

	// Increment the size of the message
	NetMsg.size += sizeof(len) + len;

	return true;
}
Exemple #2
0
size_t
mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps)
{
  if (ps == NULL)
    ps = &_gl_mbsrtowcs_state;
  {
    const char *src = *srcp;

    if (dest != NULL)
      {
        wchar_t *destptr = dest;

        for (; len > 0; destptr++, len--)
          {
            size_t src_avail;
            size_t ret;

            /* An optimized variant of
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
            if (src[0] == '\0')
              src_avail = 1;
            else if (src[1] == '\0')
              src_avail = 2;
            else if (src[2] == '\0')
              src_avail = 3;
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
              src_avail = 4;
            else
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);

            /* Parse the next multibyte character.  */
            ret = mbrtowc (destptr, src, src_avail, ps);

            if (ret == (size_t)(-2))
              /* Encountered a multibyte character that extends past a '\0' byte
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
              abort ();

            if (ret == (size_t)(-1))
              goto bad_input;
            if (ret == 0)
              {
                src = NULL;
                /* Here mbsinit (ps).  */
                break;
              }
            src += ret;
          }

        *srcp = src;
        return destptr - dest;
      }
    else
      {
        /* Ignore dest and len, don't store *srcp at the end, and
           don't clobber *ps.  */
        mbstate_t state = *ps;
        size_t totalcount = 0;

        for (;; totalcount++)
          {
            size_t src_avail;
            size_t ret;

            /* An optimized variant of
               src_avail = strnlen1 (src, MB_LEN_MAX);  */
            if (src[0] == '\0')
              src_avail = 1;
            else if (src[1] == '\0')
              src_avail = 2;
            else if (src[2] == '\0')
              src_avail = 3;
            else if (MB_LEN_MAX <= 4 || src[3] == '\0')
              src_avail = 4;
            else
              src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4);

            /* Parse the next multibyte character.  */
            ret = mbrtowc (NULL, src, src_avail, &state);

            if (ret == (size_t)(-2))
              /* Encountered a multibyte character that extends past a '\0' byte
                 or that is longer than MB_LEN_MAX bytes.  Cannot happen.  */
              abort ();

            if (ret == (size_t)(-1))
              goto bad_input2;
            if (ret == 0)
              {
                /* Here mbsinit (&state).  */
                break;
              }
            src += ret;
          }

        return totalcount;
      }

   bad_input:
    *srcp = src;
   bad_input2:
    errno = EILSEQ;
    return (size_t)(-1);
  }
}