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

network.c

/*
 * YICS: Connect a FICS interface to the Yahoo! Chess server.
 * Copyright (C) 2004  Chris Howie
 *
 * 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.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>

#include "platform.h"

#ifdef _YICS_POSIX
#include <sys/time.h>
#include <unistd.h>
#endif

#include <sys/types.h>
#include "sockets.h"
#include "types.h"
#include "util.h"
#include "network.h"
#include "globals.h"
#include "ropcodes.h"

static int sock = -1;
static bool crypt = false;
static signed long key_in = 0, key_out = 0;

#ifdef _YICS_WIN32
static bool windowsStartedUp = false;

static void ninit() {
      WORD winsockVersionRequired = 0x0101; /* Winsock Version 1.1 */
      WSADATA winsockData;

      WSAStartup (winsockVersionRequired, &winsockData);
      windowsStartedUp = true;
}
#endif

int nconnect(const char *host, unsigned short port) {
      int s;
      struct sockaddr_in sa;
      struct hostent *hp;

#ifdef _YICS_WIN32
      if (!windowsStartedUp)
            ninit();
#endif
      hp = gethostbyname(host);
      if (!hp)
            return -1;

      memset(&sa, 0, sizeof(sa));
      memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
      sa.sin_family = hp->h_addrtype;
      sa.sin_port = htons(port);

      s = socket(AF_INET, SOCK_STREAM, 0);
      if (s < 0)
            return -1;

      if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
            closesock(s);
            return -1;
      }

      return s;
}

bool yconnect(const char *host, unsigned short port) {
      int s = nconnect(host, port);

      if (s < 0)
            return false;

      sock = s;
      crypt = false;
      return true;
}

void nclose() {
      if (sock >= 0) {
            closesock(sock);
            sock = -1;
            crypt = false;
      }
}

bool socket_ready() {
      fd_set sl;
      struct timeval tv;

      if (sock < 0)
            return false;

      FD_ZERO(&sl);
      FD_SET(sock, &sl);
      tv.tv_sec = 0;
      tv.tv_usec = 1000;

      if (select(sock + 1, &sl, NULL, NULL, &tv))
            return true;

      return false;
}

void set_keys(signed long ko, signed long ki) {
      key_out = ko;
      key_in = ki;
      crypt = true;
}

int ngetc() {
      uchar c;

      if (sock < 0)
            return -1;

      if (recv(sock, (char *)&c, sizeof(c), 0) <= 0)
            return -1;

      if (crypt) {
            key_in *= 83;
            c ^= key_in;
      }

      if (netlog != NULL) {
            fputc(0, netlog);
            fputc(c, netlog);
      }

      return c;
}

int nread(char *buf, int count) {
      int read = 0;
      int c;

      while (read < count) {
            c = ngetc();
            if (c < 0)
                  break;
            if (buf != NULL)
                  buf[read++] = (char)c;
            else
                  read++;
      }

      if (buf != NULL)
            buf[read] = '\0';

      return read;
}

bool nputc(char out) {
      uchar o = (uchar)out;

      if (sock < 0)
            return false;

      if (netlog != NULL) {
            fputc(1, netlog);
            fputc(o, netlog);
      }

      if (crypt) {
            key_out *= 83;
            o ^= key_out;
      }

      if (send(sock, (char *)&o, 1, 0) <= 0)
            return false;

      return true;
}

bool nprint(const char *out, int count) {
      int i;

      if (sock < 0)
            return false;

      for (i = 0; i < count; i++) {
            if (!nputc(out[i]))
                  return false;
      }

      lastcommand = time(NULL);

      return true;
}

bool nprintrop(char opcode, const char *data, int length) {
      String *utf;
      bool r;

      if (sock < 0)
            return false;

      if (!nputc(0x64))
            return false;
      if (!nprint((char *)&session, 4))
            return false;

      utf = StringSet(StringNull(), &opcode, 1);
      StringCat(utf, data, length);
      r = nprintutf(utf->string, (unsigned short)utf->length);
      StringFree(utf);

      return r;
}

bool nprinttop(uchar number, char opcode, const char *data, int length) {
      char *packet = malloc(2 + length);
      bool r;

      if (packet == NULL)
            return false;

      packet[0] = (char)number;
      packet[1] = opcode;

      memcpy(&packet[2], data, length);

      r = nprintrop(ROP_TOP, packet, 2 + length);

      free(packet);
      return r;
}

bool nprintutf(const char *str, unsigned short length) {
      char *tmp = malloc(length + 3);
      bool r;

      if (tmp == NULL)
            return false;

      packutf(tmp, str, length);
      r = nprint(tmp, length + 2);

      free(tmp);
      return r;
}

short nreadutf(char *dest) {
      short length;

      if (nread((char *)&length, 2) != 2)
            return 0;
      length = ntohs(length);

      if (nread(dest, length) != length)
            return 0;
      dest[length] = '\0';

      return length;
}

String *nreadutfString(String *dest) {
      short length;
      char *tmp;

      if (dest == NULL)
            return NULL;

      tmp = malloc(65536);
      if (tmp == NULL)
            return NULL;

      length = nreadutf(tmp);
      StringSet(dest, tmp, length);

      free(tmp);

      return dest;
}

char *ngets(char *buffer, int max, int sd) {
      int i = 0;
      char b;
      max--;

      while ((i < max) && (recv(sd, &b, 1, 0) != 0)) {
            if (b != '\r') {
                  buffer[i++] = b;
                  if (b == '\n') {
                        buffer[i] = '\0';
                        return buffer;
                  }
            }
      }

      if (i == 0)
            return NULL;

      buffer[i] = '\0';
      return buffer;
}

Generated by  Doxygen 1.6.0   Back to index