Ejemplo n.º 1
0
  void client::info(server_info & out)
  {
    send_(makecmd("INFO", true));
    string response = recv_bulk_reply_();

    if (response.empty())
      throw protocol_error("empty");

    string_vector lines;
    split_lines(response, lines);
    if (lines.empty())
      throw protocol_error("empty line for info");

    for (string_vector::const_iterator it = lines.begin();
         it != lines.end(); ++it)
    {
      const string & line = *it;
      string_vector line_parts;
      split(line, ':', line_parts);
      if (line_parts.size() != 2)
        throw protocol_error("unexpected line format for info");

      const string & key = line_parts[0];
      const string & val = line_parts[1];

      if (key == server_info_key_version)
        out.version = val;
      else if (key == server_info_key_bgsave_in_progress)
        out.bgsave_in_progress = value_from_string<unsigned long>(val) == 1;
      else if (key == server_info_key_connected_clients)
        out.connected_clients = value_from_string<unsigned long>(val);
      else if (key == server_info_key_connected_slaves)
        out.connected_slaves = value_from_string<unsigned long>(val);
      else if (key == server_info_key_used_memory)
        out.used_memory = value_from_string<unsigned long>(val);
      else if (key == server_info_key_changes_since_last_save)
        out.changes_since_last_save = value_from_string<unsigned long>(val);
      else if (key == server_info_key_last_save_time)
        out.last_save_time = value_from_string<unsigned long>(val);
      else if (key == server_info_key_total_connections_received)
        out.total_connections_received = value_from_string<unsigned long>(val);
      else if (key == server_info_key_total_commands_processed)
        out.total_commands_processed = value_from_string<unsigned long>(val);
      else if (key == server_info_key_uptime_in_seconds)
        out.uptime_in_seconds = value_from_string<unsigned long>(val);
      else if (key == server_info_key_uptime_in_days)
        out.uptime_in_days = value_from_string<unsigned long>(val);
      else if (key == server_info_key_role)
        out.role = val == server_info_value_role_master ? role_master : role_slave;
      else
        throw protocol_error(string("unexpected info key '") + key + "'");
    }
  }
Ejemplo n.º 2
0
void P2PFolder::handle_message(const blob& message_raw) {
	V1Parser::message_type message_type = parser_.parse_MessageType(message_raw);

	counter_.add_down(message_raw.size());

	if(ready()) {
		switch(message_type) {
			case V1Parser::CHOKE: handle_Choke(message_raw); break;
			case V1Parser::UNCHOKE: handle_Unchoke(message_raw); break;
			case V1Parser::INTERESTED: handle_Interested(message_raw); break;
			case V1Parser::NOT_INTERESTED: handle_NotInterested(message_raw); break;
			case V1Parser::HAVE_META: handle_HaveMeta(message_raw); break;
			case V1Parser::HAVE_CHUNK: handle_HaveChunk(message_raw); break;
			case V1Parser::META_REQUEST: handle_MetaRequest(message_raw); break;
			case V1Parser::META_REPLY: handle_MetaReply(message_raw); break;
			case V1Parser::META_CANCEL: handle_MetaCancel(message_raw); break;
			case V1Parser::BLOCK_REQUEST: handle_BlockRequest(message_raw); break;
			case V1Parser::BLOCK_REPLY: handle_BlockReply(message_raw); break;
			case V1Parser::BLOCK_CANCEL: handle_BlockCancel(message_raw); break;
			default: throw protocol_error();
		}
	}else{
		handle_Handshake(message_raw);
	}
}
Ejemplo n.º 3
0
/**
 * Common function to handle parsing the HTTP stream for both v0 and v1 io
 * implementations.
 */
