/* Anonymous Town Hall Email Network System */
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <dirent.h>

#include <sys/socket.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <rand.h>
#include <sha.h>

#include "libpgp5.h"
#include "athens.h"

/*--------------------------------------------------*/
/* PK ID of next host in ring (to send packet to) */
static unsigned char msg[MAXUDP];
static int msglen;

#undef DIRECAST

#ifdef DIRECAST
/*--------------------------------------------------*/
void broadcast()
{
  int sockfd, cl, lcl;
  struct sockaddr_in remote_addr;
  struct ip_mreq mreq;

  /* Setup communications */
  cl = sizeof(remote_addr);
  memset(&remote_addr, 0, cl);
  remote_addr.sin_family = AF_INET;

  remote_addr.sin_port = htons(0);
  remote_addr.sin_addr.s_addr = INADDR_ANY;

  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  mreq.imr_multiaddr.s_addr = lcl;
  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
  lcl = -1;                     /* unrestricted */
  setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &lcl, 1);
  bind(sockfd, (struct sockaddr *) &remote_addr, cl);
  remote_addr.sin_port = htons(ATHENSPORT);
  lcl = inet_addr(ATHENSIP);
  memcpy(&remote_addr.sin_addr, &lcl, sizeof(lcl));
  sendto(sockfd, msg, msglen, 0, (struct sockaddr *) &remote_addr, cl);
}

#endif

/*--------------------------------------------------*/
int main(int argc, char *argv[])
{
  FILE *fp;
  unsigned char outckey[40], *bp;
  int len, n, mlen;
  unsigned long long keyid[16];

  /* create a random conventional key */
  outckey[0] = CPKE;
  outckey[1] = CYPHER;
  RAND_bytes(&outckey[2], 32);
  cfbinit(&outckey[2], &outckey[18], outckey[1]);
  for (len = 0, n = 0; len < 26; len++)
    n += outckey[len];
  outckey[26] = n & 0xff;
  /* pick second key on active list */
  if (NULL == (fp = fopen(RINGFILE, "rb")))
    return -1;
  n = 0;
  while (n < 16 && !feof(fp)) {
    len = fscanf(fp, "%*x %qx %*s %*d\n", &keyid[n]);
    if (len <= 0)
      break;
    n++;
  }
  fclose(fp);
  if (n < QUORUM)
    return -1;

  /* encrypt conventional key */
  setkeyring5("./pubring.pkr");
  len = encpke(keyid[outckey[30] % n], &msg[3], outckey, 27, 0x10);

  msg[0] = MESSAGE;
  msg[1] = len / 256;
  msg[2] = len & 255;
  bp = msg;
  bp += 3 + len;

  fp = fopen(argv[1], "rb");
  mlen = fread(&bp[2], 1, DSIZE, fp);
  fclose(fp);

  bp[0] = mlen / 256;
  bp[1] = mlen & 255;
  docfb(bp, DSIZE, 1);

  msglen = len + DSIZE + 3;

  /* and about 3375 bytes of junk */
#ifdef DIRECAST
  broadcast();
#else
  {
    unsigned char nexthtmp[80];

    sprintf(nexthtmp, "INBOX.%d", getpid());
    fp = fopen(nexthtmp, "wb");
    fwrite(msg, 1, msglen, fp);
    fclose(fp);
  }
#endif
  exit(0);
}
