Logo Search packages:      
Sourcecode: sbrsh version File versions  Download package

protocol.c

/*
 * Copyright (c) 2003, 2004, 2005 Nokia
 * Author: tsavola@movial.fi
 *
 * This program is licensed under GPL (see COPYING for details)
 */

#include "protocol.h"
#include "common.h"
#include "mount.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>

#if __BYTE_ORDER == __BIG_ENDIAN
# define htonll(n)  (n)
# define ntohll(n)  (n)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
# define htonll(n)  ((((uint64_t) htonl(n)) << 32LL) | htonl((n) >> 32LL))
# define ntohll(n)  ((((uint64_t) ntohl(n)) << 32LL) | ntohl((n) >> 32LL))
#endif


#if 0

#include <ctype.h>

static FILE *get_log(void)
{
      static FILE *file = NULL;

      if (!file) {
            static char path[PATH_MAX];
            snprintf(path, sizeof (path), "/tmp/protocol.%d", getpid());

            file = fopen(path, "w");
            if (!file)
                  abort();
      }

      return file;
}

static ssize_t my_write(int fd, void *buf, size_t len)
{
      static size_t total = 0;

      ssize_t retval;
      size_t i;
      FILE *file;

      retval = write(fd, buf, len);

      if (retval > 0) {
            total += retval;

            file = get_log();
            fprintf(file, "write fd=%2d total=%6d len=%5d buf=", fd, total, retval);

            for (i = 0; i < retval; ++i)
                  fprintf(file, "%02x", (unsigned int) ((unsigned char *) buf)[i]);

            fprintf(file, "\n");
            fflush(file);
      }

      return retval;
}

static ssize_t my_read(int fd, void *buf, size_t len)
{
      static size_t total = 0;

      ssize_t retval;
      size_t i;
      FILE *file;

      retval = read(fd, buf, len);

      if (retval > 0) {
            total += retval;

            file = get_log();
            fprintf(file, "read  fd=%2d total=%6d len=%5d buf=", fd, total, retval);

            for (i = 0; i < retval; ++i)
                  fprintf(file, "%02x", (unsigned int) ((unsigned char *) buf)[i]);

            fprintf(file, "\n");
            fflush(file);
      }

      return retval;
}

#define write my_write
#define read  my_read

#endif


uint16v_t *uint16v_alloc(uint32_t len)
{
      char *mem = malloc(sizeof (uint16v_t) + len * sizeof (uint16_t));
      uint16v_t *ints = (uint16v_t *) mem;
      if (ints) {
            ints->len = len;
            ints->vec = (uint16_t *) (mem + sizeof (uint16v_t));
      }
      return ints;
}

void uint16v_free(uint16v_t *ints)
{
      free(ints);
}

/**
 * Same as read(2) but retries on EINTR.
 */
ssize_t read_ni(int fd, void *buf, size_t len)
{
      ssize_t retval;
      do {
            retval = read(fd, buf, len);
      } while (retval < 0 && errno == EINTR);
      return retval;
}

/**
 * Same as write(2) but retries on EINTR.
 */
ssize_t write_ni(int fd, void *buf, size_t len)
{
      ssize_t retval;
      do {
            retval = write(fd, buf, len);
      } while (retval < 0 && errno == EINTR);
      return retval;
}

int write_uint16(int fd, uint16_t i)
{
      uint16_t data = htons(i);
      return write_buf(fd, &data, sizeof (data));
}

int write_uint32(int fd, uint32_t i)
{
      uint32_t data = htonl(i);
      return write_buf(fd, &data, sizeof (data));
}

int write_uint64(int fd, uint64_t i)
{
      uint64_t data = htonll(i);
      return write_buf(fd, &data, sizeof (data));
}

int write_uint16v(int fd, uint16v_t *ints)
{
      if (write_uint32(fd, ints->len) < 0)
            return -1;

      if (ints) {
            int i;
            for (i = 0; i < ints->len; ++i)
                  if (write_uint16(fd, ints->vec[i]) < 0)
                        return -1;
      }

      return 0;
}

/**
 * Writes a string into a file.
 * @param fd the file descriptor
 * @param str the null-terminated string
 * @return 0 on success, -1 on error
 */