static void read_common(http_provider *http)
{
    lcb_error_t err;
    lcb_connection_t conn = &http->connection;
    int old_generation = http->stream.generation;

    lcb_log(LOGARGS(http, TRACE),
            "Received %d bytes on HTTP stream", conn->input->nbytes);

    lcb_timer_rearm(http->io_timer,
                    PROVIDER_SETTING(&http->base, config_node_timeout));

    lcb_string_rbappend(&http->stream.chunk, conn->input, 1);

    err = htvb_parse(&http->stream, http->base.parent->settings->conntype);

    if (http->stream.generation != old_generation) {
        lcb_log(LOGARGS(http, DEBUG),
                "Generation %d -> %d", old_generation, http->stream.generation);

        set_new_config(http);
    } else {
        lcb_log(LOGARGS(http, TRACE), "HTTP not yet done. Err=0x%x", err);
    }

    if (err != LCB_BUSY && err != LCB_SUCCESS) {
        protocol_error(http, err);
        return;
    }

    lcb_sockrw_set_want(conn, LCB_READ_EVENT, 1);
    lcb_sockrw_apply_want(conn);
}
Ejemplo n.º 4
0
  client::int_type client::recv_int_reply_()
  {
    string line = read_line(socket_);

#ifndef NDEBUG
    output_proto_debug(line);
#endif

    if (line.empty())
      throw protocol_error("invalid integer reply; empty");

    if (line[0] != prefix_int_reply)
      throw protocol_error("unexpected prefix for integer reply");

    return value_from_string<client::int_type>(line.substr(1));
  }
Ejemplo n.º 5
0
void peer::on_state(readable& in)
{
	state_msg state;
	in(state);
	vector<digest> options(2);
	options.push_back(state.top_digest);
	options.push_back(state.prev_digest);
	in.read_full(options, k_max_state_depth);

	m_top_digest = state.top_digest;
	m_top_work = state.top_work;
	m_top_height = state.top_height;
	m_top_txn = std::numeric_limits<uint64_t>::max();
	m_ssync_txn = 0;
	tx_queue_t empty;
	std::swap(m_txns, empty);
	
	// Find first point to merge
	bool worked = false;
	for(uint64_t i = 0; i < options.size(); i++) {
		chain_ptr p = chain::find_by_digest(options[i]);
		if (p) {
			m_head = p;
			worked = true;
			break;
		}
	}
	if (!worked) {
		throw protocol_error("State never reached shared node");
	}
}
Ejemplo n.º 6
0
void P2PFolder::perform_handshake() {
	if(!folder_group()) throw protocol_error();

	V1Parser::Handshake message_struct;
	message_struct.auth_token = local_token();
	message_struct.device_name = Config::get()->globals()["client_name"].asString();
	message_struct.user_agent = Version::current().user_agent();

	send_message(parser_.gen_Handshake(message_struct));
	log_->debug() << log_tag() << "==> HANDSHAKE";
}
Ejemplo n.º 7
0
unsigned char get_8( void )
{
int x;

    x = fgetc( server_r );
    if (x == EOF)
    {
       protocol_error();
    }
    /*printf( "RECV %02x\n", x );*/
    return x;
}
Ejemplo n.º 8
0
void peer::on_chain(const chain_request& cr, readable& in)
{
	m_req_count--;
	vector<block_ext> bes;
	in.read_full(bes, k_max_chain_req, 1);
	for(uint64_t i = 0; i < bes.size(); i++) {
		chain_ptr nh = m_head->append(bes[i].details, bes[i].nonce);
		auto wr = work_requirements(m_head);
		if (nh->self_work() < wr.second) {
			throw protocol_error("Insufficent work in chain response");
		}
		if (nh->height() > m_top_height) {
			throw protocol_error("Height larger than expected in chain response");
		}
		m_head = nh;
	}
	if (m_head->height() == m_top_height) {
		if (m_top_work != m_head->total_work() ||
			m_top_digest != m_head->self_digest()) {
			throw protocol_error("Top of chain failed to match");
		}
	}
}
Ejemplo n.º 9
0
  client::int_type client::recv_bulk_reply_(char prefix)
  {
    string line = read_line(socket_);
//    cout<<"line:"<<line<<endl;
#ifndef NDEBUG
    output_proto_debug(line);
#endif

    if (line[0] != prefix)
      {
   	throw protocol_error("unexpected prefix for bulk reply");
      }
    return value_from_string<client::int_type>(line.substr(1));
  }
