Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added extension for pack_sockaddr_in

  • Loading branch information...
commit 8a00ff5efdb10660a3691369bccd3cc7149e7867 1 parent 2da2710
@davidbalbert authored
View
3  .gitignore
@@ -5,3 +5,6 @@ pkg/*
*.swp
.rvmrc
tags
+tmp
+*.bundle
+*.so
View
6 Rakefile
@@ -1,4 +1,10 @@
require 'bundler/gem_tasks'
+require 'rake/extensiontask'
+
+Rake::ExtensionTask.new('sockaddr') do |ext|
+ ext.lib_dir = "lib/eventless"
+ ext.ext_dir = "ext/sockaddr"
+end
SPECS = [
"test/rubyspec/library/socket/basicsocket",
View
3  eventless.gemspec
@@ -17,8 +17,11 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
+ s.extensions = ["ext/sockaddr/extconf.rb"]
s.add_dependency("cool.io")
s.add_dependency("ruby-cares")
s.add_dependency("ipaddress")
+
+ s.add_development_dependency("rake-compiler")
end
View
4 examples/resolver.rb
@@ -5,3 +5,7 @@
require 'eventless'
puts IPSocket.getaddress("www.google.com")
+
+p Socket.unpack_sockaddr_in(Socket.pack_sockaddr_in(80, "www.google.com"))
+
+p Socket.pack_sockaddr_in(80, "www.google.com")
View
3  ext/sockaddr/extconf.rb
@@ -0,0 +1,3 @@
+require 'mkmf'
+
+create_makefile('eventless/sockaddr')
View
47 ext/sockaddr/sockaddr.c
@@ -0,0 +1,47 @@
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ruby.h>
+
+static VALUE mEventless;
+static VALUE mSockaddr;
+
+VALUE
+rb_eventless_pack_sockaddr_in(VALUE self, VALUE port, VALUE host, VALUE sa_family)
+{
+ VALUE packed_str;
+
+ if (NUM2INT(sa_family) == AF_INET) {
+ struct sockaddr_in a;
+ memset(&a, 0, sizeof(a));
+
+ a.sin_family = AF_INET;
+ a.sin_port = htons(NUM2INT(port));
+ inet_pton(AF_INET, RSTRING_PTR(host), &a.sin_addr);
+ packed_str = rb_str_new((char *)&a, sizeof(struct sockaddr_in));
+ }
+ else if (NUM2INT(sa_family) == AF_INET6) {
+ struct sockaddr_in6 a;
+ memset(&a, 0, sizeof(a));
+
+ a.sin6_family = AF_INET6;
+ a.sin6_port = htons(NUM2INT(port));
+ inet_pton(AF_INET6, RSTRING_PTR(host), &a.sin6_addr);
+ packed_str = rb_str_new((char *)&a, sizeof(struct sockaddr_in6));
+ } else {
+ rb_raise(rb_eArgError, "sa_family must be either Socket::AF_INET or Socket::AF_INET6");
+ }
+
+ return packed_str;
+}
+
+void
+Init_sockaddr(void)
+{
+ mEventless = rb_define_module("Eventless");
+ mSockaddr = rb_define_module_under(mEventless, "Sockaddr");
+
+ rb_define_singleton_method(mSockaddr, "pack_sockaddr_in", rb_eventless_pack_sockaddr_in, 3);
+}
View
27 lib/eventless/socket.rb
@@ -1,6 +1,8 @@
require 'socket'
require 'fcntl'
+require 'eventless/sockaddr'
+
class BasicSocket < IO
##############
# Sending data
@@ -233,6 +235,22 @@ def byte_buffer=(buffer)
end
class Socket < BasicSocket
+
+ class << self
+ alias_method :sockaddr_in_block, :sockaddr_in
+ alias_method :pack_sockaddr_in_block, :pack_sockaddr_in
+
+ def pack_sockaddr_in(port, host)
+ STDERR.puts "Sockaddr.pack_sockaddr_in"
+
+ ip = IPAddress.parse(IPSocket.getaddress(host))
+ family = ip.ipv6? ? Socket::AF_INET6 : Socket::AF_INET
+
+ Eventless::Sockaddr.pack_sockaddr_in(port, ip.to_s, family)
+ end
+ alias_method :sockaddr_in, :pack_sockaddr_in
+ end
+
alias_method :connect_block, :connect
def connect(*args)
STDERR.puts "connect"
@@ -282,6 +300,7 @@ def recvfrom(*args)
pair
end
+
end
module Eventless
@@ -293,16 +312,10 @@ module Eventless
class TCPSocket < ::Socket
def initialize(remote_host, remote_port, local_host=nil, local_port=nil)
super(:INET, :STREAM)
-
- # TODO: Socket.pack_sockaddr_in actually calls getaddrinfo. We're
- # ensuring that remote_host is an ip address at this point, but it would
- # be better to have pack_sockaddr_in resolve the hostname asynchronously
- remote_host = ::IPSocket.getaddress(remote_host)
connect(Socket.pack_sockaddr_in(remote_port, remote_host))
if local_host && local_port
- local_host = IPSocket.getaddress(local_host)
- bind(Sock.pack_sockaddr_in(local_port, local_host))
+ bind(Socket.pack_sockaddr_in(local_port, local_host))
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.