more Go-like interface

This commit is contained in:
Marcin Wyszynski
2014-09-07 11:03:08 +01:00
parent a941836c53
commit 8e47a04a20
2 changed files with 56 additions and 29 deletions

69
spf2.go
View File

@@ -8,7 +8,10 @@ package libspf2
#include <netdb.h> #include <netdb.h>
#include <spf2/spf.h> #include <spf2/spf.h>
*/ */
import "C" import (
"C"
"errors"
)
const ( const (
SPFResultINVALID = Result(C.SPF_RESULT_INVALID) // (invalid) SPFResultINVALID = Result(C.SPF_RESULT_INVALID) // (invalid)
@@ -21,32 +24,56 @@ const (
SPFResultNONE = Result(C.SPF_RESULT_NONE) // none SPFResultNONE = Result(C.SPF_RESULT_NONE) // none
) )
type Server struct { type Client interface {
Query(host, ip string) (Result, error)
Close() error
}
type clientImpl struct {
s *C.SPF_server_t s *C.SPF_server_t
} }
// NewServer creates a new server // NewClient creates a new SPF client.
func NewServer() *Server { func NewClient() Client {
srv := new(Server) client := new(clientImpl)
srv.s = C.SPF_server_new(C.SPF_DNS_CACHE, 0) client.s = C.SPF_server_new(C.SPF_DNS_CACHE, 0)
return srv return client
} }
// Free frees the server handle func (s *clientImpl) Query(host, ip string) (Result, error) {
func (s *Server) Free() { if s.s == nil {
return SPFResultINVALID, errors.New("client already closed")
}
req := newRequest(s)
defer req.free()
if err := req.setEnvFrom(host); err != nil {
return SPFResultINVALID, err
}
if err := req.setIPv4Addr(ip); err != nil {
return SPFResultINVALID, err
}
if resp, err := req.query(); err != nil {
return SPFResultNONE, err
}
defer resp.free()
return resp.result(), nil
}
func (s *clientImpl) Close() {
if s.s != nil { if s.s != nil {
C.SPF_server_free(s.s) C.SPF_server_free(s.s)
s.s = nil s.s = nil
return nil
} }
return errors.New("already closed")
} }
type Request struct { type request struct {
s *Server s *clientImpl
r *C.SPF_request_t r *C.SPF_request_t
} }
// NewRequest creates a new SPF request func newRequest(s *clientImpl) *request {
func NewRequest(s *Server) *Request {
r := new(Request) r := new(Request)
r.s = s r.s = s
r.r = C.SPF_request_new(s.s) r.r = C.SPF_request_new(s.s)
@@ -54,7 +81,7 @@ func NewRequest(s *Server) *Request {
} }
// SetIPv4Addr sets the sender IPv4 // SetIPv4Addr sets the sender IPv4
func (r *Request) SetIPv4Addr(addr string) error { func (r *request) setIPv4Addr(addr string) error {
var stat C.SPF_errcode_t var stat C.SPF_errcode_t
stat = C.SPF_request_set_ipv4_str(r.r, C.CString(addr)) stat = C.SPF_request_set_ipv4_str(r.r, C.CString(addr))
if stat != C.SPF_E_SUCCESS { if stat != C.SPF_E_SUCCESS {
@@ -64,7 +91,7 @@ func (r *Request) SetIPv4Addr(addr string) error {
} }
// SetEnvFrom sets the sender host // SetEnvFrom sets the sender host
func (r *Request) SetEnvFrom(fromHost string) error { func (r *request) setEnvFrom(fromHost string) error {
var stat C.int var stat C.int
stat = C.SPF_request_set_env_from(r.r, C.CString(fromHost)) stat = C.SPF_request_set_env_from(r.r, C.CString(fromHost))
if stat != C.int(C.SPF_E_SUCCESS) { if stat != C.int(C.SPF_E_SUCCESS) {
@@ -74,35 +101,35 @@ func (r *Request) SetEnvFrom(fromHost string) error {
} }
// Query starts the SPF query // Query starts the SPF query
func (r *Request) Query() (*Response, error) { func (r *Request) query() (*response, error) {
var stat C.SPF_errcode_t var stat C.SPF_errcode_t
var resp *C.SPF_response_t var resp *C.SPF_response_t
stat = C.SPF_request_query_mailfrom(r.r, &resp) stat = C.SPF_request_query_mailfrom(r.r, &resp)
if stat != C.SPF_E_SUCCESS { if stat != C.SPF_E_SUCCESS {
return nil, &spfError{stat} return nil, &spfError{stat}
} }
return &Response{resp}, nil return &response{resp}, nil
} }
// Free the request handle // Free the request handle
func (r *Request) Free() { func (r *request) free() {
if r.r != nil { if r.r != nil {
C.SPF_request_free(r.r) C.SPF_request_free(r.r)
r.r = nil r.r = nil
} }
} }
type Response struct { type response struct {
r *C.SPF_response_t r *C.SPF_response_t
} }
// Result returns the SPF validation result // Result returns the SPF validation result
func (r *Response) Result() Result { func (r *response) result() result {
return Result(C.SPF_response_result(r.r)) return Result(C.SPF_response_result(r.r))
} }
// Free frees the response handle // Free frees the response handle
func (r *Response) Free() { func (r *response) free() {
if r.r != nil { if r.r != nil {
C.SPF_response_free(r.r) C.SPF_response_free(r.r)
r.r = nil r.r = nil

View File

@@ -5,27 +5,27 @@ import (
) )
func TestSpf2(t *testing.T) { func TestSpf2(t *testing.T) {
s := NewServer() c := NewClient()
defer s.Free() defer c.Free()
req := NewRequest(s) req := newRequest(c)
defer req.Free() defer req.Free()
err := req.SetIPv4Addr("173.194.39.150") err := req.setIPv4Addr("173.194.39.150")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = req.SetEnvFrom("gmail.com") err = req.setEnvFrom("gmail.com")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
resp, err := req.Query() resp, err := req.query()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer resp.Free() defer resp.free()
res := resp.Result() res := resp.result()
if res != SPFResultPASS { if res != SPFResultPASS {
t.Fatal(res) t.Fatal(res)
} }