//
// tcp_server.c
//

#include <stdio.h>
#include <iostream.h>
#include <memory.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <thread.h>

#define SERV_TCP_PORT  18934

FILE *fd;
extern int errno;

void * thread_inc(void *)
{ 
  long clk;

  while (1) {
    clk = time((long *) 0);
    cerr << ctime((const long *) &clk);
    sleep(10);
  }

  return (void *)0;
}

main(int argc, char *argv[])
{
  int  sockfd, newsockfd, clilen, cnt;
  struct sockaddr_in  cli_addr, serv_addr;
  char buffer[1024];
  int  msg_len, cli_len;
  int  price;
  long clk;
  char reply_1[512], reply_2[512], my_msg[512];
  unsigned long t1;

  if (thr_create (NULL, 0, thread_inc, 0, 0, (thread_t *)&t1) != 0) {
    cerr << "thread: creation failed" << endl;
    exit(-1);
  }

  // 
  // open a TCP socket
  // 
  if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    cerr << "server: can't open stream socket" << endl;
    exit(1);
  }

  fd = fopen("socket.trace", "a");

  memset((char *) &serv_addr, '\0', sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  serv_addr.sin_port = htons(SERV_TCP_PORT);

  if ((errno = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))) < 0) {
    if (errno == EADDRINUSE)
      cerr << "The specified address is already in use..." << endl;
    else
      cerr << "server can't bind local address [" << errno << "] ???" << endl;
    exit(-1);
  }

  listen(sockfd, 5);  
  // cerr << "I am here to listen on the Welcome Socket..." << endl;

  clilen = sizeof(cli_addr);
    
  char proj[128], conn_id[128], name[128], stock[128];

  for (;;) {
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

    if (newsockfd < 0) {
      cerr << "server: accept() error" << endl;
      exit(1);
    }

    cli_len = sizeof(struct sockaddr_in);
    errno = getpeername(newsockfd, (sockaddr *) &cli_addr, &cli_len);
    // cerr << "port # " << cli_addr.sin_port << endl;
    // cerr << "IP addr " << ((cli_addr.sin_addr.s_addr & (255 << 24)) >> 24) << endl;
    // cerr << "IP addr " << ((cli_addr.sin_addr.s_addr & (255 << 16)) >> 16) << endl;
    // cerr << "IP addr " << ((cli_addr.sin_addr.s_addr & (255 << 8)) >> 8) << endl;
    // cerr << "IP addr " << (cli_addr.sin_addr.s_addr & 255) << endl;
    sprintf(my_msg, "client socket info [%d.%d.%d.%d:%d]\n", 
                    ((cli_addr.sin_addr.s_addr & (255 << 24)) >> 24),
                    ((cli_addr.sin_addr.s_addr & (255 << 16)) >> 16),
                    ((cli_addr.sin_addr.s_addr & (255 << 8)) >> 8),
                    (cli_addr.sin_addr.s_addr & 255),
                    cli_addr.sin_port);

    msg_len = read(newsockfd, buffer, 1024);

    buffer[msg_len] = '\0';
    // printf("msg = <%s> length %d\n", buffer, msg_len);

    sscanf(buffer, "%s %s %s %s\n", proj, conn_id, name, stock);
   
    printf("proj    = [%s]\n", proj);
    printf("conn_id = [%s]\n", conn_id);
    printf("name    = [%s]\n", name);
    printf("stock   = [%s]\n", stock);
    printf("\n");
   
    price = rand() % 99;
    clk = time((long *) 0);

    sprintf(reply_1, "Stock Quote Server -- %s", ctime((const long *) &clk));

    if (strcmp(proj, "proj_1") != 0) 
      sprintf(reply_2, "Hello %s -- illegal project ID [%s]\n", name, proj);
    else
    if (strcmp(stock, "Yahoo") == 0)
      sprintf(reply_2, "Hello %s -- Quote of Yahoo is %d\n", name, price);
    else
    if (strcmp(stock, "eBay") == 0)
      sprintf(reply_2, "Hello %s -- Quote of eBay is %d\n", name, price);
    else
    if (strcmp(stock, "Amazon.com") == 0)
      sprintf(reply_2, "Hello %s -- Quote of Amazon.com is %d\n", name, price);
    else
    if (strcmp(stock, "AOL") == 0)
      { close(newsockfd); cerr << "AOL???" << endl; break; }
    else 
      sprintf(reply_2, "Hello %s -- unknown stock symbol %s\n", name, stock);

    cerr << "==" << reply_1 << "==" << strlen(reply_1) << endl;
    cerr << "==" << reply_2 << "==" << strlen(reply_2) << endl;

    write(newsockfd, reply_1, strlen(reply_1));
    write(newsockfd, reply_2, strlen(reply_2));

    fprintf(fd, "%s", my_msg);
    fprintf(fd, "%s", buffer);
    fprintf(fd, "%s", reply_1);
    fprintf(fd, "%s", reply_2);
    fprintf(fd, "\n");
    
    fflush(fd);

    close(newsockfd);
  }
  
  fclose(fd);
  close(sockfd);
}
