Files @ da79b5082151
Branch filter:

Location: DistRen/src/common/protocol.c

binki
Extend the distren CLI a little bit more and specify some more of the protocol so that the client can be further worked on while cleaning up nonfunctional distrend.
/*
  Copyright 2010 Nathan Phillip Brink

  This file is a part of DistRen.

  DistRen is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  DistRen 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 Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with DistRen.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "common/config.h"

#include "common/protocol.h"
#include "common/remoteio.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DISTREN_REQUEST_MAGIC ((uint32_t)0x32423434)

int distren_request_new(struct distren_request **req, uint32_t len, enum distren_request_type type)
{
  struct distren_request *newreq;

  newreq = malloc(sizeof(struct distren_request));
  if(!newreq)
    {
      (*req) = NULL;
      return 1;
    }

  newreq->magic = DISTREN_REQUEST_MAGIC;
  newreq->len = len;
  newreq->type = type;

  (*req) = newreq;
  return 0;
}

int distren_request_send(struct remoteio *rem, struct distren_request *req, void *data)
{
  void *packet;
  size_t len;
  int write_err;

  if(req->magic != DISTREN_REQUEST_MAGIC)
    fprintf(stderr, "distren_request_send got a bad req\n");

  len = sizeof(struct distren_request) + req->len;

  packet = malloc(len);
  if(!packet)
    {
      fprintf(stderr, "Error allocating memory for packet\n");
      return 1;
    }
  memcpy(packet, req, sizeof(struct distren_request));
  memcpy(packet + sizeof(struct distren_request), data, req->len);

  write_err = remoteio_write(rem, packet, len);

  free(packet);

  return 0;
}

int distren_request_new_fromdata(struct distren_request **req, void *data, size_t len)
{
  struct distren_request *newreq;

#if 0
  size_t counter;
  uint32_t debugtmp;
#endif

  if(len < sizeof(struct distren_request))
    return 1;

  if( ((struct distren_request *)data)->magic != DISTREN_REQUEST_MAGIC )
    {
      fprintf(stderr, "packet doesn't match magic stuffs");
#if 0
      fputs("\n\tmagic=`", stderr);
      debugtmp = DISTREN_REQUEST_MAGIC;
      for(counter = 0; counter < sizeof(uint32_t); counter ++)
	putc(((char *)&debugtmp)[counter], stderr);
      fputs("'\n\t`", stderr);
      for(counter = 0; counter < sizeof(struct distren_request); counter ++)
	putc(((char *)data)[counter], stderr);
      fputs("'\n", stderr);
#endif
      return 1;
    }

  newreq = malloc(sizeof(struct distren_request));
  if(!newreq)
    {
      fprintf(stderr, "OOM\n");
      return 1;
    }

  memcpy(newreq, data, sizeof(struct distren_request));
  (*req) = newreq;
  return 0;
}

size_t distren_request_handle(size_t *expectlen,
			      void *buf,
			      size_t len,
			      struct distren_request **req,
			      void **req_data,
			      short *err)
{
  size_t dead_expectlen;

  *err = 0;
  *req = NULL;

  if(!expectlen)
    {
      dead_expectlen = 0;
      expectlen = &dead_expectlen;
    }

  if(!*expectlen)
    {
      if(len < sizeof(struct distren_request))
	return 0;

      if(distren_request_new_fromdata(req, buf, len))
	{
	  fprintf(stderr, "Error trying to handle packet\n");
	  *err = 1;
	  return 0;
	}

      *expectlen = sizeof(struct distren_request) + (*req)->len;
    }

  if(!*expectlen
     || len < *expectlen)
    {
      if(*req)
	{
	  distren_request_free(*req);
	  *req = NULL;
	}

      return 0;
    }

  if(!*req)
    distren_request_new_fromdata(req, buf, len);
  *req_data = buf + sizeof(struct distren_request);

  return sizeof(struct distren_request) + (*req)->len;
}

int distren_request_free(struct distren_request *req)
{
  free(req);
  return 0;
}