Commit 269cfe5f authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Move HTTPTransport and errors up to irmago

parent 4827a371
......@@ -18,18 +18,6 @@ type Action string
// Version encodes the IRMA protocol version of an IRMA session.
type Version string
// ErrorCode are session errors.
type ErrorCode string
// Error is a protocol error.
type Error struct {
error
ErrorCode
*ApiError
Info string
Status int
}
// Statuses
const (
StatusConnected = Status("connected")
......@@ -44,24 +32,6 @@ const (
ActionUnknown = Action("unknown")
)
// Protocol errors
const (
// Protocol version not supported
ErrorProtocolVersionNotSupported = ErrorCode("versionNotSupported")
// Error in HTTP communication
ErrorTransport = ErrorCode("httpError")
// Invalid client JWT in first IRMA message
ErrorInvalidJWT = ErrorCode("invalidJwt")
// Unkown session type (not disclosing, signing, or issuing)
ErrorUnknownAction = ErrorCode("unknownAction")
// Crypto error during calculation of our response (second IRMA message)
ErrorCrypto = ErrorCode("cryptoResponseError")
// Server rejected our response (second IRMA message)
ErrorRejected = ErrorCode("rejectedByServer")
// (De)serializing of a message failed
ErrorSerialization = ErrorCode("serializationError")
)
// Qr contains the data of an IRMA session QR (as generated by irma_js),
// suitable for NewSession().
type Qr struct {
......@@ -82,13 +52,6 @@ type SessionInfo struct {
Keys map[irmago.IssuerIdentifier]int `json:"keys"`
}
func (e *Error) Error() string {
if e.error != nil {
return fmt.Sprintf("%s: %s", string(e.ErrorCode), e.error.Error())
}
return string(e.ErrorCode)
}
/*
So apparently, in the old Java implementation we forgot to write a (de)serialization for the Java
equivalent of the type IssuerIdentifier. This means a Java IssuerIdentifier does not serialize to
......
......@@ -39,7 +39,7 @@ func TestServiceProvider(t *testing.T) {
}
func TestTransport(t *testing.T) {
transport := NewHTTPTransport("https://xkcd.com")
transport := irmago.NewHTTPTransport("https://xkcd.com")
obj := &struct {
Num int `json:"num"`
Img string `json:"img"`
......
......@@ -22,7 +22,7 @@ type Handler interface {
StatusUpdate(action Action, status Status)
Success(action Action)
Cancelled(action Action)
Failure(action Action, err *Error)
Failure(action Action, err *irmago.Error)
UnsatisfiableRequest(action Action, missing irmago.AttributeDisjunctionList)
AskIssuancePermission(request irmago.IssuanceRequest, ServerName string, callback PermissionHandler)
......@@ -39,7 +39,7 @@ type session struct {
jwt RequestorJwt
irmaSession irmago.Session
transport *HTTPTransport
transport *irmago.HTTPTransport
}
// Supported protocol versions. Minor version numbers should be reverse sorted.
......@@ -86,7 +86,7 @@ func calcVersion(qr *Qr) (string, error) {
func NewSession(qr *Qr, handler Handler) {
version, err := calcVersion(qr)
if err != nil {
handler.Failure(ActionUnknown, &Error{ErrorCode: ErrorProtocolVersionNotSupported, error: err})
handler.Failure(ActionUnknown, &irmago.Error{ErrorCode: irmago.ErrorProtocolVersionNotSupported, Err: err})
return
}
......@@ -95,7 +95,7 @@ func NewSession(qr *Qr, handler Handler) {
Action: Action(qr.Type),
ServerURL: qr.URL,
Handler: handler,
transport: NewHTTPTransport(qr.URL),
transport: irmago.NewHTTPTransport(qr.URL),
}
// Check if the action is one of the supported types
......@@ -106,7 +106,7 @@ func NewSession(qr *Qr, handler Handler) {
case ActionUnknown:
fallthrough
default:
handler.Failure(ActionUnknown, &Error{ErrorCode: ErrorUnknownAction, error: nil, Info: string(session.Action)})
handler.Failure(ActionUnknown, &irmago.Error{ErrorCode: irmago.ErrorUnknownAction, Err: nil, Info: string(session.Action)})
return
}
......@@ -133,12 +133,12 @@ func (session *session) start() {
}
jwtparts := strings.Split(info.Jwt, ".")
if jwtparts == nil || len(jwtparts) < 2 {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorInvalidJWT})
return
}
headerbytes, err := base64.RawStdEncoding.DecodeString(jwtparts[0])
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT, error: err})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorInvalidJWT, Err: err})
return
}
var header struct {
......@@ -146,14 +146,14 @@ func (session *session) start() {
}
err = json.Unmarshal([]byte(headerbytes), &header)
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT, error: err})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorInvalidJWT, Err: err})
return
}
// Deserialize JWT, and set session state
bodybytes, err := base64.RawStdEncoding.DecodeString(jwtparts[1])
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT, error: err})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorInvalidJWT, Err: err})
return
}
switch session.Action {
......@@ -173,7 +173,7 @@ func (session *session) start() {
panic("Invalid session type") // does not happen, session.Action has been checked earlier
}
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorInvalidJWT, error: err})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorInvalidJWT, Err: err})
return
}
session.irmaSession = session.jwt.IrmaSession()
......@@ -227,11 +227,11 @@ func (session *session) do(proceed bool, choice *irmago.DisclosureChoice) {
message, err = irmago.Manager.IssueCommitments(choice, session.irmaSession.(*irmago.IssuanceRequest))
}
if err != nil {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorCrypto, error: err})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorCrypto, Err: err})
return
}
var Err *Error
var Err *irmago.Error
switch session.Action {
case ActionSigning:
fallthrough
......@@ -243,7 +243,7 @@ func (session *session) do(proceed bool, choice *irmago.DisclosureChoice) {
return
}
if response != "VALID" {
session.Handler.Failure(session.Action, &Error{ErrorCode: ErrorRejected, Info: response})
session.Handler.Failure(session.Action, &irmago.Error{ErrorCode: irmago.ErrorRejected, Info: response})
return
}
case ActionIssuing:
......@@ -256,7 +256,7 @@ func (session *session) do(proceed bool, choice *irmago.DisclosureChoice) {
err = irmago.Manager.ConstructCredentials(response, session.irmaSession.(*irmago.IssuanceRequest))
if err != nil {
session.Handler.Failure(session.Action, &Error{error: err, ErrorCode: ErrorCrypto})
session.Handler.Failure(session.Action, &irmago.Error{Err: err, ErrorCode: irmago.ErrorCrypto})
return
}
}
......
......@@ -49,7 +49,7 @@ func teardown(t *testing.T) {
type TestHandler struct {
t *testing.T
c chan *Error
c chan *irmago.Error
}
func (th TestHandler) StatusUpdate(action Action, status Status) {}
......@@ -57,13 +57,13 @@ func (th TestHandler) Success(action Action) {
th.c <- nil
}
func (th TestHandler) Cancelled(action Action) {
th.c <- &Error{}
th.c <- &irmago.Error{}
}
func (th TestHandler) Failure(action Action, err *Error) {
func (th TestHandler) Failure(action Action, err *irmago.Error) {
th.c <- err
}
func (th TestHandler) UnsatisfiableRequest(action Action, missing irmago.AttributeDisjunctionList) {
th.c <- &Error{}
th.c <- &irmago.Error{}
}
func (th TestHandler) AskVerificationPermission(request irmago.DisclosureRequest, ServerName string, callback PermissionHandler) {
choice := &irmago.DisclosureChoice{
......@@ -143,7 +143,7 @@ func getIssuanceJwt(name string, id irmago.AttributeTypeIdentifier) interface{}
// StartSession starts an IRMA session by posting the request,
// and retrieving the QR contents from the specified url.
func StartSession(request interface{}, url string) (*Qr, error) {
server := NewHTTPTransport(url)
server := irmago.NewHTTPTransport(url)
var response Qr
err := server.Post("", &response, request)
if err != nil {
......@@ -197,7 +197,7 @@ func sessionHelper(t *testing.T, jwtcontents interface{}, url string) {
require.NoError(t, transportErr)
qr.URL = url + "/" + qr.URL
c := make(chan *Error)
c := make(chan *irmago.Error)
NewSession(qr, TestHandler{t, c})
if err := <-c; err != nil {
......
package protocol
package irmago
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
......@@ -16,6 +17,18 @@ type HTTPTransport struct {
client *http.Client
}
// ErrorCode are session errors.
type ErrorCode string
// Error is a protocol error.
type Error struct {
Err error
ErrorCode
*ApiError
Info string
Status int
}
// ApiError is an error message returned by the API server on errors.
type ApiError struct {
Status int `json:"status"`
......@@ -25,6 +38,31 @@ type ApiError struct {
Stacktrace string `json:"stacktrace"`
}
// Protocol errors
const (
// Protocol version not supported
ErrorProtocolVersionNotSupported = ErrorCode("versionNotSupported")
// Error in HTTP communication
ErrorTransport = ErrorCode("httpError")
// Invalid client JWT in first IRMA message
ErrorInvalidJWT = ErrorCode("invalidJwt")
// Unkown session type (not disclosing, signing, or issuing)
ErrorUnknownAction = ErrorCode("unknownAction")
// Crypto error during calculation of our response (second IRMA message)
ErrorCrypto = ErrorCode("cryptoResponseError")
// Server rejected our response (second IRMA message)
ErrorRejected = ErrorCode("rejectedByServer")
// (De)serializing of a message failed
ErrorSerialization = ErrorCode("serializationError")
)
func (e *Error) Error() string {
if e.Err != nil {
return fmt.Sprintf("%s: %s", string(e.ErrorCode), e.Err.Error())
}
return string(e.ErrorCode)
}
// NewHTTPTransport returns a new HTTPTransport.
func NewHTTPTransport(serverURL string) *HTTPTransport {
url := serverURL
......@@ -56,7 +94,7 @@ func (transport *HTTPTransport) request(url string, method string, result interf
} else {
marshaled, err := json.Marshal(object)
if err != nil {
return &Error{error: err, ErrorCode: ErrorSerialization}
return &Error{Err: err, ErrorCode: ErrorSerialization}
//return &TransportError{Err: err.Error()}
}
//fmt.Printf("POST: %s\n", string(marshaled))
......@@ -66,7 +104,7 @@ func (transport *HTTPTransport) request(url string, method string, result interf
req, err := http.NewRequest(method, transport.Server+url, reader)
if err != nil {
return &Error{error: err, ErrorCode: ErrorTransport}
return &Error{Err: err, ErrorCode: ErrorTransport}
}
req.Header.Set("User-Agent", "irmago")
......@@ -80,12 +118,12 @@ func (transport *HTTPTransport) request(url string, method string, result interf
res, err := transport.client.Do(req)
if err != nil {
return &Error{error: err, ErrorCode: ErrorTransport}
return &Error{Err: err, ErrorCode: ErrorTransport}
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return &Error{error: err, Status: res.StatusCode}
return &Error{Err: err, Status: res.StatusCode}
}
if res.StatusCode != 200 {
apierr := &ApiError{}
......@@ -100,7 +138,7 @@ func (transport *HTTPTransport) request(url string, method string, result interf
//fmt.Printf("RESPONSE: %s\n", string(body))
err = json.Unmarshal(body, result)
if err != nil {
return &Error{error: err, Status: res.StatusCode}
return &Error{Err: err, Status: res.StatusCode}
}
return nil
......
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