Commit c93da7c7 authored by Russ Cox's avatar Russ Cox

net: doc, doc-inspired cleanup

R=r
DELTA=368  (87 added, 14 deleted, 267 changed)
OCL=25773
CL=25786
parent 5bf0fbe7
...@@ -7,6 +7,7 @@ package net ...@@ -7,6 +7,7 @@ package net
import ( import (
"net"; "net";
"flag"; "flag";
"fmt";
"io"; "io";
"os"; "os";
"testing"; "testing";
...@@ -19,13 +20,13 @@ var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present") ...@@ -19,13 +20,13 @@ var ipv6 = flag.Bool("ipv6", false, "assume ipv6 tunnel is present")
// Run an HTTP request to fetch the appropriate page. // Run an HTTP request to fetch the appropriate page.
func fetchGoogle(t *testing.T, fd net.Conn, network, addr string) { func fetchGoogle(t *testing.T, fd net.Conn, network, addr string) {
req := io.StringBytes("GET /intl/en/privacy.html HTTP/1.0\r\nHost: www.google.com\r\n\r\n"); req := io.StringBytes("GET /intl/en/privacy.html HTTP/1.0\r\nHost: www.google.com\r\n\r\n");
n, errno := fd.Write(req); n, err := fd.Write(req);
buf := make([]byte, 1000); buf := make([]byte, 1000);
n, errno = io.Readn(fd, buf); n, err = io.Readn(fd, buf);
if n < 1000 { if n < 1000 {
t.Errorf("fetchGoogle: short HTTP read from %s %s", network, addr); t.Errorf("fetchGoogle: short HTTP read from %s %s - %v", network, addr, err);
return return
} }
} }
......
...@@ -25,6 +25,7 @@ import ( ...@@ -25,6 +25,7 @@ import (
"strings"; "strings";
) )
// DNS errors returned by LookupHost.
var ( var (
DNS_InternalError = os.NewError("internal dns error"); DNS_InternalError = os.NewError("internal dns error");
DNS_MissingConfig = os.NewError("no dns configuration"); DNS_MissingConfig = os.NewError("no dns configuration");
...@@ -36,18 +37,18 @@ var ( ...@@ -36,18 +37,18 @@ var (
DNS_NameTooLong = os.NewError("dns name too long"); DNS_NameTooLong = os.NewError("dns name too long");
DNS_RedirectLoop = os.NewError("dns redirect loop"); DNS_RedirectLoop = os.NewError("dns redirect loop");
DNS_NameNotFound = os.NewError("dns name not found"); DNS_NameNotFound = os.NewError("dns name not found");
); )
// Send a request on the connection and hope for a reply. // Send a request on the connection and hope for a reply.
// Up to cfg.attempts attempts. // Up to cfg.attempts attempts.
func _Exchange(cfg *DNS_Config, c Conn, name string) (m *DNS_Msg, err *os.Error) { func _Exchange(cfg *_DNS_Config, c Conn, name string) (m *_DNS_Msg, err *os.Error) {
if len(name) >= 256 { if len(name) >= 256 {
return nil, DNS_NameTooLong return nil, DNS_NameTooLong
} }
out := new(DNS_Msg); out := new(_DNS_Msg);
out.id = 0x1234; out.id = 0x1234;
out.question = []DNS_Question{ out.question = []_DNS_Question{
DNS_Question{ name, DNS_TypeA, DNS_ClassINET } _DNS_Question{ name, _DNS_TypeA, _DNS_ClassINET }
}; };
out.recursion_desired = true; out.recursion_desired = true;
msg, ok := out.Pack(); msg, ok := out.Pack();
...@@ -71,7 +72,7 @@ func _Exchange(cfg *DNS_Config, c Conn, name string) (m *DNS_Msg, err *os.Error) ...@@ -71,7 +72,7 @@ func _Exchange(cfg *DNS_Config, c Conn, name string) (m *DNS_Msg, err *os.Error)
continue continue
} }
buf = buf[0:n]; buf = buf[0:n];
in := new(DNS_Msg); in := new(_DNS_Msg);
if !in.Unpack(buf) || in.id != out.id { if !in.Unpack(buf) || in.id != out.id {
continue continue
} }
...@@ -84,13 +85,13 @@ func _Exchange(cfg *DNS_Config, c Conn, name string) (m *DNS_Msg, err *os.Error) ...@@ -84,13 +85,13 @@ func _Exchange(cfg *DNS_Config, c Conn, name string) (m *DNS_Msg, err *os.Error)
// Find answer for name in dns message. // Find answer for name in dns message.
// On return, if err == nil, addrs != nil. // On return, if err == nil, addrs != nil.
// TODO(rsc): Maybe return [][]byte (==[]IPAddr) instead? // TODO(rsc): Maybe return [][]byte (==[]IPAddr) instead?
func answer(name string, dns *DNS_Msg) (addrs []string, err *os.Error) { func answer(name string, dns *_DNS_Msg) (addrs []string, err *os.Error) {
addrs = make([]string, 0, len(dns.answer)); addrs = make([]string, 0, len(dns.answer));
if dns.rcode == DNS_RcodeNameError && dns.authoritative { if dns.rcode == _DNS_RcodeNameError && dns.authoritative {
return nil, DNS_NameNotFound // authoritative "no such host" return nil, DNS_NameNotFound // authoritative "no such host"
} }
if dns.rcode != DNS_RcodeSuccess { if dns.rcode != _DNS_RcodeSuccess {
// None of the error codes make sense // None of the error codes make sense
// for the query we sent. If we didn't get // for the query we sent. If we didn't get
// a name error and we didn't get success, // a name error and we didn't get success,
...@@ -109,16 +110,16 @@ Cname: ...@@ -109,16 +110,16 @@ Cname:
for i := 0; i < len(dns.answer); i++ { for i := 0; i < len(dns.answer); i++ {
rr := dns.answer[i]; rr := dns.answer[i];
h := rr.Header(); h := rr.Header();
if h.class == DNS_ClassINET && h.name == name { if h.class == _DNS_ClassINET && h.name == name {
switch h.rrtype { switch h.rrtype {
case DNS_TypeA: case _DNS_TypeA:
n := len(addrs); n := len(addrs);
a := rr.(*DNS_RR_A).a; a := rr.(*_DNS_RR_A).a;
addrs = addrs[0:n+1]; addrs = addrs[0:n+1];
addrs[n] = fmt.Sprintf("%d.%d.%d.%d", (a>>24), (a>>16)&0xFF, (a>>8)&0xFF, a&0xFF); addrs[n] = fmt.Sprintf("%d.%d.%d.%d", (a>>24), (a>>16)&0xFF, (a>>8)&0xFF, a&0xFF);
case DNS_TypeCNAME: case _DNS_TypeCNAME:
// redirect to cname // redirect to cname
name = rr.(*DNS_RR_CNAME).cname; name = rr.(*_DNS_RR_CNAME).cname;
continue Cname continue Cname
} }
} }
...@@ -135,7 +136,7 @@ Cname: ...@@ -135,7 +136,7 @@ Cname:
// Do a lookup for a single name, which must be rooted // Do a lookup for a single name, which must be rooted
// (otherwise answer will not find the answers). // (otherwise answer will not find the answers).
func tryOneName(cfg *DNS_Config, name string) (addrs []string, err *os.Error) { func tryOneName(cfg *_DNS_Config, name string) (addrs []string, err *os.Error) {
err = DNS_NoServers; err = DNS_NoServers;
for i := 0; i < len(cfg.servers); i++ { for i := 0; i < len(cfg.servers); i++ {
// Calling Dial here is scary -- we have to be sure // Calling Dial here is scary -- we have to be sure
...@@ -165,18 +166,24 @@ func tryOneName(cfg *DNS_Config, name string) (addrs []string, err *os.Error) { ...@@ -165,18 +166,24 @@ func tryOneName(cfg *DNS_Config, name string) (addrs []string, err *os.Error) {
return; return;
} }
var cfg *DNS_Config var cfg *_DNS_Config
var dnserr *os.Error
func loadConfig() { func loadConfig() {
cfg = DNS_ReadConfig(); cfg, dnserr = _DNS_ReadConfig();
} }
func LookupHost(name string) (name1 string, addrs []string, err *os.Error) { // LookupHost looks up the host name using the local DNS resolver.
// It returns the canonical name for the host and an array of that
// host's addresses.
func LookupHost(name string) (cname string, addrs []string, err *os.Error)
{
// TODO(rsc): Pick out obvious non-DNS names to avoid // TODO(rsc): Pick out obvious non-DNS names to avoid
// sending stupid requests to the server? // sending stupid requests to the server?
once.Do(loadConfig); once.Do(loadConfig);
if cfg == nil { if dnserr != nil || cfg == nil {
// better error than file not found.
err = DNS_MissingConfig; err = DNS_MissingConfig;
return; return;
} }
......
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
"strconv"; "strconv";
) )
type DNS_Config struct { type _DNS_Config struct {
servers []string; // servers to use servers []string; // servers to use
search []string; // suffixes to append to local name search []string; // suffixes to append to local name
ndots int; // number of dots in name to trigger absolute lookup ndots int; // number of dots in name to trigger absolute lookup
...@@ -22,24 +22,27 @@ type DNS_Config struct { ...@@ -22,24 +22,27 @@ type DNS_Config struct {
rotate bool; // round robin among servers rotate bool; // round robin among servers
} }
var _DNS_configError *os.Error;
// See resolv.conf(5) on a Linux machine. // See resolv.conf(5) on a Linux machine.
// TODO(rsc): Supposed to call uname() and chop the beginning // TODO(rsc): Supposed to call uname() and chop the beginning
// of the host name to get the default search domain. // of the host name to get the default search domain.
// We assume it's in resolv.conf anyway. // We assume it's in resolv.conf anyway.
func DNS_ReadConfig() *DNS_Config { func _DNS_ReadConfig() (*_DNS_Config, *os.Error) {
// TODO(rsc): 6g won't let me use "file :=" // TODO(rsc): 6g won't let me use "file :="
var file = open("/etc/resolv.conf"); var file *file;
if file == nil { var err *os.Error;
return nil file, err = open("/etc/resolv.conf");
if err != nil {
return nil, err
} }
conf := new(DNS_Config); conf := new(_DNS_Config);
conf.servers = make([]string, 3)[0:0]; // small, but the standard limit conf.servers = make([]string, 3)[0:0]; // small, but the standard limit
conf.search = make([]string, 0); conf.search = make([]string, 0);
conf.ndots = 1; conf.ndots = 1;
conf.timeout = 1; conf.timeout = 1;
conf.attempts = 1; conf.attempts = 1;
conf.rotate = false; conf.rotate = false;
var err *os.Error;
for line, ok := file.readLine(); ok; line, ok = file.readLine() { for line, ok := file.readLine(); ok; line, ok = file.readLine() {
f := getFields(line); f := getFields(line);
if len(f) < 1 { if len(f) < 1 {
...@@ -105,6 +108,6 @@ func DNS_ReadConfig() *DNS_Config { ...@@ -105,6 +108,6 @@ func DNS_ReadConfig() *DNS_Config {
} }
file.close(); file.close();
return conf return conf, nil
} }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// generic pack/unpack routines. // generic pack/unpack routines.
// //
// TODO(rsc) There are enough names defined in this file that they're all // TODO(rsc) There are enough names defined in this file that they're all
// prefixed with DNS_. Perhaps put this in its own package later. // prefixed with _DNS_. Perhaps put this in its own package later.
package net package net
...@@ -33,55 +33,55 @@ import ( ...@@ -33,55 +33,55 @@ import (
// Wire constants. // Wire constants.
const ( const (
// valid DNS_RR_Header.rrtype and DNS_Question.qtype // valid _DNS_RR_Header.rrtype and _DNS_Question.qtype
DNS_TypeA = 1; _DNS_TypeA = 1;
DNS_TypeNS = 2; _DNS_TypeNS = 2;
DNS_TypeMD = 3; _DNS_TypeMD = 3;
DNS_TypeMF = 4; _DNS_TypeMF = 4;
DNS_TypeCNAME = 5; _DNS_TypeCNAME = 5;
DNS_TypeSOA = 6; _DNS_TypeSOA = 6;
DNS_TypeMB = 7; _DNS_TypeMB = 7;
DNS_TypeMG = 8; _DNS_TypeMG = 8;
DNS_TypeMR = 9; _DNS_TypeMR = 9;
DNS_TypeNULL = 10; _DNS_TypeNULL = 10;
DNS_TypeWKS = 11; _DNS_TypeWKS = 11;
DNS_TypePTR = 12; _DNS_TypePTR = 12;
DNS_TypeHINFO = 13; _DNS_TypeHINFO = 13;
DNS_TypeMINFO = 14; _DNS_TypeMINFO = 14;
DNS_TypeMX = 15; _DNS_TypeMX = 15;
DNS_TypeTXT = 16; _DNS_TypeTXT = 16;
// valid DNS_Question.qtype only // valid _DNS_Question.qtype only
DNS_TypeAXFR = 252; _DNS_TypeAXFR = 252;
DNS_TypeMAILB = 253; _DNS_TypeMAILB = 253;
DNS_TypeMAILA = 254; _DNS_TypeMAILA = 254;
DNS_TypeALL = 255; _DNS_TypeALL = 255;
// valid DNS_Question.qclass // valid _DNS_Question.qclass
DNS_ClassINET = 1; _DNS_ClassINET = 1;
DNS_ClassCSNET = 2; _DNS_ClassCSNET = 2;
DNS_ClassCHAOS = 3; _DNS_ClassCHAOS = 3;
DNS_ClassHESIOD = 4; _DNS_ClassHESIOD = 4;
DNS_ClassANY = 255; _DNS_ClassANY = 255;
// DNS_Msg.rcode // _DNS_Msg.rcode
DNS_RcodeSuccess = 0; _DNS_RcodeSuccess = 0;
DNS_RcodeFormatError = 1; _DNS_RcodeFormatError = 1;
DNS_RcodeServerFailure = 2; _DNS_RcodeServerFailure = 2;
DNS_RcodeNameError = 3; _DNS_RcodeNameError = 3;
DNS_RcodeNotImplemented = 4; _DNS_RcodeNotImplemented = 4;
DNS_RcodeRefused = 5; _DNS_RcodeRefused = 5;
) )
// The wire format for the DNS packet header. // The wire format for the DNS packet header.
type _DNS_Header struct { type __DNS_Header struct {
id uint16; id uint16;
bits uint16; bits uint16;
qdcount, ancount, nscount, arcount uint16; qdcount, ancount, nscount, arcount uint16;
} }
const ( const (
// _DNS_Header.bits // __DNS_Header.bits
_QR = 1<<15; // query/response (response=1) _QR = 1<<15; // query/response (response=1)
_AA = 1<<10; // authoritative _AA = 1<<10; // authoritative
_TC = 1<<9; // truncated _TC = 1<<9; // truncated
...@@ -90,7 +90,7 @@ const ( ...@@ -90,7 +90,7 @@ const (
) )
// DNS queries. // DNS queries.
type DNS_Question struct { type _DNS_Question struct {
name string "domain-name"; // "domain-name" specifies encoding; see packers below name string "domain-name"; // "domain-name" specifies encoding; see packers below
qtype uint16; qtype uint16;
qclass uint16; qclass uint16;
...@@ -99,7 +99,7 @@ type DNS_Question struct { ...@@ -99,7 +99,7 @@ type DNS_Question struct {
// DNS responses (resource records). // DNS responses (resource records).
// There are many types of messages, // There are many types of messages,
// but they all share the same header. // but they all share the same header.
type DNS_RR_Header struct { type _DNS_RR_Header struct {
name string "domain-name"; name string "domain-name";
rrtype uint16; rrtype uint16;
class uint16; class uint16;
...@@ -107,67 +107,67 @@ type DNS_RR_Header struct { ...@@ -107,67 +107,67 @@ type DNS_RR_Header struct {
rdlength uint16; // length of data after header rdlength uint16; // length of data after header
} }
func (h *DNS_RR_Header) Header() *DNS_RR_Header { func (h *_DNS_RR_Header) Header() *_DNS_RR_Header {
return h return h
} }
type DNS_RR interface { type _DNS_RR interface {
Header() *DNS_RR_Header Header() *_DNS_RR_Header
} }
// Specific DNS RR formats for each query type. // Specific DNS RR formats for each query type.
type DNS_RR_CNAME struct { type _DNS_RR_CNAME struct {
DNS_RR_Header; _DNS_RR_Header;
cname string "domain-name"; cname string "domain-name";
} }
type DNS_RR_HINFO struct { type _DNS_RR_HINFO struct {
DNS_RR_Header; _DNS_RR_Header;
cpu string; cpu string;
os string; os string;
} }
type DNS_RR_MB struct { type _DNS_RR_MB struct {
DNS_RR_Header; _DNS_RR_Header;
mb string "domain-name"; mb string "domain-name";
} }
type DNS_RR_MG struct { type _DNS_RR_MG struct {
DNS_RR_Header; _DNS_RR_Header;
mg string "domain-name"; mg string "domain-name";
} }
type DNS_RR_MINFO struct { type _DNS_RR_MINFO struct {
DNS_RR_Header; _DNS_RR_Header;
rmail string "domain-name"; rmail string "domain-name";
email string "domain-name"; email string "domain-name";
} }
type DNS_RR_MR struct { type _DNS_RR_MR struct {
DNS_RR_Header; _DNS_RR_Header;
mr string "domain-name"; mr string "domain-name";
} }
type DNS_RR_MX struct { type _DNS_RR_MX struct {
DNS_RR_Header; _DNS_RR_Header;
pref uint16; pref uint16;
mx string "domain-name"; mx string "domain-name";
} }
type DNS_RR_NS struct { type _DNS_RR_NS struct {
DNS_RR_Header; _DNS_RR_Header;
ns string "domain-name"; ns string "domain-name";
} }
type DNS_RR_PTR struct { type _DNS_RR_PTR struct {
DNS_RR_Header; _DNS_RR_Header;
ptr string "domain-name"; ptr string "domain-name";
} }
type DNS_RR_SOA struct { type _DNS_RR_SOA struct {
DNS_RR_Header; _DNS_RR_Header;
ns string "domain-name"; ns string "domain-name";
mbox string "domain-name"; mbox string "domain-name";
serial uint32; serial uint32;
...@@ -177,13 +177,13 @@ type DNS_RR_SOA struct { ...@@ -177,13 +177,13 @@ type DNS_RR_SOA struct {
minttl uint32; minttl uint32;
} }
type DNS_RR_TXT struct { type _DNS_RR_TXT struct {
DNS_RR_Header; _DNS_RR_Header;
txt string; // not domain name txt string; // not domain name
} }
type DNS_RR_A struct { type _DNS_RR_A struct {
DNS_RR_Header; _DNS_RR_Header;
a uint32 "ipv4"; a uint32 "ipv4";
} }
...@@ -197,19 +197,19 @@ type DNS_RR_A struct { ...@@ -197,19 +197,19 @@ type DNS_RR_A struct {
// packing sequence. // packing sequence.
// Map of constructors for each RR wire type. // Map of constructors for each RR wire type.
var rr_mk = map[int] func()DNS_RR { var rr_mk = map[int] func()_DNS_RR {
DNS_TypeCNAME: func() DNS_RR { return new(DNS_RR_CNAME) }, _DNS_TypeCNAME: func() _DNS_RR { return new(_DNS_RR_CNAME) },
DNS_TypeHINFO: func() DNS_RR { return new(DNS_RR_HINFO) }, _DNS_TypeHINFO: func() _DNS_RR { return new(_DNS_RR_HINFO) },
DNS_TypeMB: func() DNS_RR { return new(DNS_RR_MB) }, _DNS_TypeMB: func() _DNS_RR { return new(_DNS_RR_MB) },
DNS_TypeMG: func() DNS_RR { return new(DNS_RR_MG) }, _DNS_TypeMG: func() _DNS_RR { return new(_DNS_RR_MG) },
DNS_TypeMINFO: func() DNS_RR { return new(DNS_RR_MINFO) }, _DNS_TypeMINFO: func() _DNS_RR { return new(_DNS_RR_MINFO) },
DNS_TypeMR: func() DNS_RR { return new(DNS_RR_MR) }, _DNS_TypeMR: func() _DNS_RR { return new(_DNS_RR_MR) },
DNS_TypeMX: func() DNS_RR { return new(DNS_RR_MX) }, _DNS_TypeMX: func() _DNS_RR { return new(_DNS_RR_MX) },
DNS_TypeNS: func() DNS_RR { return new(DNS_RR_NS) }, _DNS_TypeNS: func() _DNS_RR { return new(_DNS_RR_NS) },
DNS_TypePTR: func() DNS_RR { return new(DNS_RR_PTR) }, _DNS_TypePTR: func() _DNS_RR { return new(_DNS_RR_PTR) },
DNS_TypeSOA: func() DNS_RR { return new(DNS_RR_SOA) }, _DNS_TypeSOA: func() _DNS_RR { return new(_DNS_RR_SOA) },
DNS_TypeTXT: func() DNS_RR { return new(DNS_RR_TXT) }, _DNS_TypeTXT: func() _DNS_RR { return new(_DNS_RR_TXT) },
DNS_TypeA: func() DNS_RR { return new(DNS_RR_A) }, _DNS_TypeA: func() _DNS_RR { return new(_DNS_RR_A) },
} }
// Pack a domain name s into msg[off:]. // Pack a domain name s into msg[off:].
...@@ -480,7 +480,7 @@ func printStruct(any interface{}) string { ...@@ -480,7 +480,7 @@ func printStruct(any interface{}) string {
} }
// Resource record packer. // Resource record packer.
func packRR(rr DNS_RR, msg []byte, off int) (off2 int, ok bool) { func packRR(rr _DNS_RR, msg []byte, off int) (off2 int, ok bool) {
var off1 int; var off1 int;
// pack twice, once to find end of header // pack twice, once to find end of header
// and again to find end of packet. // and again to find end of packet.
...@@ -499,9 +499,9 @@ func packRR(rr DNS_RR, msg []byte, off int) (off2 int, ok bool) { ...@@ -499,9 +499,9 @@ func packRR(rr DNS_RR, msg []byte, off int) (off2 int, ok bool) {
} }
// Resource record unpacker. // Resource record unpacker.
func unpackRR(msg []byte, off int) (rr DNS_RR, off1 int, ok bool) { func unpackRR(msg []byte, off int) (rr _DNS_RR, off1 int, ok bool) {
// unpack just the header, to find the rr type and length // unpack just the header, to find the rr type and length
var h DNS_RR_Header; var h _DNS_RR_Header;
off0 := off; off0 := off;
if off, ok = unpackStruct(&h, msg, off); !ok { if off, ok = unpackStruct(&h, msg, off); !ok {
return nil, len(msg), false return nil, len(msg), false
...@@ -526,7 +526,7 @@ func unpackRR(msg []byte, off int) (rr DNS_RR, off1 int, ok bool) { ...@@ -526,7 +526,7 @@ func unpackRR(msg []byte, off int) (rr DNS_RR, off1 int, ok bool) {
// A manually-unpacked version of (id, bits). // A manually-unpacked version of (id, bits).
// This is in its own struct for easy printing. // This is in its own struct for easy printing.
type _DNS_Msg_Top struct { type __DNS_Msg_Top struct {
id uint16; id uint16;
response bool; response bool;
opcode int; opcode int;
...@@ -537,19 +537,19 @@ type _DNS_Msg_Top struct { ...@@ -537,19 +537,19 @@ type _DNS_Msg_Top struct {
rcode int; rcode int;
} }
type DNS_Msg struct { type _DNS_Msg struct {
_DNS_Msg_Top; __DNS_Msg_Top;
question []DNS_Question; question []_DNS_Question;
answer []DNS_RR; answer []_DNS_RR;
ns []DNS_RR; ns []_DNS_RR;
extra []DNS_RR; extra []_DNS_RR;
} }
func (dns *DNS_Msg) Pack() (msg []byte, ok bool) { func (dns *_DNS_Msg) Pack() (msg []byte, ok bool) {
var dh _DNS_Header; var dh __DNS_Header;
// Convert convenient DNS_Msg into wire-like _DNS_Header. // Convert convenient _DNS_Msg into wire-like __DNS_Header.
dh.id = dns.id; dh.id = dns.id;
dh.bits = uint16(dns.opcode)<<11 | uint16(dns.rcode); dh.bits = uint16(dns.opcode)<<11 | uint16(dns.rcode);
if dns.recursion_available { if dns.recursion_available {
...@@ -605,9 +605,9 @@ func (dns *DNS_Msg) Pack() (msg []byte, ok bool) { ...@@ -605,9 +605,9 @@ func (dns *DNS_Msg) Pack() (msg []byte, ok bool) {
return msg[0:off], true return msg[0:off], true
} }
func (dns *DNS_Msg) Unpack(msg []byte) bool { func (dns *_DNS_Msg) Unpack(msg []byte) bool {
// Header. // Header.
var dh _DNS_Header; var dh __DNS_Header;
off := 0; off := 0;
var ok bool; var ok bool;
if off, ok = unpackStruct(&dh, msg, off); !ok { if off, ok = unpackStruct(&dh, msg, off); !ok {
...@@ -623,10 +623,10 @@ func (dns *DNS_Msg) Unpack(msg []byte) bool { ...@@ -623,10 +623,10 @@ func (dns *DNS_Msg) Unpack(msg []byte) bool {
dns.rcode = int(dh.bits & 0xF); dns.rcode = int(dh.bits & 0xF);
// Arrays. // Arrays.
dns.question = make([]DNS_Question, dh.qdcount); dns.question = make([]_DNS_Question, dh.qdcount);
dns.answer = make([]DNS_RR, dh.ancount); dns.answer = make([]_DNS_RR, dh.ancount);
dns.ns = make([]DNS_RR, dh.nscount); dns.ns = make([]_DNS_RR, dh.nscount);
dns.extra = make([]DNS_RR, dh.arcount); dns.extra = make([]_DNS_RR, dh.arcount);
for i := 0; i < len(dns.question); i++ { for i := 0; i < len(dns.question); i++ {
off, ok = unpackStruct(&dns.question[i], msg, off); off, ok = unpackStruct(&dns.question[i], msg, off);
...@@ -649,8 +649,8 @@ func (dns *DNS_Msg) Unpack(msg []byte) bool { ...@@ -649,8 +649,8 @@ func (dns *DNS_Msg) Unpack(msg []byte) bool {
return true return true
} }
func (dns *DNS_Msg) String() string { func (dns *_DNS_Msg) String() string {
s := "DNS: "+printStruct(&dns._DNS_Msg_Top)+"\n"; s := "DNS: "+printStruct(&dns.__DNS_Msg_Top)+"\n";
if len(dns.question) > 0 { if len(dns.question) > 0 {
s += "-- Questions\n"; s += "-- Questions\n";
for i := 0; i < len(dns.question); i++ { for i := 0; i < len(dns.question); i++ {
......
...@@ -75,7 +75,7 @@ type pollServer struct { ...@@ -75,7 +75,7 @@ type pollServer struct {
cr, cw chan *netFD; // buffered >= 1 cr, cw chan *netFD; // buffered >= 1
pr, pw *os.FD; pr, pw *os.FD;
pending map[int64] *netFD; pending map[int64] *netFD;
poll *Pollster; // low-level OS hooks poll *pollster; // low-level OS hooks
} }
func (s *pollServer) Run(); func (s *pollServer) Run();
...@@ -95,7 +95,7 @@ func newPollServer() (s *pollServer, err *os.Error) { ...@@ -95,7 +95,7 @@ func newPollServer() (s *pollServer, err *os.Error) {
if err = setNonblock(s.pw.Fd()); err != nil { if err = setNonblock(s.pw.Fd()); err != nil {
goto Error goto Error
} }
if s.poll, err = NewPollster(); err != nil { if s.poll, err = newpollster(); err != nil {
goto Error goto Error
} }
if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil { if err = s.poll.AddFD(s.pr.Fd(), 'r', true); err != nil {
......
...@@ -12,14 +12,14 @@ import ( ...@@ -12,14 +12,14 @@ import (
"syscall"; "syscall";
) )
type Pollster struct { type pollster struct {
kq int64; kq int64;
eventbuf [10]syscall.Kevent_t; eventbuf [10]syscall.Kevent_t;
events []syscall.Kevent_t; events []syscall.Kevent_t;
} }
func NewPollster() (p *Pollster, err *os.Error) { func newpollster() (p *pollster, err *os.Error) {
p = new(Pollster); p = new(pollster);
var e int64; var e int64;
if p.kq, e = syscall.Kqueue(); e != 0 { if p.kq, e = syscall.Kqueue(); e != 0 {
return nil, os.ErrnoToError(e) return nil, os.ErrnoToError(e)
...@@ -28,7 +28,7 @@ func NewPollster() (p *Pollster, err *os.Error) { ...@@ -28,7 +28,7 @@ func NewPollster() (p *Pollster, err *os.Error) {
return p, nil return p, nil
} }
func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error { func (p *pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
var kmode int16; var kmode int16;
if mode == 'r' { if mode == 'r' {
kmode = syscall.EVFILT_READ kmode = syscall.EVFILT_READ
...@@ -62,7 +62,7 @@ func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error { ...@@ -62,7 +62,7 @@ func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
return nil return nil
} }
func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) { func (p *pollster) WaitFD() (fd int64, mode int, err *os.Error) {
for len(p.events) == 0 { for len(p.events) == 0 {
nn, e := syscall.Kevent(p.kq, nil, p.eventbuf, nil); nn, e := syscall.Kevent(p.kq, nil, p.eventbuf, nil);
if e != 0 { if e != 0 {
...@@ -84,7 +84,7 @@ func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) { ...@@ -84,7 +84,7 @@ func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) {
return fd, mode, nil return fd, mode, nil
} }
func (p *Pollster) Close() *os.Error { func (p *pollster) Close() *os.Error {
r, e := syscall.Close(p.kq); r, e := syscall.Close(p.kq);
return os.ErrnoToError(e) return os.ErrnoToError(e)
} }
...@@ -17,15 +17,15 @@ const ( ...@@ -17,15 +17,15 @@ const (
writeFlags = syscall.EPOLLOUT writeFlags = syscall.EPOLLOUT
) )
type Pollster struct { type pollster struct {
epfd int64; epfd int64;
// Events we're already waiting for // Events we're already waiting for
events map[int64] uint32; events map[int64] uint32;
} }
func NewPollster() (p *Pollster, err *os.Error) { func newpollster() (p *pollster, err *os.Error) {
p = new(Pollster); p = new(pollster);
var e int64; var e int64;
// The arg to epoll_create is a hint to the kernel // The arg to epoll_create is a hint to the kernel
...@@ -38,7 +38,7 @@ func NewPollster() (p *Pollster, err *os.Error) { ...@@ -38,7 +38,7 @@ func NewPollster() (p *Pollster, err *os.Error) {
return p, nil return p, nil
} }
func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error { func (p *pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
var ev syscall.EpollEvent; var ev syscall.EpollEvent;
var already bool; var already bool;
ev.Fd = int32(fd); ev.Fd = int32(fd);
...@@ -65,7 +65,7 @@ func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error { ...@@ -65,7 +65,7 @@ func (p *Pollster) AddFD(fd int64, mode int, repeat bool) *os.Error {
return nil return nil
} }
func (p *Pollster) StopWaiting(fd int64, bits uint) { func (p *pollster) StopWaiting(fd int64, bits uint) {
events, already := p.events[fd]; events, already := p.events[fd];
if !already { if !already {
print("Epoll unexpected fd=", fd, "\n"); print("Epoll unexpected fd=", fd, "\n");
...@@ -98,7 +98,7 @@ func (p *Pollster) StopWaiting(fd int64, bits uint) { ...@@ -98,7 +98,7 @@ func (p *Pollster) StopWaiting(fd int64, bits uint) {
} }
} }
func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) { func (p *pollster) WaitFD() (fd int64, mode int, err *os.Error) {
// Get an event. // Get an event.
var evarray [1]syscall.EpollEvent; var evarray [1]syscall.EpollEvent;
ev := &evarray[0]; ev := &evarray[0];
...@@ -130,7 +130,7 @@ func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) { ...@@ -130,7 +130,7 @@ func (p *Pollster) WaitFD() (fd int64, mode int, err *os.Error) {
return fd, 'r', nil return fd, 'r', nil
} }
func (p *Pollster) Close() *os.Error { func (p *pollster) Close() *os.Error {
r, e := syscall.Close(p.epfd); r, e := syscall.Close(p.epfd);
return os.ErrnoToError(e) return os.ErrnoToError(e)
} }
...@@ -16,13 +16,32 @@ import ( ...@@ -16,13 +16,32 @@ import (
"net" "net"
) )
// IP address lengths (bytes).
const ( const (
IPv4len = 4; IPv4len = 4;
IPv6len = 16 IPv6len = 16
) )
// Make the 4 bytes into an IPv4 address (in IPv6 form) // An IP is a single IP address, an array of bytes.
func makeIPv4(a, b, c, d byte) []byte { // Functions in this package accept either 4-byte (IP v4)
// or 16-byte (IP v6) arrays as input. Unless otherwise
// specified, functions in this package always return
// IP addresses in 16-byte form using the canonical
// embedding.
//
// Note that in this documentation, referring to an
// IP address as an IPv4 address or an IPv6 address
// is a semantic property of the address, not just the
// length of the byte array: a 16-byte array can still
// be an IPv4 address.
type IP []byte;
// An IP mask is an IP address.
type IPMask []byte;
// IPv4 returns the IP address (in 16-byte form) of the
// IPv4 address a.b.c.d.
func IPv4(a, b, c, d byte) IP {
p := make([]byte, IPv6len); p := make([]byte, IPv6len);
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
p[i] = 0 p[i] = 0
...@@ -36,20 +55,17 @@ func makeIPv4(a, b, c, d byte) []byte { ...@@ -36,20 +55,17 @@ func makeIPv4(a, b, c, d byte) []byte {
return p return p
} }
// Well-known IP addresses // Well-known IPv4 addresses
var IPv4bcast, IPv4allsys, IPv4allrouter, IPv4prefix, IPallbits, IPnoaddr []byte var (
IPv4bcast = IPv4(255, 255, 255, 255); // broadcast
IPv4allsys = IPv4(224, 0, 0, 1); // all systems
IPv4allrouter = IPv4(224, 0, 0, 2); // all routers
)
func init() { // Well-known IPv6 addresses
IPv4bcast = makeIPv4(0xff, 0xff, 0xff, 0xff); var (
IPv4allsys = makeIPv4(0xe0, 0x00, 0x00, 0x01); IPzero = make(IP, IPv6len); // all zeros
IPv4allrouter = makeIPv4(0xe0, 0x00, 0x00, 0x02); )
IPv4prefix = makeIPv4(0, 0, 0, 0);
IPallbits = make([]byte, IPv6len);
for i := 0; i < IPv6len; i++ {
IPallbits[i] = 0xff
}
IPnoaddr = make([]byte, IPv6len); // zeroed
}
// Is p all zeros? // Is p all zeros?
func isZeros(p []byte) bool { func isZeros(p []byte) bool {
...@@ -61,61 +77,65 @@ func isZeros(p []byte) bool { ...@@ -61,61 +77,65 @@ func isZeros(p []byte) bool {
return true return true
} }
// Is p an IPv4 address (perhaps in IPv6 form)? // To4 converts the IPv4 address ip to a 4-byte representation.
// If so, return the 4-byte V4 array. // If ip is not an IPv4 address, To4 returns nil.
func ToIPv4(p []byte) []byte { func (ip IP) To4() IP {
if len(p) == IPv4len { if len(ip) == IPv4len {
return p return ip
} }
if len(p) == IPv6len if len(ip) == IPv6len
&& isZeros(p[0:10]) && isZeros(ip[0:10])
&& p[10] == 0xff && ip[10] == 0xff
&& p[11] == 0xff { && ip[11] == 0xff {
return p[12:16] return ip[12:16]
} }
return nil return nil
} }
// Convert p to IPv6 form. // To16 converts the IP address ip to a 16-byte representation.
func ToIPv6(p []byte) []byte { // If ip is not an IP address (it is the wrong length), To16 returns nil.
if len(p) == IPv4len { func (ip IP) To16() IP {
return makeIPv4(p[0], p[1], p[2], p[3]) if len(ip) == IPv4len {
return IPv4(ip[0], ip[1], ip[2], ip[3])
} }
if len(p) == IPv6len { if len(ip) == IPv6len {
return p return ip
} }
return nil return nil
} }
// Default route masks for IPv4. // Default route masks for IPv4.
var ( var (
ClassAMask = makeIPv4(0xff, 0, 0, 0); classAMask IPMask = IPv4(0xff, 0, 0, 0);
ClassBMask = makeIPv4(0xff, 0xff, 0, 0); classBMask IPMask = IPv4(0xff, 0xff, 0, 0);
ClassCMask = makeIPv4(0xff, 0xff, 0xff, 0); classCMask IPMask = IPv4(0xff, 0xff, 0xff, 0);
) )
func DefaultMask(p []byte) []byte { // DefaultMask returns the default IP mask for the IP address ip.
if p = ToIPv4(p); p == nil { // Only IPv4 addresses have default masks; DefaultMask returns
// nil if ip is not a valid IPv4 address.
func (ip IP) DefaultMask() IPMask {
if ip = ip.To4(); ip == nil {
return nil return nil
} }
switch true { switch true {
case p[0] < 0x80: case ip[0] < 0x80:
return ClassAMask; return classAMask;
case p[0] < 0xC0: case ip[0] < 0xC0:
return ClassBMask; return classBMask;
default: default:
return ClassCMask; return classCMask;
} }
return nil; // not reached return nil; // not reached
} }
// Apply mask to ip, returning new address. // Mask returns the result of masking the IP address ip with mask.
func Mask(ip []byte, mask []byte) []byte { func (ip IP) Mask(mask IPMask) IP {
n := len(ip); n := len(ip);
if n != len(mask) { if n != len(mask) {
return nil return nil
} }
out := make([]byte, n); out := make(IP, n);
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
out[i] = ip[i] & mask[i]; out[i] = ip[i] & mask[i];
} }
...@@ -137,7 +157,6 @@ func itod(i uint) string { ...@@ -137,7 +157,6 @@ func itod(i uint) string {
} }
return string(b[bp:len(b)]) return string(b[bp:len(b)])
// return string((&b)[bp:len(b)])
} }
// Convert i to hexadecimal string. // Convert i to hexadecimal string.
...@@ -155,13 +174,17 @@ func itox(i uint) string { ...@@ -155,13 +174,17 @@ func itox(i uint) string {
} }
return string(b[bp:len(b)]) return string(b[bp:len(b)])
// return string((&b)[bp:len(b)])
} }
// Convert IP address to string. // String returns the string form of the IP address ip.
func IPToString(p []byte) string { // If the address is an IPv4 address, the string representation
// is dotted decimal ("74.125.19.99"). Otherwise the representation
// is IPv6 ("2001:4860:0:2001::68").
func (ip IP) String() string {
p := ip;
// If IPv4, use dotted notation. // If IPv4, use dotted notation.
if p4 := ToIPv4(p); len(p4) == 4 { if p4 := p.To4(); len(p4) == 4 {
return itod(uint(p4[0]))+"." return itod(uint(p4[0]))+"."
+itod(uint(p4[1]))+"." +itod(uint(p4[1]))+"."
+itod(uint(p4[2]))+"." +itod(uint(p4[2]))+"."
...@@ -204,7 +227,7 @@ func IPToString(p []byte) string { ...@@ -204,7 +227,7 @@ func IPToString(p []byte) string {
// If mask is a sequence of 1 bits followed by 0 bits, // If mask is a sequence of 1 bits followed by 0 bits,
// return the number of 1 bits. // return the number of 1 bits.
func simpleMaskLength(mask []byte) int { func simpleMaskLength(mask IP) int {
var i int; var i int;
for i = 0; i < len(mask); i++ { for i = 0; i < len(mask); i++ {
if mask[i] != 0xFF { if mask[i] != 0xFF {
...@@ -228,7 +251,12 @@ func simpleMaskLength(mask []byte) int { ...@@ -228,7 +251,12 @@ func simpleMaskLength(mask []byte) int {
return n return n
} }
func MaskToString(mask []byte) string { // String returns the string representation of mask.
// If the mask is in the canonical form--ones followed by zeros--the
// string representation is just the decimal number of ones.
// If the mask is in a non-canonical form, it is formatted
// as an IP address.
func (mask IPMask) String() string {
switch len(mask) { switch len(mask) {
case 4: case 4:
n := simpleMaskLength(mask); n := simpleMaskLength(mask);
...@@ -241,11 +269,11 @@ func MaskToString(mask []byte) string { ...@@ -241,11 +269,11 @@ func MaskToString(mask []byte) string {
return itod(uint(n)) return itod(uint(n))
} }
} }
return IPToString(mask) return IP(mask).String();
} }
// Parse IPv4 address (d.d.d.d). // Parse IPv4 address (d.d.d.d).
func parseIPv4(s string) []byte { func parseIPv4(s string) IP {
var p [IPv4len]byte; var p [IPv4len]byte;
i := 0; i := 0;
for j := 0; j < IPv4len; j++ { for j := 0; j < IPv4len; j++ {
...@@ -268,7 +296,7 @@ func parseIPv4(s string) []byte { ...@@ -268,7 +296,7 @@ func parseIPv4(s string) []byte {
if i != len(s) { if i != len(s) {
return nil return nil
} }
return makeIPv4(p[0], p[1], p[2], p[3]) return IPv4(p[0], p[1], p[2], p[3])
} }
// Parse IPv6 address. Many forms. // Parse IPv6 address. Many forms.
...@@ -279,8 +307,8 @@ func parseIPv4(s string) []byte { ...@@ -279,8 +307,8 @@ func parseIPv4(s string) []byte {
// * A run of zeros can be replaced with "::". // * A run of zeros can be replaced with "::".
// * The last 32 bits can be in IPv4 form. // * The last 32 bits can be in IPv4 form.
// Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4. // Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4.
func parseIPv6(s string) []byte { func parseIPv6(s string) IP {
p := make([]byte, 16); p := make(IP, 16);
ellipsis := -1; // position of ellipsis in p ellipsis := -1; // position of ellipsis in p
i := 0; // index in string s i := 0; // index in string s
...@@ -377,7 +405,12 @@ L: for j < IPv6len { ...@@ -377,7 +405,12 @@ L: for j < IPv6len {
return p return p
} }
func ParseIP(s string) []byte { // ParseIP parses s as an IP address, returning the result.
// The string s can be in dotted decimal ("74.125.19.99")
// or IPv6 ("2001:4860:0:2001::68") form.
// If s is not a valid textual representation of an IP address,
// ParseIP returns nil.
func ParseIP(s string) IP {
p := parseIPv4(s); p := parseIPv4(s);
if p != nil { if p != nil {
return p return p
......
...@@ -16,12 +16,10 @@ var ( ...@@ -16,12 +16,10 @@ var (
MissingAddress = os.NewError("missing address"); MissingAddress = os.NewError("missing address");
UnknownNetwork = os.NewError("unknown network"); UnknownNetwork = os.NewError("unknown network");
UnknownHost = os.NewError("unknown host"); UnknownHost = os.NewError("unknown host");
DNS_Error = os.NewError("dns error looking up host"); UnknownSocketFamily = os.NewError("unknown socket family");
UnknownPort = os.NewError("unknown port");
UnknownsocketFamily = os.NewError("unknown socket family");
) )
func LookupHost(name string) (name1 string, addrs []string, err *os.Error) func LookupHost(name string) (cname string, addrs []string, err *os.Error)
// Split "host:port" into "host" and "port". // Split "host:port" into "host" and "port".
// Host cannot contain colons unless it is bracketed. // Host cannot contain colons unless it is bracketed.
...@@ -75,7 +73,7 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err ...@@ -75,7 +73,7 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err
var addr []byte; var addr []byte;
if host == "" { if host == "" {
if mode == "listen" { if mode == "listen" {
addr = IPnoaddr; // wildcard - listen to all addr = IPzero; // wildcard - listen to all
} else { } else {
return nil, 0, MissingAddress; return nil, 0, MissingAddress;
} }
...@@ -103,9 +101,9 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err ...@@ -103,9 +101,9 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err
p, i, ok := dtoi(port, 0); p, i, ok := dtoi(port, 0);
if !ok || i != len(port) { if !ok || i != len(port) {
p, ok = LookupPort(net, port); p, err = LookupPort(net, port);
if !ok { if err != nil {
return nil, 0, UnknownPort return nil, 0, err
} }
} }
if p < 0 || p > 0xFFFF { if p < 0 || p > 0xFFFF {
...@@ -119,14 +117,14 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err ...@@ -119,14 +117,14 @@ func hostPortToIP(net, hostport, mode string) (ip []byte, iport int, err *os.Err
func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err *os.Error) { func sockaddrToHostPort(sa *syscall.Sockaddr) (hostport string, err *os.Error) {
switch sa.Family { switch sa.Family {
case syscall.AF_INET, syscall.AF_INET6: case syscall.AF_INET, syscall.AF_INET6:
addr, port, e := SockaddrToIP(sa); addr, port, e := sockaddrToIP(sa);
if e != nil { if e != nil {
return "", e return "", e
} }
host := IPToString(addr); host := addr.String();
return joinHostPort(host, strconv.Itoa(port)), nil; return joinHostPort(host, strconv.Itoa(port)), nil;
default: default:
return "", UnknownsocketFamily return "", UnknownSocketFamily
} }
return "", nil // not reached return "", nil // not reached
} }
...@@ -308,7 +306,7 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string) ...@@ -308,7 +306,7 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string)
(fd *netFD, err *os.Error) (fd *netFD, err *os.Error)
{ {
// Parse addresses (unless they are empty). // Parse addresses (unless they are empty).
var lip, rip []byte; var lip, rip IP;
var lport, rport int; var lport, rport int;
var lerr, rerr *os.Error; var lerr, rerr *os.Error;
...@@ -336,7 +334,7 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string) ...@@ -336,7 +334,7 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string)
default: default:
// Otherwise, guess. // Otherwise, guess.
// If the addresses are IPv4 and we prefer IPv4, use 4; else 6. // If the addresses are IPv4 and we prefer IPv4, use 4; else 6.
if preferIPv4 && ToIPv4(lip) != nil && ToIPv4(rip) != nil { if preferIPv4 && lip.To4() != nil && rip.To4() != nil {
vers = 4 vers = 4
} else { } else {
vers = 6 vers = 6
...@@ -346,10 +344,10 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string) ...@@ -346,10 +344,10 @@ func internetSocket(net, laddr, raddr string, proto int64, mode string)
var cvt func(addr []byte, port int) (sa *syscall.Sockaddr, err *os.Error); var cvt func(addr []byte, port int) (sa *syscall.Sockaddr, err *os.Error);
var family int64; var family int64;
if vers == 4 { if vers == 4 {
cvt = IPv4ToSockaddr; cvt = v4ToSockaddr;
family = syscall.AF_INET family = syscall.AF_INET
} else { } else {
cvt = IPv6ToSockaddr; cvt = v6ToSockaddr;
family = syscall.AF_INET6 family = syscall.AF_INET6
} }
...@@ -437,13 +435,17 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err *os.Error) { ...@@ -437,13 +435,17 @@ func DialUDP(net, laddr, raddr string) (c *ConnUDP, err *os.Error) {
// TODO: raw ethernet connections // TODO: raw ethernet connections
// A Conn is a generic network connection.
type Conn interface { type Conn interface {
Read(b []byte) (n int, err *os.Error); Read(b []byte) (n int, err *os.Error);
Write(b []byte) (n int, err *os.Error); Write(b []byte) (n int, err *os.Error);
Close() *os.Error;
// For UDP sockets.
ReadFrom(b []byte) (n int, addr string, err *os.Error); ReadFrom(b []byte) (n int, addr string, err *os.Error);
WriteTo(addr string, b []byte) (n int, err *os.Error); WriteTo(addr string, b []byte) (n int, err *os.Error);
Close() *os.Error;
// Methods that have meaning only on some networks.
SetReadBuffer(bytes int) *os.Error; SetReadBuffer(bytes int) *os.Error;
SetWriteBuffer(bytes int) *os.Error; SetWriteBuffer(bytes int) *os.Error;
SetTimeout(nsec int64) *os.Error; SetTimeout(nsec int64) *os.Error;
...@@ -456,16 +458,21 @@ type Conn interface { ...@@ -456,16 +458,21 @@ type Conn interface {
BindToDevice(dev string) *os.Error; BindToDevice(dev string) *os.Error;
} }
// Dial connects to the remote address raddr on the network net.
// Dial's arguments are the network, local address, and remote address. // If the string laddr is not empty, it is used as the local address
// for the connection.
//
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only),
// "udp", "udp4" (IPv4-only), and "udp6" (IPv6-only).
//
// For IP networks, addresses have the form host:port. If host is
// a literal IPv6 address, it must be enclosed in square brackets.
//
// Examples: // Examples:
// Dial("tcp", "", "12.34.56.78:80") // Dial("tcp", "", "12.34.56.78:80")
// Dial("tcp", "", "google.com:80")
// Dial("tcp", "", "[de:ad:be:ef::ca:fe]:80") // Dial("tcp", "", "[de:ad:be:ef::ca:fe]:80")
// Dial("tcp", "127.0.0.1:123", "127.0.0.1:88") // Dial("tcp", "127.0.0.1:123", "127.0.0.1:88")
//
// Eventually, we plan to allow names in addition to IP addresses,
// but that requires writing a DNS library.
func Dial(net, laddr, raddr string) (c Conn, err *os.Error) { func Dial(net, laddr, raddr string) (c Conn, err *os.Error) {
switch net { switch net {
case "tcp", "tcp4", "tcp6": case "tcp", "tcp4", "tcp6":
...@@ -492,23 +499,29 @@ func Dial(net, laddr, raddr string) (c Conn, err *os.Error) { ...@@ -492,23 +499,29 @@ func Dial(net, laddr, raddr string) (c Conn, err *os.Error) {
return nil, UnknownNetwork return nil, UnknownNetwork
} }
// A Listener is a generic network listener.
// Accept waits for the next connection and Close closes the connection.
type Listener interface { type Listener interface {
Accept() (c Conn, raddr string, err *os.Error); Accept() (c Conn, raddr string, err *os.Error);
Close() *os.Error; Close() *os.Error;
} }
// ListenerTCP is a TCP network listener.
// Clients should typically use variables of type Listener
// instead of assuming TCP.
type ListenerTCP struct { type ListenerTCP struct {
fd *netFD; fd *netFD;
laddr string laddr string
} }
// ListenTCP announces on the TCP address laddr and returns a TCP listener.
// Net must be "tcp", "tcp4", or "tcp6".
func ListenTCP(net, laddr string) (l *ListenerTCP, err *os.Error) { func ListenTCP(net, laddr string) (l *ListenerTCP, err *os.Error) {
fd, e := internetSocket(net, laddr, "", syscall.SOCK_STREAM, "listen"); fd, e := internetSocket(net, laddr, "", syscall.SOCK_STREAM, "listen");
if e != nil { if e != nil {
return nil, e return nil, e
} }
r, e1 := syscall.Listen(fd.fd, ListenBacklog()); r, e1 := syscall.Listen(fd.fd, listenBacklog());
if e1 != 0 { if e1 != 0 {
syscall.Close(fd.fd); syscall.Close(fd.fd);
return nil, os.ErrnoToError(e1) return nil, os.ErrnoToError(e1)
...@@ -518,6 +531,8 @@ func ListenTCP(net, laddr string) (l *ListenerTCP, err *os.Error) { ...@@ -518,6 +531,8 @@ func ListenTCP(net, laddr string) (l *ListenerTCP, err *os.Error) {
return l, nil return l, nil
} }
// AcceptTCP accepts the next incoming call and returns the new connection
// and the remote address.
func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err *os.Error) { func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err *os.Error) {
if l == nil || l.fd == nil || l.fd.fd < 0 { if l == nil || l.fd == nil || l.fd.fd < 0 {
return nil, "", os.EINVAL return nil, "", os.EINVAL
...@@ -535,6 +550,8 @@ func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err *os.Error) { ...@@ -535,6 +550,8 @@ func (l *ListenerTCP) AcceptTCP() (c *ConnTCP, raddr string, err *os.Error) {
return newConnTCP(fd, raddr), raddr, nil return newConnTCP(fd, raddr), raddr, nil
} }
// Accept implements the accept method in the Listener interface;
// it waits for the next call and returns a generic Conn.
func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) { func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) {
c1, r1, e1 := l.AcceptTCP(); c1, r1, e1 := l.AcceptTCP();
if e1 != nil { if e1 != nil {
...@@ -543,6 +560,8 @@ func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) { ...@@ -543,6 +560,8 @@ func (l *ListenerTCP) Accept() (c Conn, raddr string, err *os.Error) {
return c1, r1, nil return c1, r1, nil
} }
// Close stops listening on the TCP address.
// Already Accepted connections are not closed.
func (l *ListenerTCP) Close() *os.Error { func (l *ListenerTCP) Close() *os.Error {
if l == nil || l.fd == nil { if l == nil || l.fd == nil {
return os.EINVAL return os.EINVAL
...@@ -550,6 +569,8 @@ func (l *ListenerTCP) Close() *os.Error { ...@@ -550,6 +569,8 @@ func (l *ListenerTCP) Close() *os.Error {
return l.fd.Close() return l.fd.Close()
} }
// Listen announces on the local network address laddr.
// The network string net must be "tcp", "tcp4", or "tcp6".
func Listen(net, laddr string) (l Listener, err *os.Error) { func Listen(net, laddr string) (l Listener, err *os.Error) {
switch net { switch net {
case "tcp", "tcp4", "tcp6": case "tcp", "tcp4", "tcp6":
...@@ -561,6 +582,7 @@ func Listen(net, laddr string) (l Listener, err *os.Error) { ...@@ -561,6 +582,7 @@ func Listen(net, laddr string) (l Listener, err *os.Error) {
/* /*
more here more here
*/ */
// BUG(rsc): Listen should support UDP.
} }
return nil, UnknownNetwork return nil, UnknownNetwork
} }
......
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
"unsafe"; "unsafe";
) )
func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { func v4ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
p = ToIPv4(p); p = p.To4();
if p == nil || port < 0 || port > 0xFFFF { if p == nil || port < 0 || port > 0xFFFF {
return nil, os.EINVAL return nil, os.EINVAL
} }
...@@ -27,8 +27,8 @@ func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { ...@@ -27,8 +27,8 @@ func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
} }
func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
p = ToIPv6(p); p = p.To16();
if p == nil || port < 0 || port > 0xFFFF { if p == nil || port < 0 || port > 0xFFFF {
return nil, os.EINVAL return nil, os.EINVAL
} }
...@@ -44,18 +44,18 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { ...@@ -44,18 +44,18 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
} }
func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) { func sockaddrToIP(sa1 *syscall.Sockaddr) (p IP, port int, err *os.Error) {
switch sa1.Family { switch sa1.Family {
case syscall.AF_INET: case syscall.AF_INET:
sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1)); sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1));
a := ToIPv6(sa.Addr); a := IP(sa.Addr).To16();
if a == nil { if a == nil {
return nil, 0, os.EINVAL return nil, 0, os.EINVAL
} }
return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil; return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
case syscall.AF_INET6: case syscall.AF_INET6:
sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1)); sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1));
a := ToIPv6(sa.Addr); a := IP(sa.Addr).To16();
if a == nil { if a == nil {
return nil, 0, os.EINVAL return nil, 0, os.EINVAL
} }
...@@ -66,7 +66,7 @@ func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) { ...@@ -66,7 +66,7 @@ func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) {
return nil, 0, nil // not reached return nil, 0, nil // not reached
} }
func ListenBacklog() int64 { func listenBacklog() int64 {
return syscall.SOMAXCONN return syscall.SOMAXCONN
} }
...@@ -11,8 +11,8 @@ import ( ...@@ -11,8 +11,8 @@ import (
"unsafe"; "unsafe";
) )
func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { func v4ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
p = ToIPv4(p); p = p.To4();
if p == nil || port < 0 || port > 0xFFFF { if p == nil || port < 0 || port > 0xFFFF {
return nil, os.EINVAL return nil, os.EINVAL
} }
...@@ -26,10 +26,8 @@ func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { ...@@ -26,10 +26,8 @@ func IPv4ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
} }
var ipv6zero [16]byte; func v6ToSockaddr(p IP, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
p = p.To16();
func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
p = ToIPv6(p);
if p == nil || port < 0 || port > 0xFFFF { if p == nil || port < 0 || port > 0xFFFF {
return nil, os.EINVAL return nil, os.EINVAL
} }
...@@ -37,8 +35,8 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { ...@@ -37,8 +35,8 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
// IPv4 callers use 0.0.0.0 to mean "announce on any available address". // IPv4 callers use 0.0.0.0 to mean "announce on any available address".
// In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0", // In IPv6 mode, Linux treats that as meaning "announce on 0.0.0.0",
// which it refuses to do. Rewrite to the IPv6 all zeros. // which it refuses to do. Rewrite to the IPv6 all zeros.
if p4 := ToIPv4(p); p4 != nil && p4[0] == 0 && p4[1] == 0 && p4[2] == 0 && p4[3] == 0 { if p4 := p.To4(); p4 != nil && p4[0] == 0 && p4[1] == 0 && p4[2] == 0 && p4[3] == 0 {
p = ipv6zero; p = IPzero;
} }
sa := new(syscall.SockaddrInet6); sa := new(syscall.SockaddrInet6);
...@@ -51,18 +49,18 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) { ...@@ -51,18 +49,18 @@ func IPv6ToSockaddr(p []byte, port int) (sa1 *syscall.Sockaddr, err *os.Error) {
return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil return (*syscall.Sockaddr)(unsafe.Pointer(sa)), nil
} }
func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) { func sockaddrToIP(sa1 *syscall.Sockaddr) (p IP, port int, err *os.Error) {
switch sa1.Family { switch sa1.Family {
case syscall.AF_INET: case syscall.AF_INET:
sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1)); sa := (*syscall.SockaddrInet4)(unsafe.Pointer(sa1));
a := ToIPv6(sa.Addr); a := IP(sa.Addr).To16();
if a == nil { if a == nil {
return nil, 0, os.EINVAL return nil, 0, os.EINVAL
} }
return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil; return a, int(sa.Port[0])<<8 + int(sa.Port[1]), nil;
case syscall.AF_INET6: case syscall.AF_INET6:
sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1)); sa := (*syscall.SockaddrInet6)(unsafe.Pointer(sa1));
a := ToIPv6(sa.Addr); a := IP(sa.Addr).To16();
if a == nil { if a == nil {
return nil, 0, os.EINVAL return nil, 0, os.EINVAL
} }
...@@ -73,7 +71,7 @@ func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) { ...@@ -73,7 +71,7 @@ func SockaddrToIP(sa1 *syscall.Sockaddr) (p []byte, port int, err *os.Error) {
return nil, 0, nil // not reached return nil, 0, nil // not reached
} }
func ListenBacklog() int64 { func listenBacklog() int64 {
// TODO: Read the limit from /proc/sys/net/core/somaxconn, // TODO: Read the limit from /proc/sys/net/core/somaxconn,
// to take advantage of kernels that have raised the limit. // to take advantage of kernels that have raised the limit.
return syscall.SOMAXCONN return syscall.SOMAXCONN
......
...@@ -55,12 +55,12 @@ func (f *file) readLine() (s string, ok bool) { ...@@ -55,12 +55,12 @@ func (f *file) readLine() (s string, ok bool) {
return return
} }
func open(name string) *file { func open(name string) (*file, *os.Error) {
fd, err := os.Open(name, os.O_RDONLY, 0); fd, err := os.Open(name, os.O_RDONLY, 0);
if err != nil { if err != nil {
return nil return nil, err;
} }
return &file{fd, make([]byte, 1024)[0:0]}; return &file{fd, make([]byte, 1024)[0:0]}, nil;
} }
func byteIndex(s string, c byte) int { func byteIndex(s string, c byte) int {
......
...@@ -21,7 +21,8 @@ func TestReadLine(t *testing.T) { ...@@ -21,7 +21,8 @@ func TestReadLine(t *testing.T) {
br := bufio.NewBufRead(fd); br := bufio.NewBufRead(fd);
// TODO(rsc): 6g rejects "file :=" // TODO(rsc): 6g rejects "file :="
var file = open(filename); var file *file;
file, err = open(filename);
if file == nil { if file == nil {
t.Fatalf("net.open(%s) = nil", filename); t.Fatalf("net.open(%s) = nil", filename);
} }
......
...@@ -14,12 +14,17 @@ import ( ...@@ -14,12 +14,17 @@ import (
"strconv"; "strconv";
) )
// The error returned by LookupPort when a network service
// is not listed in the database.
var ErrNoService = os.NewError("unknown network service");
var services map[string] map[string] int var services map[string] map[string] int
var servicesError *os.Error
func readServices() { func readServices() {
services = make(map[string] map[string] int); services = make(map[string] map[string] int);
// TODO(rsc): 6g won't let me do "file := " var file *file;
var file = open("/etc/services"); file, servicesError = open("/etc/services");
for line, ok := file.readLine(); ok; line, ok = file.readLine() { for line, ok := file.readLine(); ok; line, ok = file.readLine() {
// "http 80/tcp www www-http # World Wide Web HTTP" // "http 80/tcp www www-http # World Wide Web HTTP"
if i := byteIndex(line, '#'); i >= 0 { if i := byteIndex(line, '#'); i >= 0 {
...@@ -49,21 +54,24 @@ func readServices() { ...@@ -49,21 +54,24 @@ func readServices() {
file.close(); file.close();
} }
func LookupPort(netw, name string) (port int, ok bool) { // LookupPort looks up the port for the given network and service.
func LookupPort(network, service string) (port int, err *os.Error) {
once.Do(readServices); once.Do(readServices);
switch netw { switch network {
case "tcp4", "tcp6": case "tcp4", "tcp6":
netw = "tcp"; network = "tcp";
case "udp4", "udp6": case "udp4", "udp6":
netw = "udp"; network = "udp";
} }
m, mok := services[netw]; m, ok := services[network];
if !mok { if !ok {
return return 0, ErrNoService;
}
port, ok = m[service];
if !ok {
return 0, ErrNoService;
} }
port, ok = m[name]; return port, nil;
return
} }
...@@ -51,9 +51,9 @@ var porttests = []portTest { ...@@ -51,9 +51,9 @@ var porttests = []portTest {
func TestLookupPort(t *testing.T) { func TestLookupPort(t *testing.T) {
for i := 0; i < len(porttests); i++ { for i := 0; i < len(porttests); i++ {
tt := porttests[i]; tt := porttests[i];
if port, ok := LookupPort(tt.netw, tt.name); port != tt.port || ok != tt.ok { if port, err := LookupPort(tt.netw, tt.name); port != tt.port || (err == nil) != tt.ok {
t.Errorf("LookupPort(%q, %q) = %v, %v; want %v, %v", t.Errorf("LookupPort(%q, %q) = %v, %s; want %v",
tt.netw, tt.name, port, ok, tt.port, tt.ok); tt.netw, tt.name, port, err, tt.port);
} }
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment