Logo Search packages:      
Sourcecode: fbb version File versions  Download package

fbb_orb.c

   /****************************************************************
    Copyright (C) 1986-2000 by

    F6FBB - Jean-Paul ROUBELAT
    6, rue George Sand
    31120 - Roquettes - France
      jpr@f6fbb.org

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

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Parts of code have been taken from many other softwares.
    Thanks for the help.
    ****************************************************************/

/*
 * Serveur de communication socket pour connection console
 *
 */

#include <serv.h>

#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/if_ether.h>
#include <netinet/in.h>

#include <fbb_orb.h>

#define WAITINFO  0
#define WAITPASS  1
#define CONNECTED 2
#define DISCONNECT      3

extern void process (void);
void orb_services (void);
static void set_opt(char *command, char *value);

/* extern void usleep(unsigned long); */

static int orb_fd = -1;

typedef struct _OrbClient
{
      int fd;
      int state;
      int monitor;
      int channel;
      int options;
      int infos;
      long mask;
      time_t cle;
      char callsign[12];
      struct _OrbClient *next;
}
OrbClient;

static OrbClient *client_head = NULL;

static OrbClient *orb_add_client (void)
{
      OrbClient *sptr;

      sptr = calloc (1, sizeof (OrbClient));
      if (sptr == NULL)
            return (NULL);

      sptr->next = client_head;
      client_head = sptr;

      return (sptr);
}

static void orb_del_client (OrbClient * cptr)
{
      OrbClient *sptr;
      OrbClient *prev;

      prev = NULL;
      sptr = client_head;
      while (sptr)
      {
            if (sptr == cptr)
            {
                  if (prev)
                        prev->next = sptr->next;
                  else
                        client_head = sptr->next;
                  free (sptr);
                  break;
            }
            prev = sptr;
            sptr = sptr->next;
      }
}

static int orb_new_connection (int fd)
{
      int addr_len;
      struct sockaddr_in sock_addr;
      OrbClient *sptr;

      sptr = orb_add_client ();

      addr_len = sizeof (sock_addr);

      sptr->fd = accept (fd, (struct sockaddr *) &sock_addr, &addr_len);
      sptr->state = WAITINFO;

      return (sptr->fd);
}

static int send_data(int sock, char *datafile, char *datarequest, int len, int command)
{
      int fd;
      int nb;
      char buffer[1024];

      printf("sending file %s\n", datafile);
      
      buffer[0] = ORB_DATA;
      buffer[1] = command;

      buffer[2] = len % 256;
      buffer[3] = len >> 8;
      memcpy(buffer+4, datarequest, len);
      write(sock, buffer, len+4);
            
      fd = open(datafile, O_RDONLY);
      if (fd == -1)
      {
            buffer[2] = 0;
            buffer[3] = 0;
            write(sock, buffer, 4);
            return errno;
      }
            
      for (;;)
      {
            nb = read(fd, buffer+4, 1000);
            if (nb < 0)
                  nb = 0;
            buffer[2] = nb % 256;
            buffer[3] = nb >> 8;
            write(sock, buffer, nb+4);
            printf("%d data sent\n", nb);
            if (nb == 0)
                  break;
      }
      
      close(fd);
      unlink(datafile);
            
      return 0;
}

static long flength(char *filename)
{
      struct stat bstat;
      
      if (stat(filename, &bstat) == -1)
            return 0L;

      return bstat.st_size;
}

static int send_data_buf(OrbClient * sptr, int service, char *command, char *data, int datalen)
{
      char buffer[1024];
      int length;

      length = strlen(command);
      strcpy(buffer+4, command);
      if ((length + datalen + 4) > 1024)
            return -1;

      if (datalen)
      {     
            memcpy(buffer+4+length, data, datalen);
            length += datalen;
      }
      
      buffer[0] = ORB_DATA;
      buffer[1] = service;
      buffer[2] = length & 0xff;
      buffer[3] = length >> 8;
      
      write(sptr->fd, buffer, 4+length);
      
      return length;
}

