Net-OSCAR

 view release on metacpan or  search on metacpan

lib/Net/OSCAR/Connection.pm  view on Meta::CPAN

		die "Proxying not support for listening sockets.\n";
	} else {
		$self->{socket} = gensym;
		socket($self->{socket}, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

		setsockopt($self->{socket}, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) or return $self->{session}->crapout($self, "Couldn't set listen socket options: $!");
		
		my $sockaddr = sockaddr_in($self->{session}->{local_port} || $port || 0, inet_aton($self->{session}->{local_ip} || 0));
		bind($self->{socket}, $sockaddr) or return $self->{session}->crapout("Couldn't bind to desired IP: $!");
		$self->set_blocking(0);
		listen($self->{socket}, SOMAXCONN) or return $self->{session}->crapout("Couldn't listen: $!");

		$self->{state} = "read";
		$self->{rv}->{ft_state} = "listening";
	}

	binmode($self->{socket}) or return $self->{session}->crapout("Couldn't set binmode: $!");
	return 1;
}



sub get_filehandle($) { shift->{socket}; }

# $read/$write tell us if select indicated readiness to read and/or write
# Ditto for $error
sub process_one($;$$$) {
	my($self, $read, $write, $error) = @_;
	my $snac;

	if($error) {
		$self->{sockerr} = 1;
		return $self->disconnect();
	}

	if($write && $self->{outbuff}) {
		$self->log_print(OSCAR_DBG_DEBUG, "Flushing output buffer.");
		$self->flap_put();
	}

	if($write && !$self->{connected}) {
		$self->log_print(OSCAR_DBG_NOTICE, "Connected.");
		$self->{connected} = 1;
		$self->{state} = "read";
		$self->{session}->callback_connection_changed($self, "read");
		return 1;
	} elsif($read && !$self->{ready}) {
		$self->log_print(OSCAR_DBG_DEBUG, "Getting connack.");
		my $flap = $self->flap_get();
		if(!defined($flap)) {
			$self->log_print(OSCAR_DBG_NOTICE, "Couldn't connect.");
			return 0;
		} else {
			$self->log_print(OSCAR_DBG_DEBUG, "Got connack.");
		}

		return $self->{session}->crapout($self, "Got bad connack from server") unless $self->{channel} == FLAP_CHAN_NEWCONN;

		if($self->{conntype} == CONNTYPE_LOGIN) {
			$self->log_print(OSCAR_DBG_DEBUG, "Got connack.  Sending connack.");
			$self->flap_put(pack("N", 1), FLAP_CHAN_NEWCONN) unless $self->{session}->{svcdata}->{hashlogin};
			$self->log_print(OSCAR_DBG_SIGNON, "Connected to login server.");
			$self->{ready} = 1;
			$self->{families} = {23 => 1};

			if(!$self->{session}->{svcdata}->{hashlogin}) {
				$self->proto_send(protobit => "initial_signon_request",
					protodata => {screenname => $self->{session}->{screenname}},
					nopause => 1
				);
			} else {
				$self->proto_send(protobit => "ICQ_signon_request",
					protodata => {signon_tlv($self->{session}, delete($self->{auth}))},
					nopause => 1
				);
			}
		} else {
			$self->log_print(OSCAR_DBG_NOTICE, "Sending BOS-Signon.");
			$self->proto_send(protobit => "BOS_signon",
				reqid => 0x01000000 | (unpack("n", substr($self->{auth}, 0, 2)))[0],
				protodata => {cookie => substr(delete($self->{auth}), 2)},
				nopause => 1
			);
		}
		$self->log_print(OSCAR_DBG_DEBUG, "SNAC time.");
		$self->{ready} = 1;
	} elsif($read) {
		my $no_reread = 0;
		while(1) {
			if(!$self->{session}->{svcdata}->{hashlogin}) {
				$snac = $self->snac_get($no_reread) or return 0;
				Net::OSCAR::Callbacks::process_snac($self, $snac);
			} else {
				my $data = $self->flap_get($no_reread) or return 0;
				$snac = {data => $data, reqid => 0, family => 0x17, subtype => 0x3};
				if($self->{channel} == FLAP_CHAN_CLOSE) {
					$self->{conntype} = CONNTYPE_LOGIN;
					$self->{family} = 0x17;
					$self->{subtype} = 0x3;
					$self->{data} = $data;
					$self->{reqid} = 0;
					$self->{reqdata}->[0x17]->{pack("N", 0)} = "";
					Net::OSCAR::Callbacks::process_snac($self, $snac);
				} else {
					my $snac = $self->snac_decode($data);
					if($snac) {
						Net::OSCAR::Callbacks::process_snac($self, $snac);
					} else {
						return 0;
					}
				}
			}
		} continue {
			$no_reread = 1;
		}
	}
}

sub ready($) {
	my($self) = shift;

	return if $self->{sentready}++;
	send_versions($self, 1);
	$self->unpause();
}

sub session($) { return shift->{session}; }

sub peer_ip($) {
	my($self) = @_;

	my $sockaddr = getpeername($self->{socket});
	my($port, $iaddr) = sockaddr_in($sockaddr);
	return inet_ntoa($iaddr);
}

sub local_ip($) {
	my($self) = @_;

	my $sockaddr = getsockname($self->{socket});
	my($port, $iaddr) = sockaddr_in($sockaddr);
	return inet_ntoa($iaddr);
}

1;



( run in 0.720 second using v1.01-cache-2.11-cpan-13bb782fe5a )