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

Socks.cpp

#ifdef WIN32
#include <winsock.h>
#else
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#endif

#ifdef LINUX
#include <stdint.h>
#endif

#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#include <errno.h>

#include <gtk/gtk.h>

#include "papaya/system.h"

#include "Message.h"
#include "Socks.h"
#include "Prefs.h"

/**
 * Default constructor, initialises anything not initialised in Socket()
 */

Socks::Socks(Connection * c) : Socket(c) {
  initSocks = SOCKS_INITIAL;
  dest_host = NULL;
  dest_port = 0;
}

/**
 * Destructor.
 */

Socks::~Socks() {
  if (dest_host)
    free(dest_host);
}

/**
 * Creates a connection to a host via the Socks proxy.
 */

int Socks::create(char * host, int port) {

  dest_port = port;
  dest_host = strdup(host);


  if (!conn->queryPreferences()->getPreference("SocksHost")) {
    new Message("Error", _("Please edit this connection's prefererences and specify the socks proxy's name."), true);
    return -1;
  }

  int res = Socket::create(conn->queryPreferences()->getPreference("SocksHost"), conn->queryPreferences()->getPreferenceInteger("SocksPort"));
  if (res == -1) {
    new Message("Error", _("Papaya was unable to contact the configured socks proxy."), true);
    return -1;
  }
  
  return res;
}

/**
 * Checks if we're connected, sending socks initialisation and waiting for
 * response before telling the client that we're connected.
 */

int Socks::connected() {

  char * send;
  int res;

  if (Socket::connected()) {
    switch (initSocks) {
    case SOCKS_INITIAL: // Send the request to the server.
      struct socks_request req;
      
      if (!dest_host) {
      new Message("Error", ("No socks proxy host was specified."), true);
      return -1;
      }

      send = (char *)malloc(sizeof(struct socks_request));

      req.vn = 4;
      req.cd = 1;
      req.port = htons(dest_port);
      // Figure out the IP address of the remote host.

      struct in_addr addr;

      if (isalpha(*dest_host)) {
      struct hostent * hp;
      hp = gethostbyname(dest_host);
      if (!hp) {
        char buf[1024];
        snprintf(buf, 1024, _("gethostbyname: %s"), strerror(errno));
        new Message("Error", buf, true);
        return -1;
      }

      memcpy((char *)&addr, hp->h_addr, sizeof(struct in_addr));
      req.host = addr.s_addr;
      } else {
      req.host = inet_addr(dest_host);
      }
      
      sprintf(req.name, "%s", conn->queryPreferences()->getPreference("SocksUser"));
      memcpy(send, &req, sizeof(struct socks_request));
      write(send, 8 + strlen(conn->queryPreferences()->getPreference("SocksUser")) + 1);
      initSocks = SOCKS_REQUEST_SENT;
      free(send);

      return 0;
      break;

    case SOCKS_REQUEST_SENT: // Check for a response
      struct socks_response resp;
      char buf[8];
      res = read(8, buf);
      
      // No longer connected.
      if (res == -1)
      return -1;

      // Not yet connected.
      if (res == 0)
      return 0;

      // Unable to read all 8 bytes - error.
      if (res < 8)
      return -1;

      memcpy(&resp, buf, 8);

      if (resp.cd == 90)
      return 1;

      return -1;
      break;

    default:

      new Message("Error", _("Papaya detected an error connecting to the socks server."), true);
      return -1;
      break;
    }
  }
  
  return 0;
}


Generated by  Doxygen 1.6.0   Back to index