static void orb_process_data (OrbClient * sptr)
{
      int i, j;
      int nb;
      int lg;
      static char buffer[1024];
      static char datafile[256];
      static char datarequest[1024];
      static int nbrcv = 0;
      static int rcv_fd;
      static int rcv_state = 0;
      char call[256];
      char pass[256];
      char *ptr;

      lg = 0;
      
      nb = read (sptr->fd, buffer + nbrcv, sizeof (buffer) - nbrcv);
      if (nb == -1)
            return;

      if (nb == 0)
      {
            editor = 0;
            /* Client is disconnected */
            if (sptr->mask & ORB_CONSOLE)
            {
                  /* Disconnect from console */
                  deconnexion (CONSOLE, 0);
            }
            else
            {
                  close (sptr->fd);
                  orb_del_client (sptr);
            }
            nbrcv = 0;
            return;
      }

      nbrcv += nb;

again:

      if ((nbrcv >= 3) && (buffer[0] == ORB_REQUEST))
      {
            unsigned int len;
            int mask;
            int old_mask = sptr->mask;
            int ack;
            char cmd[300];

            /*commande */
            switch (buffer[1])
            {
            case 0:
                  /* Changement de masque */
                  mask = buffer[2] & 0xff;
                  ack = 0;
                  
                  if ((mask & ORB_CONSOLE) != (sptr->mask & ORB_CONSOLE))
                  {
                        if (mask & ORB_CONSOLE)
                        {
                              FILE *fptr;

                              if ((fptr = fopen (d_disque ("etat.sys"), "r+t")) != NULL)
                              {
                                    fprintf (fptr, "%-6s-%X\n",
                                                 cons_call.call, cons_call.num);
                                    ferme (fptr, 74);
                              }

                              /* Console connection */
                              if (v_tell && connect_tell ())
                              {
                                    music (0);
                                    ack = 1;
                              }
                              else if (!connect_console ())
                              {
                                    ack = 2;
                              }
                              else
                              {
                                    ack = 1;
                              }
                        }
                        else
                        {
                              /* Console deconnection */
                              deconnexion (CONSOLE, 0);
                              ack = 0;
                              nbrcv = 0;
                              return;
                        }
                        buffer[0] = ORB_XFBBX;
                        buffer[1] = 0;
                        buffer[2] = 1;
                        buffer[3] = 0;
                        buffer[4] = ack;
                        write (sptr->fd, buffer, 5);
                  }
                  if (ack != 2)     /* Don't update mask if connection refused */
                  {
                        sptr->mask = mask;
                        if ((mask & ORB_MSGS) != (old_mask & ORB_MSGS))
                        {
                              reset_msgs ();
                              aff_msg_cons ();
                        }
                        if ((mask & ORB_STATUS) != (old_mask & ORB_STATUS))
                        {
                              FbbMem (1);
                              test_pactor(1);
                        }
                        if ((mask & ORB_NBCNX) != (old_mask & ORB_NBCNX))
                              fbb_list (1);
                        if ((mask & ORB_LISTCNX) != (old_mask & ORB_LISTCNX))
                              fbb_list (1);
                  }
                  lg = 3;
                  break;
            case SVC_DIR:
                  /* Dir request */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        int nb;

                        buffer[nbrcv] = '\0';
                        sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                        nb = 1+sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                        sprintf(cmd, "ls -oA %s | awk '{ print substr($1,1,1),$4,$8,$5\"-\"$6\"-\"$7 }' > %s 2>&1", datarequest, datafile);
                        printf("system %s\n", cmd);
                        system(cmd);
                        nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                        send_data(sptr->fd, datafile, datarequest, nb, SVC_DIR);
                  }
                  lg = len+4;
                  break;
            case SVC_RECV:
                  /* File request */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        buffer[nbrcv] = '\0';
                        sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                        nb = 1+sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                        sprintf(cmd, "cp %s %s", datarequest, datafile);
                        printf("system %s\n", cmd);
                        system(cmd);
                        nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                        send_data(sptr->fd, datafile, datarequest, nb, SVC_RECV);
                  }
                  lg = len+4;
                  break;
            case SVC_SEND:
                  /* File receive */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                        
                  if (len <= 1000)
                  {
                        switch (rcv_state)
                        {
                        case 0 :
                              buffer[nbrcv] = '\0';
                              sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                              sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                              printf("receiving file %s\n", datafile);
                              rcv_fd = open(datafile, O_CREAT|O_TRUNC|O_WRONLY, 0666);
                              rcv_state = 1;
                              break;
                        case 1:                       
                              if (len == 0)
                              {
                                    char header[4];
                                    
                                    /* End of file */
                                    if (rcv_fd > 0)
                                    {
                                          close(rcv_fd);
                                          sprintf(cmd, "mv %s %s", datafile, datarequest);
                                          printf("system %s\n", cmd);
                                          system(cmd);
                                          test_fichiers = 1;
                                    }
                                    header[0] = ORB_DATA;
                                    header[1] = SVC_SEND;
                                    header[2] = 0;
                                    header[3] = 0;
                                    write(sptr->fd, header, 4);
                                    rcv_state = 0;
                                    break;
                              }
                              if (rcv_fd > 0)
                              {
                                    nb = write(rcv_fd, buffer+4, len);
                                    printf("%d data received\n", len);
                                    if (nb <= 0)
                                    {
                                          close(rcv_fd);
                                          rcv_fd = -1;
                                    }
                              }
                              break;
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_FWD:
                  /* Pending forward request */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char command[80];
                        char arg[80];
                        
                        buffer[nbrcv] = '\0';

                        sscanf(buffer+4, "%s %s", command, arg);
                        if (strcasecmp(command, "LIST") == 0)
                        {
                              sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                              strcpy(datarequest, "pending_forward.txt");
                              nb = 1+sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                              RequestPendingForward(datafile);
                              nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                              send_data(sptr->fd, datafile, datarequest, nb, SVC_FWD);
                        }
                        else if (strcasecmp(command, "START") == 0)
                        {
                              sprintf(datarequest, "START %s", StartForward(atoi(arg)));
                              send_data_buf(sptr, SVC_FWD, datarequest, NULL, 0);
                        }
                        else if (strcasecmp(command, "STOP") == 0)
                        {
                              sprintf(datarequest, "STOP %s", StopForward(atoi(arg)));
                              send_data_buf(sptr, SVC_FWD, datarequest, NULL, 0);
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_DISC:
                  /* Disconnect request */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char callsign[80];
                        int nChan;
                        int bImm;
                        int nb;

                        buffer[nbrcv] = '\0';
                        nb = sscanf(buffer+4, "%d %s %d", &nChan, callsign, &bImm);
                        if (nb == 3)
                              disconnect_channel(nChan, bImm);
                  }
                  lg = len+4;
                  break;
            case SVC_USER:
                  /* users management */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        int length;
                        char command[80];
                        char arg[80];
                        char *ptr;
                        
                        buffer[nbrcv] = '\0';

                        sscanf(buffer+4, "%s %s", command, arg);
                        if (strcasecmp(command, "LIST") == 0)
                        {
                              sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                              strcpy(datarequest, "service.txt");
                              nb = 1+sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                              RequestUsersList(datafile);
                              nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                              send_data(sptr->fd, datafile, datarequest, nb, SVC_USER);
                        }
                        else if (strcasecmp(command, "GET") == 0)
                        {
                              ptr = GetUserInfo(arg, &length);
                              sprintf(datarequest, "USER %s %d\n", arg, length);
                              send_data_buf(sptr, SVC_USER, datarequest, ptr, length);
                        }
                        else if (strcasecmp(command, "PUT") == 0)
                        {
                              int datalen = len;
                              ptr = buffer+4;
                              while (*ptr && (*ptr != '\n'))
                              {
                                    ++ptr;
                                    --datalen;
                              }
                              if (*ptr == '\n')
                              {
                                    ++ptr;
                                    PutUserInfo(arg, ptr, datalen);
                                    ptr = GetUserInfo(arg, &length);
                                    sprintf(datarequest, "USER %s %d\n", arg, length);
                                    send_data_buf(sptr, SVC_USER, datarequest, ptr, length);
                              }
                        }
                        else if (strcasecmp(command, "NEW") == 0)
                        {
                              NewUserInfo(arg);
                              ptr = GetUserInfo(arg, &length);
                              sprintf(datarequest, "USER %s %d\n", arg, length);
                              send_data_buf(sptr, SVC_USER, datarequest, ptr, length);
                        }
                        else if (strcasecmp(command, "DEL") == 0)
                        {
                              DelUserInfo(arg);
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_MSG:
                  /* messages management */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        int length;
                        char command[80];
                        char arg[80];
                        char *ptr;
                        
                        buffer[nbrcv] = '\0';

                        sscanf(buffer+4, "%s %s", command, arg);
                        if (strcasecmp(command, "LIST") == 0)
                        {
                              sprintf(datafile, "%sclientdata.txt", back2slash(DATADIR));
                              strcpy(datarequest, "service.txt");
                              nb = 1+sprintf(datarequest, "%s%s", back2slash(CONFDIR), buffer+4);
                              RequestMsgsList(datafile);
                              nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                              send_data(sptr->fd, datafile, datarequest, nb, SVC_MSG);
                        }
                        else if (strcasecmp(command, "GET") == 0)
                        {
                              ptr = GetMsgInfo(arg, &length);
                              sprintf(datarequest, "MSG %s %d\n", arg, length);
                              send_data_buf(sptr, SVC_MSG, datarequest, ptr, length);
                        }
                        else if (strcasecmp(command, "PUT") == 0)
                        {
                              int datalen = len;
                              ptr = buffer+4;
                              while (*ptr && (*ptr != '\n'))
                              {
                                    ++ptr;
                                    --datalen;
                              }
                              if (*ptr == '\n')
                              {
                                    ++ptr;
                                    PutMsgInfo(arg, ptr, datalen);
                                    ptr = GetMsgInfo(arg, &length);
                                    sprintf(datarequest, "MSG %s %d\n", arg, length);
                                    send_data_buf(sptr, SVC_MSG, datarequest, ptr, length);
                              }
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_MREQ:
                  /* message request */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char command[80];
                        char arg[80];

                        buffer[nbrcv] = '\0';
                        sscanf(buffer+4, "%s %s", command, arg);
                        if (strcasecmp(command, "MSG") == 0)
                        {
                              sprintf(datafile, "%smessage.txt", back2slash(DATADIR));
                              mess_name(MESSDIR, atol(arg), datarequest);
                              nb = 1+strlen(datarequest);
                              sprintf(cmd, "cp %s %s", datarequest, datafile);
                              printf("system %s\n", cmd);
                              system(cmd);
                              nb += 1+sprintf(datarequest + nb, "%ld", flength(datafile));
                              send_data(sptr->fd, datafile, datarequest, nb, SVC_MREQ);
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_OPT:
                  /* options management */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char command[80];
                        char arg[80];
                        char val[80];

                        sptr->options = 1;
                        buffer[nbrcv] = '\0';
                        *arg = *val = '\0';
                        sscanf(buffer+4, "%s %s %s", command, arg, val);
                        if (strcasecmp(command, "GET") == 0)
                        {
                              orb_options();
                        }
                        else if (strcasecmp(command, "SET") == 0)
                        {
                              set_opt(arg, val);
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_PACTOR:
                  /* pactor management */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char command[80];
                        int val = 1;
                        int port = 0;

                        buffer[nbrcv] = '\0';
                        sscanf(buffer+4, "%s %d %d", command, &port, &val);
                        if (strcasecmp(command, "SCAN") == 0)
                        {
                              CmdScan(port, val);
                        }
                        else if (strcasecmp(command, "CHO") == 0)
                        {
                              CmdCHO(port, 1);
                        }
                        else if (strcasecmp(command, "BRK") == 0)
                        {
                              CmdCHO(port, 0);
                        }
                  }
                  lg = len+4;
                  break;
            case SVC_INFO:
                  /* channel information */
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  if (sptr->state != CONNECTED)
                        return;
                  if (len < 256)
                  {
                        char command[80];
                        int val = -1;

                        buffer[nbrcv] = '\0';
                        sscanf(buffer+4, "%s %d", command, &val);
                        sptr->infos = (val != -1);
                        set_info_channel(val);
                  }
                  lg = len+4;
                  break;
            default:
                  if (nbrcv < 4)
                        return;
                  len = ((unsigned int) buffer[3] << 8) + (unsigned int) buffer[2];
                  if (nbrcv < len+4)
                        return;
                  lg = len+4;
                  break;
            }
                        
      }
      else 
      {
            char *endptr;
            
            /* Check if the whole line is received */
            buffer[nbrcv] = '\0';
            endptr = strrchr (buffer, '\n');
            if (endptr == NULL)
                  return;

            editor = 0;
            
            lg = 1 + endptr - buffer;

            switch (sptr->state)
            {
            case WAITINFO:

                  /* Mask of services */
                  sscanf (buffer, "%ld %d %s", &sptr->mask, &sptr->channel, call);
                  call[11] = '\0';
                  strcpy (sptr->callsign, call);
                  sptr->cle = time (NULL);
                  sprintf (call, "%010ld", sptr->cle);
                  write (sptr->fd, call, strlen (call));
                  sptr->state = WAITPASS;
                  break;

            case WAITPASS:

                  /* Callsign sans SSID */
                  strcpy (call, sptr->callsign);
                  if ((ptr = strchr (call, '-')))
                        *ptr = '\0';

                  /* Password */
                  sscanf (buffer, "%s", pass);

                  if (comp_passwd (call, pass, sptr->cle))
                  {
                        orb_services();
                        cons_call.num = extind (strupr (sptr->callsign), cons_call.call);
                        reset_msgs ();
                        FbbMem (1);
                        aff_msg_cons ();
                        fbb_list (1);
                        test_pactor(1);
                        if (sptr->mask & ORB_CONSOLE)
                        {
                              FILE *fptr;

                              if ((fptr = fopen (d_disque ("etat.sys"), "r+t")) != NULL)
                              {
                                    fprintf (fptr, "%-6s-%X\n",
                                                 cons_call.call, cons_call.num);
                                    ferme (fptr, 74);
                              }

                              /* Console connection */
                              if (v_tell && connect_tell ())
                              {
                                    music (0);
                              }
                              else if (!connect_console ())
                              {
                                    char *txt = "Console already connected !\n\n";
                                    int len = strlen (txt) + 3;

                                    strcpy (buffer + 7, txt);

                                    /* Header */
                                    buffer[0] = ORB_CONSOLE;
                                    buffer[1] = 0;
                                    buffer[2] = (len) & 0xff;
                                    buffer[3] = (len) >> 8;

                                    buffer[4] = CONSOLE;
                                    buffer[5] = W_CNST;
                                    buffer[6] = 0;

                                    write (sptr->fd, buffer, len + 4);
                                    close (sptr->fd);
                                    orb_del_client (sptr);
                              }
                        }
                        sptr->state = CONNECTED;
                        rcv_state = 0;
                  }
                  else
                  {
                        char *txt = "Callsign/Password error !\n\n";
                        int len = strlen (txt) + 3;

                        strcpy (buffer + 7, txt);

                        /* Header */
                        buffer[0] = ORB_CONSOLE;
                        buffer[1] = 0;
                        buffer[2] = (len) & 0xff;
                        buffer[3] = (len) >> 8;

                        buffer[4] = CONSOLE;
                        buffer[5] = W_CNST;
                        buffer[6] = 0;

                        write (sptr->fd, buffer, len + 4);
                        close (sptr->fd);
                        orb_del_client (sptr);
                  }
                  break;

            case CONNECTED:

                  if (sptr->mask & ORB_CONSOLE)
                  {
                        for (i = 0, j = 0; i < nbrcv; i++)
                        {
                              if (buffer[i] == '\r')
                                    continue;

                              if (buffer[i] == '\n')
                                    buffer[j++] = '\r';
                              else
                                    buffer[j++] = buffer[i];
                        }

                        console_inbuf (buffer, j);
                  }

                  break;
            }
      }
      
      if (lg < nbrcv)
      {
            nbrcv -= lg;
            memmove(buffer, buffer+lg, nbrcv);
            goto again;
      }
      
      nbrcv = 0;
}

static void orb_process (void)
{
      int nb;
      int maxfd;
      fd_set tcp_read;
      fd_set tcp_write;
      fd_set tcp_excep;
      struct timeval to;
      OrbClient *sptr;

      if (orb_fd == -1)
            return;

      to.tv_sec = to.tv_usec = 0;

      FD_ZERO (&tcp_read);
      FD_ZERO (&tcp_write);
      FD_ZERO (&tcp_excep);

      maxfd = orb_fd;
      FD_SET (orb_fd, &tcp_read);

      sptr = client_head;
      while (sptr)
      {
            FD_SET (sptr->fd, &tcp_read);
            if (sptr->fd > maxfd)
                  maxfd = sptr->fd;
            sptr = sptr->next;
      }

      nb = select (maxfd + 1, &tcp_read, NULL, NULL, &to);

      if (nb == -1)
      {
            perror ("orb_select");
            return;
      }

      if (nb == 0)
      {
            /* nothing to do */
            return;
      }

      /* To avoid network locks */
      alarm(60);

      if (FD_ISSET (orb_fd, &tcp_read))
      {
            /* New client connection */
            orb_new_connection (orb_fd);
      }

      sptr = client_head;
      while (sptr)
      {
            /* On sauvegarde le next car le pointeur de client peut etre
               * libere pendant le traitement en cas de deconnexion */
            OrbClient *ptemp = sptr->next;

            if (FD_ISSET (sptr->fd, &tcp_read))
            {
                  orb_process_data (sptr);
                  is_idle = 0;
            }
            sptr = ptemp;
      }
      
      alarm(0);

      return;
}

int fbb_orb (char *service, int port)
{
      int val;
      int len;
      struct sockaddr_in sock_addr;

      if ((orb_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
      {
            perror ("socket_r");
            return (0);
      }

      val = 1;
      len = sizeof (val);
      if (setsockopt (orb_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, len) == -1)
      {
            perror ("opn_tcp : setsockopt SO_REUSEADDR");
      }

      sock_addr.sin_family = AF_INET;
      sock_addr.sin_addr.s_addr = 0;
      sock_addr.sin_port = htons (port);

      if (bind (orb_fd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) != 0)
      {
            perror ("opn_tcp : bind");
            close (orb_fd);
            return (0);
      }

      if (listen (orb_fd, SOMAXCONN) == -1)
      {
            perror ("listen");
            close (orb_fd);
            return (0);
      }

      fprintf (stderr, "xfbbC/X server running ...\n");
      fprintf (stderr, "xfbbd ready and running ...\n");
      fflush (stderr);

      for (;;)
      {
            orb_process ();
            process ();
            if (is_idle)
            {
                  usleep (1);
            }
            else
            {
                  is_idle = 1;
            }
      }

      return 1;
}

static void orb_send_data (char *buffer, int lg, int mask)
{
      OrbClient *sptr = client_head;

      while (sptr)
      {
            if (sptr->mask & mask)
            {
                  switch (mask)
                  {
                  case ORB_MONITOR:
                  case ORB_CONSOLE:
                  case ORB_CHANNEL:
                        if (((mask == ORB_MONITOR) && (buffer[4] == 0xff)) ||
                              ((mask == ORB_CONSOLE) && (buffer[4] == 0)))
                        {
                              write (sptr->fd, buffer, lg);
                        }
/*                      if ((mask == ORB_CHANNEL) && (buffer[4] > 0) && (buffer[4] < 0xff)) */
                        if (mask == ORB_CHANNEL)
                        {
                              if ((sptr->channel == 0) || (sptr->channel == buffer[4]))
                                    write (sptr->fd, buffer, lg);
                        }
                        break;
                  case ORB_XFBBX:
                        if (sptr->mask & ORB_CONSOLE)
                              write (sptr->fd, buffer, lg);
                        break;
                  default:
                        write (sptr->fd, buffer, lg);
                        break;
                  }
            }
            sptr = sptr->next;
      }
}

void orb_write (int channel, char *data, int len, int color, int header)
{
      int i, j;
      char *buffer;

      buffer = malloc (len + 8);
      if (buffer == NULL)
            return;

      for (i = 0, j = 7; i < len; i++)
      {
            if (data[i] == '\n')
                  continue;

            if (data[i] == '\r')
                  buffer[j++] = '\n';
            else
                  buffer[j++] = data[i];
      }

      if (channel == CONSOLE)
      {
            /* Editor request ? */
            if (editor_request)
            {
                  int len = 1;
                  
                  char buf[80];

                  editor_request = 0;
                  editor = 1;
                  buf[0] = ORB_XFBBX;
                  buf[1] = 0;
                  buf[3] = 0;
                  switch (reply)
                  {
                  case 1 :    /* SR */
                        len += sprintf(buf+5, "%ld", svoie[CONSOLE]->enrcur);
                        buf[4] = 4;
                        break;
                  case 3 :    /* Sx */
                        buf[4] = 3;
                        break;
                  default:
                        buf[4] = 0;
                        break;
                  }
                  buf[2] = len;
                  orb_send_data (buf, 4+len, ORB_XFBBX);
            }

            /* Header */
            buffer[0] = ORB_CONSOLE;
            buffer[1] = 0;
            buffer[2] = (j - 4) & 0xff;
            buffer[3] = (j - 4) >> 8;

            /* Envoie les data de console au client */
            buffer[4] = CONSOLE;
            buffer[5] = color;
            buffer[6] = header;
            orb_send_data (buffer, j, ORB_CONSOLE);
      }
      else if (channel == MMONITOR)
      {
            /* Header */
            buffer[0] = ORB_MONITOR;
            buffer[1] = 0;
            buffer[2] = (j - 4) & 0xff;
            buffer[3] = (j - 4) >> 8;

            /* Envoie les data de monitoring au client */
            buffer[4] = 0xff;
            buffer[5] = color;
            buffer[6] = header;
            orb_send_data (buffer, j, ORB_MONITOR);
      }
      else
      {
            /* Header */
            buffer[0] = ORB_CHANNEL;
            buffer[1] = 0;
            buffer[2] = (j - 4) & 0xff;
            buffer[3] = (j - 4) >> 8;

            /* Envoie les data de monitoring au client */
            buffer[4] = channel - 1;
            buffer[5] = color;
            buffer[6] = header;
            orb_send_data (buffer, j, ORB_CHANNEL);
      }
      free (buffer);
}

void orb_disc (void)
{
      OrbClient *sptr = client_head;

      /* Deconnecte un client */
      while (sptr)
      {
            if (sptr->mask & ORB_CONSOLE)
            {
                  if (sptr->mask & ORB_XFBBX)
                  {
                        char buffer[5];

                        /* Envoie la commande de deconnection */
                        buffer[0] = ORB_XFBBX;
                        buffer[1] = 0;
                        buffer[2] = 1;
                        buffer[3] = 0;
                        buffer[4] = 0;
                        write (sptr->fd, buffer, 5);
                        sptr->mask &= ~ORB_CONSOLE;
                  }
                  else
                  {
                        close (sptr->fd);
                        orb_del_client (sptr);
                  }
                  break;
            }
            sptr = sptr->next;
      }
}

void orb_services (void)
{
      char buffer[260];
      int i;
      
      printf("sending %d services\n", SVC_MAX-1);

      /* Header */
      buffer[0] = ORB_DATA;
      buffer[1] = SVC_LIST;
      buffer[2] = SVC_MAX-1; /* Max 255 services */
      buffer[3] = 0;

      /* One service per byte */
      for (i = 1 ; i < SVC_MAX ; i++)
            buffer[4 + i - 1] = i;
      
      orb_send_data (buffer, 4 + SVC_MAX - 1, 0xffff);
}

void orb_con_list (int channel, char *ligne)
{
      char buffer[256];
      int len = strlen (ligne);

      /* Header */
      buffer[0] = ORB_LISTCNX;
      buffer[1] = 0;
      buffer[2] = (len) & 0xff;
      buffer[3] = (len) >> 8;

      /* Envoie la ligne de connection du canal */
      strcpy (buffer + 4, ligne);
      orb_send_data (buffer, len + 4, ORB_LISTCNX);
}

void orb_pactor_status(int port, int p_status)
{
      char buffer[80];
      int len;

      sprintf (buffer + 4, "%d %d", port, p_status);
      len = strlen (buffer + 4);

      /* Header */
      buffer[0] = ORB_DATA;
      buffer[1] = SVC_PACTOR;
      buffer[2] = (len) & 0xff;
      buffer[3] = (len) >> 8;

      /* Send pactor status */
      orb_send_data (buffer, len + 4, ORB_STATUS);
}

void orb_con_nb (int nb)
{
      char buffer[80];
      int len;

      sprintf (buffer + 4, "%d", nb);
      len = strlen (buffer + 4);

      /* Header */
      buffer[0] = ORB_NBCNX;
      buffer[1] = 0;
      buffer[2] = (len) & 0xff;
      buffer[3] = (len) >> 8;

      /* Envoie le nombre de connections */
      orb_send_data (buffer, len + 4, ORB_NBCNX);
}

void orb_nb_msg (int priv, int hold, int nbmess)
{
      char buffer[80];
      int len;

      sprintf (buffer + 4, "%d %d %d", priv, hold, nbmess);
      len = strlen (buffer + 4);

      /* Header */
      buffer[0] = ORB_MSGS;
      buffer[1] = 0;
      buffer[2] = (len) & 0xff;
      buffer[3] = (len) >> 8;

      /* Envoie le nombre de messages */
      orb_send_data (buffer, len + 4, ORB_MSGS);
}

void orb_status (long lmem, long gmem, long disk1, long disk2)
{
      char buffer[80];
      int len;

      sprintf (buffer + 4, "%ld %ld %ld %ld", lmem, gmem, disk1, disk2);
      len = strlen (buffer + 4);

      /* Header */
      buffer[0] = ORB_STATUS;
      buffer[1] = 0;
      buffer[2] = (len) & 0xff;
      buffer[3] = (len) >> 8;

      /* Envoie les infos de status */
      orb_send_data (buffer, len + 4, ORB_STATUS);
}

static void set_opt(char *command, char *value)
{
      int val = atoi(value);
      int ok = 1;
      
      switch(*command)
      {
      case 'B' :
            bip = val;
            break;
      case 'G' :
            gate = val;
            break;
      case 'M' :
            sed = val;
            break;
      case 'T' :
            ok_tell = val;
            break;
      case 'X' :
            aff_inexport = val;
            break;
      case 'P' :
            aff_popsmtp = val;
            break;
      default :
            ok = 0;
            break;
      }

      if (ok)     
            maj_options();
}

void orb_options(void)
{
      OrbClient *sptr = client_head;
      char *command = "OPT\n";
      char buffer[256];
      int nb = 0;
      
      nb += sprintf(buffer+nb, "B %d Connection bip\n", (bip) ? 1 : 0);
      nb += sprintf(buffer+nb, "G %d Gateway\n", (gate) ? 1 : 0);
      nb += sprintf(buffer+nb, "M %d Message Editor\n", (sed) ? 1 : 0);
      nb += sprintf(buffer+nb, "T %d Talk\n", (ok_tell) ? 1 : 0);
      nb += sprintf(buffer+nb, "X %d Im/export display\n", (aff_inexport) ? 1 : 0);
      nb += sprintf(buffer+nb, "P %d POP/SMTP display\n", (aff_popsmtp) ? 1 : 0);

      while (sptr)
      {
            /* Send information only to the right clients */
            if (sptr->options)
                  send_data_buf(sptr, SVC_OPT, command, buffer, nb);
            sptr = sptr->next;
      }
}

void orb_info(int val, char *str)
{
      static char buffer[512];
      static int nb = 0;

      if (str)
      {
            nb += sprintf(buffer+nb, "%d %s\n", val, str);
      }
      else if (nb > 0)
      {
            OrbClient *sptr = client_head;
            char *command = "INFO\n";
            while (sptr)
            {
                  /* Send information only to the right clients */
                  if (sptr->infos)
                        send_data_buf(sptr, SVC_INFO, command, buffer, nb);
                  sptr = sptr->next;
            }
            nb = 0;
      }
}

Generated by  Doxygen 1.6.0   Back to index