int write_str(int fd, const char *str)
{
      uint32_t len;

      if (!str)
            str = "";

      len = strlen(str);

      if (write_uint32(fd, len) < 0 || write_buf(fd, (void *) str, len) < 0)
            return -1;
      return 0;
}

/**
 * Writes a string vector into a file.
 * @param fd the file descriptor
 * @param strv the string vector
 * @return 0 on success, -1 on error
 */
int write_strv(int fd, char **strv)
{
      if (write_uint32(fd, calc_vec_len((void **) strv)) < 0)
            return -1;

      if (strv) {
            char **s;
            for (s = strv; *s; ++s)
                  if (write_str(fd, *s) < 0)
                        return -1;
      }

      return 0;
}

int write_mount(int fd, const mount_info_t *mi)
{
      if (write_enum  (fd, mi->type      ) < 0 || write_str(fd, mi->point) < 0 ||
          write_str   (fd, mi->device    ) < 0 || write_str(fd, mi->opts ) < 0 ||
          write_uint64(fd, mi->device_dev))
            return -1;
      return 0;
}

int write_mountv(int fd, mount_info_t **mounts)
{
      if (write_uint32(fd, calc_vec_len((void **) mounts)) < 0)
            return -1;

      if (mounts) {
            mount_info_t **p;
            for (p = mounts; *p; ++p)
                  if (write_mount(fd, *p) < 0)
                        return -1;
      }

      return 0;
}

int write_buf(int fd, void *buf, size_t len)
{
      ssize_t i, cnt;

      for (i = 0; i < len; i += cnt) {
            cnt = write(fd, buf + i, len - i);
            if (cnt < 0) {
                  if (errno == EAGAIN || errno == EINTR) {
                        cnt = 0;
                        continue;
                  }

                  return -1;
            }
      }

      return 0;
}

/**
 * Reads a complete buffer from a file.  errno will be set to EIO at EOF.
 * @param fd a file descriptor
 * @param buf pointer to a buffer large enough
 * @param len the length of the buffer
 * @return 0 on success, -1 on i/o error
 */
int read_buf(int fd, void *buf, size_t len)
{
      ssize_t i, cnt;

      for (i = 0; i < len; i += cnt) {
            cnt = read(fd, buf + i, len - i);
            if (cnt < 0) {
                  if (errno == EAGAIN || errno == EINTR) {
                        cnt = 0;
                        continue;
                  }

                  return -1;
            }

            if (cnt == 0) {
                  errno = EIO;
                  return -1;
            }
      }

      return 0;
}

int read_uint16(int fd, uint16_t *iptr)
{
      uint16_t data;
      if (read_buf(fd, &data, sizeof (data)) < 0)
            return -1;
      *iptr = ntohs(data);
      return 0;
}

int read_uint32(int fd, uint32_t *iptr)
{
      uint32_t data;
      if (read_buf(fd, &data, sizeof (data)) < 0)
            return -1;
      *iptr = ntohl(data);
      return 0;
}

int read_uint64(int fd, uint64_t *iptr)
{
      uint64_t data;
      if (read_buf(fd, &data, sizeof (data)) < 0)
            return -1;
      *iptr = ntohll(data);
      return 0;
}

uint16v_t *read_uint16v(int fd)
{
      uint32_t len, i;
      uint16v_t *ints;

      if (read_uint32(fd, &len) < 0)
            return NULL;

      ints = uint16v_alloc(len);
      if (!ints)
            return NULL;

      for (i = 0; i < len; ++i)
            if (read_uint16(fd, &ints->vec[i]) < 0) {
                  uint16v_free(ints);
                  return NULL;
            }

      return ints;
}

/**
 * Reads a string from a file. The returned string should be free()'d.
 * @param fd a file descriptor
 * @return NULL on error
 */
char *read_str(int fd)
{
      uint32_t len;
      char *str;

      if (read_uint32(fd, &len) < 0)
            return NULL;

      str = calloc(len + 1, 1);
      if (!str)
            return NULL;

      if (read_buf(fd, str, len) < 0) {
            free(str);
            return NULL;
      }
      return str;
}

/**
 * Reads a string vector from a file. The returned strings and the vector
 * should be set free(). The vector is null-terminated.
 * @param fd a file descriptor
 * @return NULL on error
 */