Ejemplo n.º 10
0
  string client::recv_single_line_reply_()
  {
    string line = read_line(socket_);

#ifndef NDEBUG
    output_proto_debug(line);
#endif

    if (line.empty())
      throw protocol_error("empty single line reply");

    if (line.find(prefix_status_reply_error) == 0) 
    {
      string error_msg = line.substr(prefix_status_reply_error.length());
      if (error_msg.empty()) 
        error_msg = "unknown error";
      throw protocol_error(error_msg);
    }

    if (line[0] != prefix_status_reply_value)
      throw protocol_error("unexpected prefix for status reply");

    return line.substr(1);
  }
Ejemplo n.º 11
0
void peer::on_txd(const digest& block, const digest& txn, readable& in)
{
	if (block != m_head->self_digest()) {
		return;  // Looks like I've moved on
	}
	if (m_head != m_server.top()) {
		return;  // Looks like the server has moved on
	}
	txn_pow pow;
	in(pow);
	if (txn != digest(pow.txn)) {
		throw protocol_error("Txn digest does not match txn");
	}
	m_server.build_block()->apply_remote_txn(pow);
}
Ejemplo n.º 12
0
void peer::on_message(readable& in) {
	resp_type rt;
	in(rt);
	if (rt == resp_type::state) {
		on_state(in);
		return;
	}
	if (rt != resp_type::success && rt != resp_type::ood) {
		throw protocol_error("Invalid response type");
	}
	auto p = std::move(m_queue.front());
	m_queue.pop();
	if (rt == resp_type::success) {
		p.first(in);
	} else {
		p.second();
	}
}
Ejemplo n.º 13
0
/* Handle session start information */  
gchar *
get_session_info (gint out, gchar *code)
{
  gchar *buffer;
  gchar *retval;

  buffer = read_code (out);
  if (!strcmp (buffer, code))
    {
      flush_buffer (buffer);
      buffer = read_line (out);
      retval = get_info_after_colon (buffer);
      g_free (buffer);
      return retval;
    }

  g_warning ("Waiting for %s, got %s\n", code, buffer);
  protocol_error ("session info!");
  return NULL;
}
Ejemplo n.º 14
0
/** handshake - accept incoming connection  */
static int accept_connection(ICI *d, char **remotehost, unsigned short *rport) {
  struct sockaddr_in addr;
  int s;
  socklen_t addrlen = sizeof(addr);

  debugmsg(DEBUG_SRV, "SRV: waiting for accept on server-fd:%d\n", d->fd);

  do {
    s = accept(d->fd, (struct sockaddr *)&addr, &addrlen);
  } while(s < 0 && errno == EINTR);

  *remotehost = inet_ntoa(addr.sin_addr);
  *rport = ntohs(addr.sin_port);

  if(s<0) {
    dlog(DLOG_WARNING, "SRV: socket accept error: %s\n", strerror(errno));
    return (-1);
  }
  dlog(DLOG_INFO, "SRV: Connection accepted %s:%d\n", *remotehost, *rport);

  //  pthread_mutex_lock(&d->lock); ? not needed
  if (d->num_clients >= MAXCONNECTIONS) {
    protocol_error(s, 503, "Too many open connections. Please try again later.");
#ifndef HAVE_WINDOWS
    close(s);
#else
    closesocket(s);
#endif
    dlog(DLOG_WARNING, "SRV: refused client. max number of connections (%i) readed.\n", MAXCONNECTIONS);
    return (-1);
  }

  // check if we should use SO_KEEPALIVE here
  //int val = 1; setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &val,  sizeof(int));
  // or set non-blocking i/o ...
  //setnonblock(s, 1);
  return(s);
}
Ejemplo n.º 15
0
void ptree::read(readable& in) 
{
	vector<ptree_ptr> stack;
	vector<uint8_t> split_stack;
	uint8_t max_byte = std::numeric_limits<uint8_t>::max();
	stack.reserve(k_max_ptree_proof_stack);
	split_stack.reserve(k_max_ptree_proof_stack);
	// Loop exits on valid EOF marker or when read throws due to EOF
	while(1) {
		if (stack.size() == k_max_ptree_proof_stack) {
			// To use 256 elements of the stack requires a depth of 128, which
			// basically means SHA256 is broken...
			throw protocol_error("Stack impossibly large in ptree");
		}
		uint8_t type;
		in.read_full(type);
		if (type == pid_eof) {
			// We are done, leave loop and validate
			break;
		} else if (type == pid_leaf) {
			// Read a leaf + push to stack
			ptree_ptr p = make_shared<ptree_leaf>(in);
			stack.push_back(p);
			split_stack.push_back(max_byte);
		} else if (type == pid_proxy) {
			// Read a proxy + push to stack
			ptree_ptr p = make_shared<ptree_proxy>(in);
			stack.push_back(p);
			split_stack.push_back(max_byte);
		} else {
			// Construct a branch
			// First validate stack size
			if (stack.size() < 2) {
				throw protocol_error("Invalid ptree structure");
			}
			// Pop the nodes
			ptree_ptr p2 = stack.back(); stack.pop_back();
			ptree_ptr p1 = stack.back(); stack.pop_back();
			// Make sure they are not both proxies
			if (p1->is_proxy() && p2->is_proxy()) {
				throw protocol_error("Two proxy children in ptree");
			}
			// Make sure they don't overflow sum
			if (p1->node_count() > k_max_ptree_nodes || p2->node_count() > k_max_ptree_nodes) {
				throw protocol_error("Node count overflow");
			}
			uint8_t split_pos = type;
			// If they are both actual nodes, make sure split_pos matches + order is right
			if (!p1->is_proxy() && !p2->is_proxy()) {
				uint64_t validate_split = p1->prefix().first_diff(p2->prefix());
				if (validate_split != split_pos) {
					throw protocol_error("Invalid node split position");
				}
				if (p1->prefix() >= p2->prefix()) {
					throw protocol_error("Invalid node order");
				}
			} else if (p1->is_proxy()) {
				// Check p2 is 1 bit at proper spot
				if (p2->prefix().get_bit(split_pos) != 1) {
					throw protocol_error("Invalid bit next to proxy");
				}
			} else {  // p2->is_proxy()
				if (p1->prefix().get_bit(split_pos) != 0) {
					throw protocol_error("Invalid bit next to proxy");
				}
			}
			// Either way, make sure split position is smaller as we go up stack
			uint8_t s2 = split_stack.back(); split_stack.pop_back();
			uint8_t s1 = split_stack.back(); split_stack.pop_back();
			if (min(s1, s2) <= type) {
				throw protocol_error("Invalid split pos structure");
			}
			// Make node + push
			ptree_ptr p = make_shared<ptree_branch>(split_pos, p1, p2);
			stack.push_back(p);
			split_stack.push_back(split_pos); 
		}
	}
	// There should be zero or 1 entries on the stack
	if (stack.size() > 1) {
		throw protocol_error("Invalid stack at EOF of ptree");
	}
	// If it's zero, it's an empty ptree!
	if (stack.size() == 0) {
		m_root = ptree_ptr();
	}
	// If it's one entry, make sure it's not a proxy
	if (stack[0]->is_proxy()) {
		throw protocol_error("Pure proxy ptree is invalid");
	}
	// Otherwise, we are good
	m_root = stack[0];
}
Ejemplo n.º 16
0
 void client::recv_int_ok_reply_()
 {
   if (recv_int_reply_() != 1)
     throw protocol_error("expecting int reply of 1");
 }
