int sockets[10] ;
string names[10] ;

void socket_connected(int handle; int new)
{
  int n ;

  define_socket_to_text(new, "\0d\0a", 2, 1) ;
  for (n=0; sockets[n] >= 0 && n < 10; n=n+1 ;)  ;
  if (n < 10)
  {
    sockets[n]=new ;
    names[n]="" ;
    line_to_socket(new, "Welcome to the RabbitScript talker, please enter a nickname.\0d\0a") ;
  }
  else
  {
    line_to_socket(new, "The maximum number of concurrent users has been reached, please try again later\0d\0a") ;
    close_socket(new) ;
  }
}

void relay_line(string line)
{
  int n ;

  for (n=0; n < 10; n=n+1 ;)
  {
    if (sockets[n] >= 0 && string_len(names[n]) > 0)
    {
      line_to_socket(sockets[n], line) ;
      line_to_socket(sockets[n], "\0d\0a") ;
    }
  }
}

/* contrary to relay_line, this also relays to not yet logged on connections */
void relay_line_all(string line)
{
  int n ;

  for (n=0; n < 10; n=n+1 ;)
  {
    if (sockets[n] >= 0)
    {
      line_to_socket(sockets[n], line) ;
      line_to_socket(sockets[n], "\0d\0a") ;
    }
  }
}

int pre_quit()
{
  relay_line_all("Talker dying") ;
  return 0 ;
}

void line_from_socket(int handle; string line)
{
  int n ;

  if (string_len(line))
  {
    for (n=0; sockets[n] != handle; n=n+1 ;) n=n ;
    if (string_len(names[n]) = 0)
    {
      int test ;

      string_trunc(line, 10) ;
      for (test=0; test < 10; test=test+1 ;)
      {
        if (string_compare(line, names[test]))
        {
          line_to_socket(handle, "The nickname is already in use, please choose another.\0d\0a") ;
          return ;
        }
      }
      names[n]=line ;

      string send ;

      send="" ;
      string_cat(send, line) ;
      string_cat(send, " has connected") ;
      relay_line(send) ;
    }
    else
    {
      switch (string_char(line, 0))
      {
        case '.': {
                    int command ;

                    line=mid_string(line, 1) ;
                    command=search_for_tag("quit help who", line) ;
                    switch (command)
                    {
                      case 0: {
                                string send ;
                                close_socket(handle) ;
                                sockets[n]=-1 ;
                                send=names[n] ;
                                string_cat(send, " has disconnected (quit)") ;
                                names[n]="" ;
                                relay_line(send) ;
                              }
                      case 1: {
                                line_to_socket(handle, "This is only an experimental talker, the only command other than .help is .quit. Precede a line with ';' to emote.\0d\0a") ;
                              }
                      case 2: {
                                int n ;

                                for (n=0; n < 10; n=n+1 ;)
                                {
                                  if (sockets[n] >= 0)
                                  {
                                    if (string_len(names[n]) > 0)
                                    {
                                      line_to_socket(handle, names[n]) ;
                                      line_to_socket(handle, "\0d\0a") ;
                                    }
                                    else
                                    {
                                      line_to_socket(handle, "*Connecting*\0d\0a") ;
                                    }
                                  }
                                }
                              }
                      default: {
                                 string send ;

                                 send="No such command '" ;
                                 string_cat(send, /*line*/int_to_string(string_len(line))) ;
                                 string_cat(send, "'\0d\0a") ;
                                 line_to_socket(handle, send) ;
                               }
                    }
                  }
        case ';': {
                    string send ;
                    send=names[n] ;
                    string_cat(send, " ") ;
                    string_cat(send, mid_string(line, 1)) ;
                    relay_line(send) ;
                  }
        default: {
                   string send ;

                   send="" ;
                   string_cat(send, names[n]) ;
                   string_cat(send, ": ") ;
                   string_cat(send, line) ;
                   relay_line(send) ;
                 }
      }
    }
  }
}

void socket_closed(int handle)
{
  int n ;
  string send ;

  for (n=0; sockets[n] != handle; n=n+1 ;) n=n ;
  sockets[n]=-1 ;
  send=names[n] ;
  string_cat(send, " has disconnected (socket closed)") ;
  relay_line(send) ;
  names[n]="" ;
}

void main()
{
  init("Talker", "Simple talker", "Sham Gardner", "0.00 (December 1997)", 0) ;

  int port, socket ;
  port=1234 ;
  socket=create_listening_socket(port) ;
  if (socket < 0)
  {
    report_error("Unable to bind port 1234, is something else using it?") ;
    quit() ;
  }

  int n ;
  for (n=0; n < 10; n=n+1 ;)
  {
    if (n=10)
    {
      report_error("wibble") ;
    }
    sockets[n]= -1 ;
  }
}
