Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
IRMA
Github mirrors
irmago
Commits
0f5ec227
Commit
0f5ec227
authored
Dec 09, 2019
by
Sietse Ringers
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: switch to binary protocol in revocation HTTP traffic
parent
669bd187
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
116 additions
and
37 deletions
+116
-37
internal/servercore/api.go
internal/servercore/api.go
+12
-12
messages.go
messages.go
+40
-0
revocation.go
revocation.go
+10
-6
server/api.go
server/api.go
+1
-11
transport.go
transport.go
+53
-8
No files found.
internal/servercore/api.go
View file @
0f5ec227
...
...
@@ -384,41 +384,41 @@ func (s *Server) handleRevocationMessage(
)
(
int
,
[]
byte
)
{
if
(
noun
==
"updatefrom"
||
noun
==
"updatelatest"
)
&&
method
==
http
.
MethodGet
{
if
len
(
args
)
!=
2
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"GET "
+
noun
+
" expects 2 url arguments"
))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"GET "
+
noun
+
" expects 2 url arguments"
))
}
i
,
err
:=
strconv
.
ParseUint
(
args
[
1
],
10
,
64
)
if
err
!=
nil
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
}
cred
:=
irma
.
NewCredentialTypeIdentifier
(
args
[
0
])
if
noun
==
"updatefrom"
{
return
server
.
Json
Response
(
s
.
handleGetUpdateFrom
(
cred
,
i
))
return
server
.
Gob
Response
(
s
.
handleGetUpdateFrom
(
cred
,
i
))
}
else
{
return
server
.
Json
Response
(
s
.
handleGetUpdateLatest
(
cred
,
i
))
return
server
.
Gob
Response
(
s
.
handleGetUpdateLatest
(
cred
,
i
))
}
}
if
noun
==
"update"
&&
method
==
http
.
MethodPost
{
if
len
(
args
)
!=
1
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"POST update expects 1 url argument"
))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"POST update expects 1 url argument"
))
}
cred
:=
irma
.
NewCredentialTypeIdentifier
(
args
[
0
])
var
update
*
revocation
.
Update
if
err
:=
json
.
Unmarshal
(
message
,
&
update
);
err
!=
nil
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
if
err
:=
irma
.
Unmarshal
Binary
(
message
,
update
);
err
!=
nil
{
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
}
return
server
.
Json
Response
(
s
.
handlePostUpdate
(
cred
,
update
))
return
server
.
Gob
Response
(
s
.
handlePostUpdate
(
cred
,
update
))
}
if
noun
==
"issuancerecord"
&&
method
==
http
.
MethodPost
{
if
len
(
args
)
!=
2
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"POST issuancercord expects 2 url arguments"
))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
"POST issuancercord expects 2 url arguments"
))
}
cred
:=
irma
.
NewCredentialTypeIdentifier
(
args
[
0
])
counter
,
err
:=
strconv
.
ParseUint
(
args
[
1
],
10
,
64
)
if
err
!=
nil
{
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorMalformedInput
,
err
.
Error
()))
}
return
server
.
Json
Response
(
s
.
handlePostIssuanceRecord
(
cred
,
counter
,
message
))
return
server
.
Gob
Response
(
s
.
handlePostIssuanceRecord
(
cred
,
counter
,
message
))
}
return
server
.
Json
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
""
))
return
server
.
Gob
Response
(
nil
,
server
.
RemoteError
(
server
.
ErrorInvalidRequest
,
""
))
}
messages.go
View file @
0f5ec227
...
...
@@ -2,6 +2,8 @@ package irma
import
(
"bytes"
"encoding"
"encoding/gob"
"encoding/json"
"net/url"
"strconv"
...
...
@@ -131,6 +133,44 @@ func UnmarshalValidate(data []byte, dest interface{}) error {
return
nil
}
func
UnmarshalValidateBinary
(
data
[]
byte
,
dest
interface
{})
error
{
if
err
:=
UnmarshalBinary
(
data
,
dest
);
err
!=
nil
{
return
err
}
if
v
,
ok
:=
dest
.
(
Validator
);
ok
{
return
v
.
Validate
()
}
return
nil
}
func
MarshalBinary
(
message
interface
{})
([]
byte
,
error
)
{
var
bts
[]
byte
var
err
error
if
m
,
ok
:=
message
.
(
encoding
.
BinaryMarshaler
);
ok
{
bts
,
err
=
m
.
MarshalBinary
()
if
err
!=
nil
{
return
nil
,
err
}
}
else
{
var
buf
bytes
.
Buffer
if
err
=
gob
.
NewEncoder
(
&
buf
)
.
Encode
(
message
);
err
!=
nil
{
return
nil
,
err
}
bts
=
buf
.
Bytes
()
}
return
bts
,
nil
}
func
UnmarshalBinary
(
data
[]
byte
,
dst
interface
{})
error
{
if
u
,
ok
:=
dst
.
(
encoding
.
BinaryUnmarshaler
);
ok
{
return
u
.
UnmarshalBinary
(
data
)
}
if
err
:=
gob
.
NewDecoder
(
bytes
.
NewBuffer
(
data
))
.
Decode
(
dst
);
err
!=
nil
{
return
err
}
return
nil
}
func
(
err
*
RemoteError
)
Error
()
string
{
var
msg
string
if
err
.
Message
!=
""
{
...
...
revocation.go
View file @
0f5ec227
...
...
@@ -509,6 +509,7 @@ func (rs *RevocationStorage) getSettings(typ CredentialTypeIdentifier) *Revocati
func
(
client
RevocationClient
)
PostUpdate
(
typ
CredentialTypeIdentifier
,
urls
[]
string
,
update
*
revocation
.
Update
)
{
transport
:=
NewHTTPTransport
(
""
)
transport
.
Binary
=
true
for
_
,
url
:=
range
urls
{
err
:=
transport
.
Post
(
fmt
.
Sprintf
(
"%s/revocation/update/%s"
,
url
,
typ
.
String
()),
nil
,
update
)
if
err
!=
nil
{
...
...
@@ -537,15 +538,18 @@ func (client RevocationClient) FetchUpdateLatest(typ CredentialTypeIdentifier, c
}
func
(
client
RevocationClient
)
fetchUpdate
(
typ
CredentialTypeIdentifier
,
u
string
,
i
uint64
)
(
*
revocation
.
Update
,
error
)
{
records
:=
&
revocation
.
Update
{}
var
err
error
var
errs
multierror
.
Error
transport
:=
NewHTTPTransport
(
""
)
var
(
err
error
errs
multierror
.
Error
update
=
&
revocation
.
Update
{}
transport
=
NewHTTPTransport
(
""
)
)
transport
.
Binary
=
true
for
_
,
url
:=
range
client
.
Conf
.
CredentialTypes
[
typ
]
.
RevocationServers
{
transport
.
Server
=
url
err
=
transport
.
Get
(
fmt
.
Sprintf
(
"revocation/%s/%s/%d"
,
u
,
typ
,
i
),
&
records
)
err
=
transport
.
Get
(
fmt
.
Sprintf
(
"revocation/%s/%s/%d"
,
u
,
typ
,
i
),
&
update
)
if
err
==
nil
{
return
records
,
nil
return
update
,
nil
}
else
{
errs
.
Errors
=
append
(
errs
.
Errors
,
err
)
}
...
...
server/api.go
View file @
0f5ec227
package
server
import
(
"bytes"
"encoding/gob"
"encoding/json"
"fmt"
"io/ioutil"
...
...
@@ -104,15 +102,7 @@ func JsonResponse(v interface{}, err *irma.RemoteError) (int, []byte) {
}
func
GobResponse
(
v
interface
{},
err
*
irma
.
RemoteError
)
(
int
,
[]
byte
)
{
return
encodeValOrError
(
v
,
err
,
gobMarshal
)
}
func
gobMarshal
(
v
interface
{})
([]
byte
,
error
)
{
var
b
bytes
.
Buffer
if
err
:=
gob
.
NewEncoder
(
&
b
)
.
Encode
(
v
);
err
!=
nil
{
return
nil
,
err
}
return
b
.
Bytes
(),
nil
return
encodeValOrError
(
v
,
err
,
irma
.
MarshalBinary
)
}
func
encodeValOrError
(
v
interface
{},
err
*
irma
.
RemoteError
,
encoder
func
(
interface
{})
([]
byte
,
error
))
(
int
,
[]
byte
)
{
...
...
transport.go
View file @
0f5ec227
...
...
@@ -26,6 +26,7 @@ import (
// HTTPTransport sends and receives JSON messages to a HTTP server.
type
HTTPTransport
struct
{
Server
string
Binary
bool
client
*
retryablehttp
.
Client
headers
map
[
string
]
string
}
...
...
@@ -91,6 +92,49 @@ func NewHTTPTransport(serverURL string) *HTTPTransport {
}
}
func
(
transport
*
HTTPTransport
)
marshal
(
o
interface
{})
([]
byte
,
error
)
{
if
transport
.
Binary
{
return
MarshalBinary
(
o
)
}
return
json
.
Marshal
(
o
)
}
func
(
transport
*
HTTPTransport
)
unmarshal
(
data
[]
byte
,
dst
interface
{})
error
{
if
transport
.
Binary
{
return
UnmarshalBinary
(
data
,
dst
)
}
return
json
.
Unmarshal
(
data
,
dst
)
}
func
(
transport
*
HTTPTransport
)
unmarshalValidate
(
data
[]
byte
,
dst
interface
{})
error
{
if
transport
.
Binary
{
return
UnmarshalValidateBinary
(
data
,
dst
)
}
return
UnmarshalValidate
(
data
,
dst
)
}
func
(
transport
*
HTTPTransport
)
log
(
prefix
string
,
message
interface
{},
binary
bool
)
{
if
!
Logger
.
IsLevelEnabled
(
logrus
.
TraceLevel
)
{
return
// do nothing if nothing would be printed anyway
}
var
str
string
switch
s
:=
message
.
(
type
)
{
case
[]
byte
:
str
=
string
(
s
)
case
string
:
str
=
s
default
:
tmp
,
_
:=
json
.
Marshal
(
message
)
str
=
string
(
tmp
)
binary
=
false
}
if
!
binary
{
Logger
.
Tracef
(
"transport: %s: %s"
,
prefix
,
str
)
}
else
{
Logger
.
Tracef
(
"transport: %s (base64): %s"
,
prefix
,
base64
.
RawStdEncoding
.
EncodeToString
([]
byte
(
str
)))
}
}
// SetHeader sets a header to be sent in requests.
func
(
transport
*
HTTPTransport
)
SetHeader
(
name
,
val
string
)
{
transport
.
headers
[
name
]
=
val
...
...
@@ -133,19 +177,19 @@ func (transport *HTTPTransport) jsonRequest(url string, method string, result in
if
object
!=
nil
{
switch
o
:=
object
.
(
type
)
{
case
[]
byte
:
Logger
.
Trace
(
"transport: body (base64): "
,
base64
.
StdEncoding
.
EncodeToString
(
o
)
)
transport
.
log
(
"body"
,
o
,
true
)
contenttype
=
"application/octet-stream"
reader
=
bytes
.
NewBuffer
(
o
)
case
string
:
Logger
.
Trace
(
"
transport
:
body
:
"
,
o
)
transport
.
log
(
"
body"
,
o
,
false
)
contenttype
=
"text/plain; charset=UTF-8"
reader
=
bytes
.
NewBuffer
([]
byte
(
o
))
default
:
marshaled
,
err
:=
json
.
M
arshal
(
object
)
marshaled
,
err
:=
transport
.
m
arshal
(
object
)
if
err
!=
nil
{
return
&
SessionError
{
ErrorType
:
ErrorSerialization
,
Err
:
err
}
}
Logger
.
Trace
(
"
transport
:
body
:
"
,
string
(
marshaled
))
transport
.
log
(
"
body"
,
string
(
marshaled
)
,
transport
.
Binary
)
contenttype
=
"application/json; charset=UTF-8"
reader
=
bytes
.
NewBuffer
(
marshaled
)
}
...
...
@@ -165,22 +209,22 @@ func (transport *HTTPTransport) jsonRequest(url string, method string, result in
}
if
res
.
StatusCode
!=
200
{
apierr
:=
&
RemoteError
{}
err
=
json
.
U
nmarshal
(
body
,
apierr
)
err
=
transport
.
u
nmarshal
(
body
,
apierr
)
if
err
!=
nil
||
apierr
.
ErrorName
==
""
{
// Not an ApiErrorMessage
return
&
SessionError
{
ErrorType
:
ErrorServerResponse
,
RemoteStatus
:
res
.
StatusCode
}
}
Logger
.
Tracef
(
"transport: error: %+v
"
,
apierr
)
transport
.
log
(
"error
"
,
apierr
,
false
)
return
&
SessionError
{
ErrorType
:
ErrorApi
,
RemoteStatus
:
res
.
StatusCode
,
RemoteError
:
apierr
}
}
Logger
.
Tracef
(
"
transport
:
response
: %s"
,
string
(
bod
y
)
)
transport
.
log
(
"
response
"
,
body
,
transport
.
Binar
y
)
if
result
==
nil
{
// caller doesn't care about server response
return
nil
}
if
_
,
resultstr
:=
result
.
(
*
string
);
resultstr
{
*
result
.
(
*
string
)
=
string
(
body
)
}
else
{
err
=
U
nmarshalValidate
(
body
,
result
)
err
=
transport
.
u
nmarshalValidate
(
body
,
result
)
if
err
!=
nil
{
return
&
SessionError
{
ErrorType
:
ErrorServerResponse
,
Err
:
err
,
RemoteStatus
:
res
.
StatusCode
}
}
...
...
@@ -202,6 +246,7 @@ func (transport *HTTPTransport) GetBytes(url string) ([]byte, error) {
if
err
!=
nil
{
return
nil
,
&
SessionError
{
ErrorType
:
ErrorServerResponse
,
Err
:
err
,
RemoteStatus
:
res
.
StatusCode
}
}
transport
.
log
(
"response"
,
b
,
true
)
return
b
,
nil
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment