Phidget22 Network Protocol: Difference between revisions
(Created page with " =Introduction= The Phidget22 Network Protocol is primarily JSON based with a binary header that describes the contents of the JSON. ==Header== The network request header is...") |
|||
Line 115: | Line 115: | ||
===HandShakeS0=== | ===HandShakeS0=== | ||
The server will reply to {{Code|MSG_CONNECT}}.{{Code|SMSG_HANDSHAKEC0}} with {{Code|MSG_CONNECT}}.{{Code|SMSG_HANDSHAKES0}}. The payload must contain at least ''type'', ''pmajor'', ''pminor'' and ''result''. | |||
{| | |||
| type | string | identifies the server type | |||
|- | |||
| pmajor | int | the major protocol version supported by the server | |||
the request | |- | ||
| pminor | int | the minor protocol version supported by the server | |||
|- | |||
| result | int | result code from the {{Code|SMSG_HANDSHAKEC0}} request | |||
|} | |||
HDR( | ''result'' indicates success or failure of the client handshake request, and will be zero if successful. If ''result'' is not zero, the server has rejected the request, and the socket will have been closed. | ||
HDR(REQUEST, MSG_CONNECT, MSG_HANDSHAKES0) { | |||
type: PHIDGET_NET_PROTOCOL, // phid22device | type: PHIDGET_NET_PROTOCOL, // phid22device | ||
pmajor: 2, | pmajor: 2, | ||
Line 129: | Line 135: | ||
} | } | ||
===AuthC0=== | |||
MSG_CONNECT | Once the handshake has completed, authentication begins. The client begins by sending {{Code|MSG_CONNECT}}.{{Code|SMSG_AUTHC0}} with a payload containing ''ident'' and ''nonceC''. | ||
{| | |||
| ident || string || must be '''phidgetclient''' | |||
|- | |||
| nonceC || string(15) || random client nonce | |||
|} | |||
''nonceC'' is a 15 byte random value. Typical implementations generate a random array of bytes, calculate the base64 of those bytes and send the first 15 bytes of the base64. | |||
HDR( | HDR(REQUEST, MSG_CONNECT, MSG_AUTHC0) { | ||
ident: 'phidgetclient', | ident: 'phidgetclient', | ||
nonceC: '0123456789abcde' | nonceC: '0123456789abcde' | ||
} | } | ||
===AuthS0=== | |||
The server handles a {{Code|SMSG_AUTHC0}} request by validating the 'ident', and then sending a {{Code|MSG_CONNECT}}.{{Code|SMSG_AUTHS0}} command. The payload will contain ''srvname'', ''nonceC'', ''nonceS'', ''salt'', ''count'', and ''result''. | |||
the server | |||
{| | |||
15 | | srvname || string || the name of the server | ||
|- | |||
| nonceC || string(15) || the nonce send to the server by the client | |||
|- | |||
| nonceS || string(15) || random server nonce | |||
|- | |||
| salt || string(15) || random server generated salt | |||
|- | |||
| count || int || the number of sha256 rounds (currently 1) | |||
|- | |||
| result || int || the result code for the {{Code|SMSG_AUTHC0}} request | |||
|} | |||
HDR( | If the server failed to handle the clients {{Code|SMSG_AUTHC0}} request, no response will be sent, and the | ||
server will close the connection. | |||
HDR(REQUEST, MSG_CONNECT, MSG_AUTHS0) { | |||
srvname: 'srvname', | srvname: 'srvname', | ||
nonceC: '0123456789abcde', | nonceC: '0123456789abcde', | ||
Line 158: | Line 180: | ||
} | } | ||
===AuthC1=== | |||
The client handles the {{Code|SMSG_AUTHS0}} reply by first validating that the ''nonceC'' value in the playload matches the ''nonceC'' value that was sent, and that the ''result'' value is zero. If validation is not successful, the client must close the connection. | |||
A challenge response is calculated on the client by building a string containing the protocol ident, any password, ''nonceC'', ''nonceS'' and ''salt''. | |||
challenge = ('phidgetclient' + <passwd> + <nonceC> + <nonceS> + <salt>) | challenge = ('phidgetclient' + <passwd> + <nonceC> + <nonceS> + <salt>) | ||
The resulting challenge string must be SHA256 hashed count times, and base64 encoded. | |||
The client sends a {{Code|MSG_CONNECT}}.{{Code|SMSG_AUTHC1}} request with the playload ''nonceC'', ''nonceS'', and ''proof''. ''nonceC'' must be the ''nonceC'' value from the original {{Code|SMSG_AUTHC0}} request, and ''nonceS'' must be the ''nonceS'' value received in the {{Code|SMSG_AUTHS0}} request. ''proof'' is the full length base64 encoded challenge string. | |||
HDR( | HDR(REQUEST, MSG_CONNECT, MSG_AUTHC1) { | ||
nonceC: '0123456789abcde', | nonceC: '0123456789abcde', | ||
nonceS: 'edcba9876543210', | nonceS: 'edcba9876543210', | ||
Line 179: | Line 197: | ||
} | } | ||
===AuthS1=== | |||
The server handles the {{Code|SMSG_AUTHC1}} request by first validating the ''nonceC'' and ''nonceS'' values, and then by validating the challenge response. If validation is successful, a reply packet is sent with a result of zero. If validation is not successful, a reply packet is sent with a result code of {{Code|EPHIDGET_ACCESS}}. | |||
Note that the password used to calculate the challange and response is never transferred, and must be previously known by both the client and the server. If no password is required, it must be a zero length string. | |||
HDR( | HDR(REPLY, MSG_COMMAND, SMSG_REPLY) { | ||
E: <result code> | E: <result code> | ||
} | } | ||
Once authentication is complete, the server will begin delivering events to the client, and the client may begin sending commands to the server. | |||
Revision as of 16:01, 26 July 2017
Introduction
The Phidget22 Network Protocol is primarily JSON based with a binary header that describes the contents of the JSON.
Header
The network request header is a union of a NR_HEADERLEN
byte array and the members of the netreq
structure. The values are not marshalled in C (except on big endian), and must be handled correctly by light clients.
The header contains a four byte magic, four byte length, two byte flags, two byte request sequence number, two byte reply sequence number, one byte type and a one byte sub-type.
Header Members
Member | Size | Description | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
magic | 4 | used to identify the header and to ensure stream alignment 0x50484930
| |||||||||||||||
len | 4 | indicates the payload length NR_MAXDATALEN
| |||||||||||||||
flags | 2 | flags
| |||||||||||||||
reqseq | 2 | Request sequence number. Ignored for replies and events. | |||||||||||||||
repseq | 2 | Reply sequence number (the reqseq the reply is for). Used to route replies to async requests. | |||||||||||||||
type | 1 | Indicates the packet type, and what the payload should contain | |||||||||||||||
stype | 1 | Packet sub-type. Further describes the type .
|
Packet Types
MSG_CONNECT |
10 | Connection control packet
SMSG_AUTHC0 || 10 || Begin authentication request
| |||||||||||||||||||||||
MSG_COMMAND |
20 | Command packet
| |||||||||||||||||||||||
MSG_DEVICE |
30 | Device or Channel packet
|
Connection
A connection begins with the client opening a TCP/IP connection to the server and sending the initial packet.
HandShakeC0
The identification packet is MSG_CONNECT
.SMSG_HANDSHAKEC0
. The playload contains at least the keys type, pmajor, and pminor.
type | string | the type of the server |
pmajor | int | the major protocol version supported by the client |
pminor | int | the minor protocol version supported by the client |
dgram | bool | Optional if 1 datagram is supported by the client |
port | int | Optional if dgram is true, the UDP port the client is listening on |
If type begins with "www", the server will send SMSG_DEVCHANNEL
messages to the client; otherwise, the server assumes the client is aware of channels belonging to specific devices.
HDR(REQUEST, MSG_CONNECT, MSG_HANDSHAKEC0) { type: '[www],clienttype', pmajor: 2, pminor: 1, dgram: 1, port: <UDP port number> }
HandShakeS0
The server will reply to MSG_CONNECT
.SMSG_HANDSHAKEC0
with MSG_CONNECT
.SMSG_HANDSHAKES0
. The payload must contain at least type, pmajor, pminor and result.
string | identifies the server type |
int | the major protocol version supported by the server |
int | the minor protocol version supported by the server |
int | result code from the SMSG_HANDSHAKEC0 request
|
result indicates success or failure of the client handshake request, and will be zero if successful. If result is not zero, the server has rejected the request, and the socket will have been closed.
HDR(REQUEST, MSG_CONNECT, MSG_HANDSHAKES0) { type: PHIDGET_NET_PROTOCOL, // phid22device pmajor: 2, pminor: 1, result: 0 }
AuthC0
Once the handshake has completed, authentication begins. The client begins by sending MSG_CONNECT
.SMSG_AUTHC0
with a payload containing ident and nonceC.
ident | string | must be phidgetclient |
nonceC | string(15) | random client nonce |
nonceC is a 15 byte random value. Typical implementations generate a random array of bytes, calculate the base64 of those bytes and send the first 15 bytes of the base64.
HDR(REQUEST, MSG_CONNECT, MSG_AUTHC0) { ident: 'phidgetclient', nonceC: '0123456789abcde' }
AuthS0
The server handles a SMSG_AUTHC0
request by validating the 'ident', and then sending a MSG_CONNECT
.SMSG_AUTHS0
command. The payload will contain srvname, nonceC, nonceS, salt, count, and result.
srvname | string | the name of the server |
nonceC | string(15) | the nonce send to the server by the client |
nonceS | string(15) | random server nonce |
salt | string(15) | random server generated salt |
count | int | the number of sha256 rounds (currently 1) |
result | int | the result code for the SMSG_AUTHC0 request
|
If the server failed to handle the clients SMSG_AUTHC0
request, no response will be sent, and the
server will close the connection.
HDR(REQUEST, MSG_CONNECT, MSG_AUTHS0) { srvname: 'srvname', nonceC: '0123456789abcde', nonceS: 'edcba9876543210', salt: 'randomsalt00000', count: 1, result: 0 }
AuthC1
The client handles the SMSG_AUTHS0
reply by first validating that the nonceC value in the playload matches the nonceC value that was sent, and that the result value is zero. If validation is not successful, the client must close the connection.
A challenge response is calculated on the client by building a string containing the protocol ident, any password, nonceC, nonceS and salt.
challenge = ('phidgetclient' + <passwd> + <nonceC> + <nonceS> + <salt>)
The resulting challenge string must be SHA256 hashed count times, and base64 encoded.
The client sends a MSG_CONNECT
.SMSG_AUTHC1
request with the playload nonceC, nonceS, and proof. nonceC must be the nonceC value from the original SMSG_AUTHC0
request, and nonceS must be the nonceS value received in the SMSG_AUTHS0
request. proof is the full length base64 encoded challenge string.
HDR(REQUEST, MSG_CONNECT, MSG_AUTHC1) { nonceC: '0123456789abcde', nonceS: 'edcba9876543210', proof: '<base64 challenge response>' }
AuthS1
The server handles the SMSG_AUTHC1
request by first validating the nonceC and nonceS values, and then by validating the challenge response. If validation is successful, a reply packet is sent with a result of zero. If validation is not successful, a reply packet is sent with a result code of EPHIDGET_ACCESS
.
Note that the password used to calculate the challange and response is never transferred, and must be previously known by both the client and the server. If no password is required, it must be a zero length string.
HDR(REPLY, MSG_COMMAND, SMSG_REPLY) { E: <result code> }
Once authentication is complete, the server will begin delivering events to the client, and the client may begin sending commands to the server.