./ MultiCS.r82 / msg-newcamd.c
#include "common.h"

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>

#ifdef WIN32

#include <windows.h>
#include <sys/types.h>
#include <sys/_default_fcntl.h>
#include <sys/poll.h>
#include <cygwin/types.h>
#include <cygwin/socket.h>
#include <sys/errno.h>
#include <cygwin/in.h>
#include <sched.h>
#include <netdb.h>
#include <netinet/tcp.h>

#else

#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <netdb.h> 
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <poll.h>

#endif

#include "des.h"
#include "debug.h"
#include "sockets.h"
#include "msg-newcamd.h"

int cs_message_send(int sock,struct cs_custom_data *cd, unsigned char *buffer, int len, unsigned char *deskey)
{
	unsigned char netbuf[CWS_NETMSGSIZE];

	if (sock==INVALID_SOCKET) return 0;

	if (!len) len = 0x0fff & ( (buffer[1]<<8)|buffer[2] );
	else {
		buffer[1] = (buffer[1] & 0xf0) | (((len - 3) >> 8) & 0x0f);
		buffer[2] = (len - 3) & 0xff;
	}

	if (len < 3 || len + 12 > CWS_NETMSGSIZE) return -1;

	//NetBuf Header

	memset(netbuf, 0, 12);
	if (cd) {
		netbuf[2] = (cd->msgid >> 8) & 0xff; 
		netbuf[3] = cd->msgid & 0xff;
		netbuf[4] = (cd->sid >> 8) & 0xff;
		netbuf[5] = cd->sid & 0xff;
		netbuf[6] = (cd->caid >> 8) & 0xff;
		netbuf[7] = cd->caid & 0xff;
		netbuf[8] = (cd->provid >> 16) & 0xff;
		netbuf[9] = (cd->provid >> 8) & 0xff;
		netbuf[10] = cd->provid & 0xff;
		netbuf[11] = (cd->provid >> 24) & 0xff; // used for mgcamd
	}
	memcpy(netbuf+12, buffer, len);
	// adding packet header size
	len += 12;

	//debugdump(netbuf,len,"SEND BUF ");
#ifdef DEBUG_NETWORK
	if (flag_debugnet) {
		debugf(0," newcamd: send data %d\n",len);
		debughex(netbuf,len);
	}
#endif
	len=des_encrypt(netbuf, len, deskey);

	if (len < 0) return -1;
	netbuf[0] = (len - 2) >> 8;
	netbuf[1] = (len - 2) & 0xff;

	return send_nonb(sock, netbuf, len,100);
}


// -2: timeout
// -1: Error
// =0: disconnect
// >0: ok
int cs_message_receive(int sock,struct cs_custom_data *cd, unsigned char *buffer, unsigned char *deskey, int timeout)
{
  int len;
  unsigned char netbuf[CWS_NETMSGSIZE];
  int returnLen;

  if (sock<=0) {
	//printf("newcamd: Invalid Socket\n");
	return -1;
  }

	len = recv_nonb(sock, netbuf, 2, timeout);

  if (len<=0) {
	//printf("newcamd: first recive error (%d)\n",errno);
	return len; // disconnected
  }
  if (len != 2) {
	//printf("newcamd: header length error (%d)\n",len);
	return -1;
  }
  if (((netbuf[0] << 8) | netbuf[1]) > CWS_NETMSGSIZE - 2) {
	//printf("newcamd: big message size (%d)\n", (netbuf[0] << 8) | netbuf[1] );
	return -1;
  }
  int netlen = (netbuf[0] << 8) | netbuf[1];

  // TEST LENGTH
  if (netlen>(CWS_NETMSGSIZE-2)) return -1;

	len = recv_nonb(sock, netbuf+2, netlen, timeout);

  if (len<=0) {
	//printf("newcamd: recive error\n");
	return len; // disconnected
  }
  if (len!=netlen) {
	//printf("newcamd: data length error\n");
	return -1;
  }
  len += 2;

  len= des_decrypt(netbuf, len, deskey);

  if (len < 15) {
	//printf("newcamd: Error des_decrypt length %d\n",len);
    //debug_dump(netbuf, len, "netbuf:");
	return -2;
  }

  if ( (returnLen = (((netbuf[13] & 0x0f) << 8) | netbuf[14]) + 3)  > len-12) {
	//printf("newcamd: wrong data length\n");
	return -1;
  }

  //debugdump(netbuf,returnLen+12,"RECV BUF ");
#ifdef DEBUG_NETWORK
	if (flag_debugnet) {
		debugf(0," newcamd: receive data %d\n",returnLen+12);
		debughex(netbuf,returnLen+12);
	}
#endif
	// Setup Custom Data
	if (cd) {
		cd->msgid = (netbuf[2] << 8) | netbuf[3];
		cd->sid = (netbuf[4] << 8) | netbuf[5];
		cd->caid = (netbuf[6] << 8) | netbuf[7];
		cd->provid = (netbuf[8] << 16) | (netbuf[9] << 8) | netbuf[10];
	}
  memcpy(buffer, netbuf+12, returnLen);
  return returnLen;
}