char **read_strv(int fd)
{
      uint32_t len, i;
      char **strv;

      if (read_uint32(fd, &len) < 0)
            return NULL;

      strv = calloc(len + 1, sizeof (char *));
      if (!strv)
            return NULL;

      for (i = 0; i < len; ++i) {
            strv[i] = read_str(fd);
            if (!strv[i]) {
                  free_vec((void **) strv, NULL);
                  return NULL;
            }
      }

      return strv;
}

mount_info_t *read_mount(int fd)
{
      mount_info_t *mi;

      mi = mntinfo_alloc();
      if (!mi)
            return NULL;

      if ((mi->type   = read_enum(fd)) >= 0 &&
          (mi->point  = read_str(fd)) &&
          (mi->device = read_str(fd)) &&
          (mi->opts   = read_str(fd)) &&
          read_uint64(fd, &mi->device_dev) >= 0)
            return mi;

      mntinfo_free(mi);
      return NULL;
}

mount_info_t **read_mountv(int fd)
{
      uint32_t len, i;
      mount_info_t **mounts;

      if (read_uint32(fd, &len) < 0)
            return NULL;

      mounts = calloc(len + 1, sizeof (mount_info_t *));
      if (!mounts)
            return NULL;

      for (i = 0; i < len; ++i) {
            mounts[i] = read_mount(fd);
            if (!mounts[i]) {
                  free_vec((void **) mounts, (free_func_t *) mntinfo_free);
                  return NULL;
            }
      }

      return mounts;
}

int write_winsize(int fd, const struct winsize *ws)
{
      if (write_uint16(fd, ws->ws_row   ) < 0 || write_uint16(fd, ws->ws_col   ) < 0 ||
          write_uint16(fd, ws->ws_xpixel) < 0 || write_uint16(fd, ws->ws_ypixel) < 0)
            return -1;
      return 0;
}

struct winsize *read_winsize(int fd)
{
      uint16_t row, col, xpixel, ypixel;
      struct winsize *ws;

      if (read_uint16(fd, &row   ) < 0 || read_uint16(fd, &col   ) < 0 ||
          read_uint16(fd, &xpixel) < 0 || read_uint16(fd, &ypixel) < 0)
            return NULL;

      ws = malloc(sizeof (struct winsize));
      if (!ws)
            return NULL;

      ws->ws_row    = row;
      ws->ws_col    = col;
      ws->ws_xpixel = xpixel;
      ws->ws_ypixel = ypixel;
      return ws;
}

int write_enum(int fd, int type)
{
      return write_uint16(fd, type);
}

int read_enum(int fd)
{
      uint16_t type;
      if (read_uint16(fd, &type) < 0)
            return -1;
      return type;
}

int write_buf_packet(int fd, ptype_t type, size_t size, void *buf)
{
      if (write_enum(fd, type) < 0 || write_uint32(fd, size) < 0 || write_buf(fd, buf, size) < 0)
            return -1;
      return 0;
}

int write_str_packet(int fd, ptype_t type, const char *str)
{
      if (write_enum(fd, type) < 0 || write_str(fd, (char *) str) < 0)
            return -1;
      return 0;
}

int write_uint16_packet(int fd, ptype_t type, uint16_t val)
{
      if (write_enum(fd, type) < 0 || write_uint16(fd, val) < 0)
            return -1;
      return 0;
}

/**
 * Writes the VERSION packet to a file.
 * @param fd a file descriptor
 * @return 0 on success, -1 on i/o error
 */
int send_version(int fd)
{
      if (write_enum(fd, PTYPE_VERSION) < 0 || write_uint16(fd, PROTOCOL_VERSION) < 0)
            return -1;
      return 0;
}

/**
 * Reads the VERSION packet from a file.
 * @param fd a file descriptor
 * @return version on success, -1 on i/o error
 */
int get_version(int fd)
{
      uint16_t ver;
      if (read_enum(fd) != PTYPE_VERSION) {
            errno = 0;
            return -1;
      }
      if (read_uint16(fd, &ver) < 0)
            return -1;
      return ver;
}

Generated by  Doxygen 1.6.0   Back to index