Ejemplo n.º 17
0
int
main (int argc, char **argv)
{
  gchar *confdir;

  gchar *host = g_strdup ("localhost");
  gchar *port = g_strdup ("22");
  gchar *sshkey = NULL;

  gchar *user = NULL;
  gchar *password = NULL;

  gchar *session = g_strdup ("thinnx");
  gchar *type = g_strdup ("unix-gnome");
  gchar *cookie = NULL;

  gboolean use_ssl = 0;

  gchar *link = g_strdup ("adsl");
  gchar *kbdtype = g_strdup ("pc104/us");

  gchar *geometry = g_strdup ("fullscreen");
  gchar *screeninfo = NULL;

  gchar *session_id = NULL;
  gchar *session_display = NULL;
  gchar *pcookie = NULL;
  
  gchar **nxssh_argv = (gchar**) g_malloc (sizeof(gchar*) * 9);

  gchar *restore_id = NULL;

  pid_t pid;

  int parent_pipe[2];	/* For talking to the parent */
  int child_pipe[2];	/* For talking to the child */

  gint in = 0, out = 0;

  gtk_init (&argc, &argv);

  homedir = g_get_home_dir ();
  confdir = g_strdup_printf ("%s/.nx/", homedir);
  sshkey = g_strdup_printf ("%s/.ssh/id_dsa", homedir);

  {
    struct stat info;
    
    if (stat (confdir, &info) == -1)
      {
      if (mkdir (confdir, 0777) == -1)
	g_critical ("Could not create directory %s: %s\n", 
		    confdir, strerror (errno));
      }
  }    

  {
#if GTK_MAJOR_VERSION == 2
    GdkScreen *screen;

    screen = gdk_screen_get_default ();
    
    screeninfo = g_strdup_printf ("%dx%dx%d+render", 
				  gdk_screen_get_width (screen),
				  gdk_screen_get_height (screen),
				  gdk_visual_get_best_depth ());
#else
    screeninfo = g_strdup_printf ("%dx%dx%d+render",
				  gdk_screen_width (),
				  gdk_screen_height (),
				  gdk_visual_get_best_depth ());
#endif
  }

  { /* get X authentication cookie information */
    FILE *xauth_output;
    gchar xauth[256] = {0};

    gchar *tmp = NULL;
    gchar **tmpv = NULL;
    gchar *display = NULL;

    /* avoid problems with "network" DISPLAY's */
    display = g_strdup (getenv ("DISPLAY"));
    tmpv = g_strsplit (display, ":", 3);
    g_free (display);
  
    display = g_strdup_printf (":%s", tmpv[1]);
    g_strfreev (tmpv);

    /* get the authorization token */
    tmp = g_strdup_printf (XAUTHBINDIR"/xauth list %s | "
			   "grep 'MIT-MAGIC-COOKIE-1' | "
			   "cut -d ' ' -f 5",
			   display);

    if ((xauth_output = popen (tmp, "r")) == NULL)
      {
	g_critical ("Failed to obtain xauth key: %s", strerror(errno));
	exit (1);
      }

    fread (xauth, sizeof(char), 256, xauth_output);
    xauth[strlen(xauth) - 1] = '\0';
    pclose (xauth_output);
    g_free (tmp);

    if (!strcmp (xauth, ""))
      {
	message_dialog ("Não foi possível obter um cookie de autenticação\n"
			"do servidor X. Impossível continuar.");
	exit (1);
      }

    cookie = g_strdup (xauth);
  }


  { /* read configuration file */
    FILE *fconf;
    gint fconf_fd;
    gchar **tmp, *key, *value;
    struct stat info;
    
    if (stat (CONFFILE, &info) == -1)
      {
	g_warning ("WARNING: Could not stat %s: %s.\n", 
		   CONFFILE, strerror (errno));
      }

    fconf = fopen (CONFFILE, "r");
    if (fconf == NULL)
      {
	g_critical ("Could not open %s: %s.\n", 
		    CONFFILE, strerror (errno));
      }
    else
      {
	fconf_fd = fileno (fconf);

	while (!feof (fconf))
	  {

	    buffer = read_line (fconf_fd);
	    if (!buffer)
	      break;

	    /* remove comments */
	    tmp = g_strsplit (buffer, "#", 2);
	    g_free (buffer);

	    buffer = g_strdup (tmp[0]);
	    g_strfreev (tmp);

	    /* check if we still have a key/value pair */
	    tmp = g_strsplit (buffer, "=", 2);
	    g_free (buffer);
	    if (tmp[1] == NULL || tmp[0] == NULL)
	      {
		g_strfreev (tmp);
		continue;
	      }

	    key = tmp[0];
	    value = tmp[1];

	    g_strstrip (key);
	    g_strstrip (value);

	    if (!strcmp ("host", key))
	      {
		g_free (host);
		host = g_strdup (value);
	      }
	    else if (!strcmp ("port", key))
	      {
		g_free (port);
		port = g_strdup (value);
	      }
	    else if (!strcmp ("sshkey", key))
	      {
		g_free (sshkey);
		sshkey = g_strdup (value);
	      }
	    else if (!strcmp ("session", key))
	      {
		g_free (session);
		session = g_strdup (value);
	      }
	    else if (!strcmp ("ssl", key))
	      {
		if (!strcmp (value, "yes"))
		    use_ssl = 1;
	      }
	    else if (!strcmp ("type", key))
	      {
		g_free (type);
		type = g_strdup (value);
	      }
	    else if (!strcmp ("link", key))
	      {
		g_free (link);
		link = g_strdup (value);
	      }
	    else if (!strcmp ("kbdtype", key))
	      {
		g_free (kbdtype);
		kbdtype = g_strdup (value);
	      }
	    else if (!strcmp ("geometry", key))
	      {
		g_free (geometry);
		geometry = g_strdup (value);
	      }
	    else
	      g_warning ("Unknown option in %s: %s=%s\n", 
			 CONFFILE, key, value);

	    g_strfreev (tmp);
	  }
	fclose (fconf);
      }
  }

  /* grab auth information from the user before anything else */
  input_dialog (&user, &password);

  if (!strcmp (user, "root"))
    {
      message_dialog ("O usuário root não pode entrar por aqui!");
      exit (1);
    }

  pipe (parent_pipe);
  pipe (child_pipe);

  pid = fork ();
  if (pid == -1)
    {
      g_critical ("Could not fork!\n");
      exit (1);
    }
  else if (pid == 0)
    {
      close (child_pipe[1]);
      dup2 (child_pipe[0], STDIN_FILENO);
      dup2 (parent_pipe[1], STDOUT_FILENO);

      nxssh_argv[0] = g_strdup (BINDIR"/nxssh");
      nxssh_argv[1] = g_strdup ("-nx");
      nxssh_argv[2] = g_strdup_printf ("-p%s", port);
      nxssh_argv[3] = g_strdup ("-i");
      nxssh_argv[4] = g_strdup (sshkey);
      nxssh_argv[5] = g_strdup_printf ("nx@%s", host);
      nxssh_argv[6] = g_strdup ("-2");
      nxssh_argv[7] = g_strdup ("-S");
      nxssh_argv[8] = NULL;

      execv (nxssh_argv[0], nxssh_argv);
    }
  else
    {
      close(parent_pipe[1]);

      out = parent_pipe[0];
      in = child_pipe[1];

      /* Handle initial hand-shaking */
      {
	gboolean ssh_authed = FALSE;

	while (!ssh_authed)
	  {
	    buffer = read_code (out);
	    if (!strcmp (buffer, "NX> 205"))
	      {
		flush_buffer (buffer);
		drop_line (out);
		drop_line (out);
		drop_chars (out, 56);
		write_line (in, "yes");
		drop_line (out);
		drop_line (out);

		/* buffer != NULL? but why?! */
		buffer = NULL;
	      }
	    else if (!strcmp (buffer, "NX> 208"))
	      { 
		/* OK, authenticating... */
	      }
	    else if (!strcmp (buffer, "NX> 203") || 
		     (!strcmp (buffer, "NX> 285")) ||
		     (!strcmp (buffer, "NX> 200")) ||
		     (!strcmp (buffer, "NX> 202")))
	      {
		/* ignored stderr */
	      }
	    else if (!strncmp (buffer, "nxssh", 5))
	      {
		gchar *msg;

		flush_buffer (buffer);
		buffer = read_line (out);
		msg = get_info_after_colon (buffer);
		g_free (buffer);

		if (!strcmp (msg, "Name or service not known"))
		  message_dialog ("Não foi possível resolver o nome do servidor.");
		else if (!strcmp (msg, "Connection refused"))
		  message_dialog ("A conexão foi recusada!\n"
				  "Verifique a porta.");
		else if (!strcmp (msg, "Connection timed out"))
		  message_dialog ("Tempo limite da conexão expirou!\n"
				  "Verifique servidor e porta.");

		flush_buffer (msg);
		fprintf (stderr, "\n");
		exit (1);
	      }
	    else if (!strcmp (buffer, "NX> 204"))
	      {
		message_dialog ("Falha na autenticação inicial!\n"
				"Confira a chave privada.");
		g_critical ("Failed to authenticate to SSH using the public key!\n");
		exit (1);
	      }
	    else if (!strcmp (buffer, "HELLO N"))
	      {
		/* OK, time to say HELLO! */
		ssh_authed = TRUE;
	      }
	    else
	      protocol_error ("problems waiting for HELLO");

	    flush_buffer (buffer);

	    buffer = read_line (out);
	    flush_buffer (buffer);
	  }
      }

      /* Handle HELLO */
      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 105"))
	{
	  flush_buffer (buffer);
	  drop_chars (out, 1);
	  write_line (in, "HELLO NXCLIENT - Version 1.4.0");
	  drop_line (out);
	}
      else
	protocol_error ("problems during HELLO");

      /* Handle Login */
      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 134"))
	{
	  flush_buffer (buffer);
	  buffer = read_line (out);
	  flush_buffer (buffer);
	}
      else
	protocol_error ("HELLO failed?");

      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 105"))
	{
	  flush_buffer (buffer);
	  drop_chars (out, 1);
	  write_line (in, "login");
	  drop_line (out);
	}
      else
	protocol_error ("No login? How come!");

      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 101"))
	{
	  flush_buffer (buffer);
	  drop_chars (out, 7);
	  write_line (in, user);
	  drop_line (out);
	}
      else
	protocol_error ("who took my login prompt away?");

      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 102"))
	{
	  flush_buffer (buffer);
	  drop_chars (out, 11);
	  write_line (in, password);
	  drop_line (out);
	}
      else
	protocol_error ("where is my password prompt?");

      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 103"))
	{
	  flush_buffer (buffer);
	  drop_line (out);
	}
      else
	{
	  flush_buffer (buffer);
	  message_dialog ("Login ou senha incorretos!");
	  exit (1);
	}

      buffer = read_code (out);
      if (!strcmp (buffer, "NX> 105"))
	{
	  gchar *m;

	  flush_buffer (buffer);
	  drop_chars (out, 1);

	  m = g_strdup_printf ("list %s", user);
	  write_line (in, m);
	  g_free (m);

	  drop_lines (out, 5);

	  while (1)
	    {
	      buffer = read_code (out);
	      if (!strcmp (buffer, "NX> 105"))
		{
		  flush_buffer (buffer);
		  drop_chars (out, 1);
		  break;
		}

	      flush_buffer (buffer);
	      buffer = read_line (out);
	      restore_id = get_restore_id (buffer);
	    }
	}
      else
	protocol_error ("session startup, buddy, I don't want problems!");
      

      {
	gchar *cmdline;
	
	if (!restore_id)
	  cmdline = g_strdup_printf ("startsession --session=\"%s\" --type=\"%s\" --cache=\"8M\" --images=\"32M\" --cookie=\"%s\" --link=\"%s\" --kbtype=\"%s\" --nodelay=\"1\" --backingstore=\"never\" --geometry=\"%s\" --media=\"0\" --agent_server=\"\" --agent_user=\"\" --agent_password=\"\" --screeninfo=\"%s\" --encryption=\"%d\"", session, type, cookie, link, kbdtype, geometry, screeninfo, use_ssl);
	else
	  cmdline = g_strdup_printf ("restoresession --session=\"%s\" --type=\"%s\" --cache=\"8M\" --images=\"32M\" --cookie=\"%s\" --link=\"%s\" --kbtype=\"%s\" --nodelay=\"1\" --backingstore=\"never\" --geometry=\"%s\" --media=\"0\" --agent_server=\"\" --agent_user=\"\" --agent_password=\"\" --screeninfo=\"%s\" --encryption=\"%d\" --id=\"%s\"", session, type, cookie, link, kbdtype, geometry, screeninfo, use_ssl, restore_id);
	
	write_line (in, cmdline);
	g_free (cmdline);
	cmdline = NULL;
	
	drop_lines (out, 4);
      }

      session_id = get_session_info (out, "NX> 700");
      session_display = get_session_info (out, "NX> 705");
      drop_line (out); /* 703 (session type) */
      pcookie = get_session_info (out, "NX> 701");
      drop_line (out); /* 702 proxy ip */
      drop_line (out); /* 706 agent cookie */
      drop_line (out); /* 704 session cache */
      {
	gchar *tmp = get_session_info (out, "NX> 707"); /* 707 ssl tunneling */
	
	use_ssl = atoi (tmp);
	g_free (tmp);
      }
      drop_line (out); /* 710 session status: running */
      drop_line (out); /* 1002 commit */
      drop_line (out); /* 1006 session status: running */

      read_code (out);
      drop_chars (out, 1);

      /* now prepare to run nxproxy */
      {
	FILE *options;
		
	gchar *dirname;
	gchar *fname;
	gchar *cmdline;
		
	dirname = g_strdup_printf ("%s/.nx/S-%s", homedir, session_id);
	fname = g_strdup_printf ("%s/options", dirname);
		
	g_print ("Dir: %s\nFname: %s\n", dirname, fname);
		
	if (mkdir (dirname, 0777) == -1)
	  {
	    /* BOMB or handle 'directory already exists' */
	  }
	g_free (dirname);
		
	if (use_ssl)
	  buffer = g_strdup_printf ("cookie=%s,root=%s/.nx,session=%s,id=%s,listen=%d:%s", pcookie, homedir, session, session_id, 8008, session_display);
	else
	  buffer = g_strdup_printf ("cookie=%s,root=%s/.nx,session=%s,id=%s,connect=%s:%s", pcookie, homedir, session, session_id, host, session_display);
		
	options = fopen (fname, "w");
	fwrite (buffer, sizeof(char), strlen (buffer), options);
	fclose (options);
		
	g_free (buffer);
		
	cmdline = g_strdup_printf (BINDIR"/nxproxy -S options=%s:%s", fname, session_display);
	system (cmdline);
	g_free (cmdline);
		
	g_free (fname);
      }
    }

  write_line (in, "bye");
  drop_line (out);

  if (use_ssl)
    write_line (in, "switch");

  drop_line (out);
  drop_line (out);
  drop_line (out);

  return 0;
}