// -1: not yet
// 0: disconnect
// >0: ok
int cs_msg_chkrecv(int sock)
{
	int len;
	unsigned char netbuf[CWS_NETMSGSIZE];

	len = recv(sock, netbuf, 2, MSG_PEEK|MSG_NOSIGNAL|MSG_DONTWAIT);

	if (len==0) return 0;
	if (len!=2) return -1;

	int datasize = (netbuf[0] << 8) | netbuf[1];
	if ( datasize > CWS_NETMSGSIZE-2) return 0;

	len = recv(sock, netbuf, 2+datasize, MSG_PEEK|MSG_NOSIGNAL|MSG_DONTWAIT);

	if (len!=2+datasize) return -1;

	return len;
}


// -1: not yet
// 0: disconnect
// >0: ok
int cs_peekmsg( int handle, struct message_data *msg, uint8_t *sessionkey,struct cs_custom_data *cd, unsigned char *buffer)
{
	int len;
	if (msg->len<=0) {
		len = recv( handle, msg->data, 2, MSG_NOSIGNAL|MSG_DONTWAIT);
		if (len==0) return 0;
		if (len==-1) {
			if ( (errno==EINTR)||(errno==EWOULDBLOCK)||(errno==EAGAIN) ) return -1; 
			else return 0;
		}
		if (len>0) msg->len = len;
	}
	else if (msg->len==1) {
		len = recv( handle, msg->data+1, 1, MSG_NOSIGNAL|MSG_DONTWAIT);
		if (len==0) return 0;
		if (len==-1) {
			if ( (errno == EINTR)||(errno==EWOULDBLOCK)||(errno==EAGAIN) ) return -1; 
			else return 0;
		}
		if (len>0) msg->len +=len;
	}
	if (msg->len<2) return -1;
	// GOOD
	int datasize = 2 + ( (msg->data[0] << 8) | msg->data[1] );
	if ( datasize > CWS_NETMSGSIZE ) return 0;
	//
	if (datasize > msg->len) {
		len = recv( handle, msg->data+msg->len, datasize-msg->len, MSG_NOSIGNAL|MSG_DONTWAIT);
		//printf(" lennn = %d\n", len);
		if (len==0) return 0;
		if (len==-1) {
			if ( (errno==EINTR)||(errno==EWOULDBLOCK)||(errno==EAGAIN) ) return -1; 
			else return 0;
		}
		if (len>0) msg->len +=len;
	}
	//printf(" chk msg '%s' (%d) datasize:%d\n", cli->user, msg->len, datasize);
	if (datasize == msg->len) {
		len = des_decrypt( msg->data, msg->len, sessionkey);
		msg->len = 0;
		if (len < 15) return 0;
		int returnLen = (((msg->data[13] & 0x0f) << 8 ) | msg->data[14]) + 3;
		if ( returnLen > (len-12) ) return 0;
		// Setup Custom Data
		if (cd) {
			cd->msgid = (msg->data[2] << 8) | msg->data[3];
			cd->sid = (msg->data[4] << 8) | msg->data[5];
			cd->caid = (msg->data[6] << 8) | msg->data[7];
			cd->provid = (msg->data[8] << 16) | (msg->data[9] << 8) | msg->data[10];
		}
		memcpy(buffer, msg->data+12, returnLen);
		return returnLen;
	}
	return -1;
}