IS2: Go to protobuf v3

This commit is contained in:
Heikki Hannikainen 2022-10-26 01:51:38 +03:00
parent 5eee1b66d3
commit 1dfba6333a
5 changed files with 178 additions and 156 deletions

View File

@ -61,11 +61,11 @@ static void *is2_allocate_buffer(int len)
* Write a message to a client, return result from c->write
*/
static int is2_write_message(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_write_message(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
char buf[IS2_MAXIMUM_FRAME_LEN];
int len = is2_message__get_packed_size(m);
int len = aprsis2__is2_message__get_packed_size(m);
int blen = len + IS2_HEAD_LEN + IS2_TAIL_LEN;
if (blen > IS2_MAXIMUM_FRAME_LEN) {
@ -75,7 +75,7 @@ static int is2_write_message(struct worker_t *self, struct client_t *c, IS2Messa
//hlog(LOG_DEBUG, "%s/%s: IS2: serialized length %d", c->addr_rem, c->username, len);
is2_setup_buffer(buf, len);
is2_message__pack(m, (void *)buf + IS2_HEAD_LEN);
aprsis2__is2_message__pack(m, (void *)buf + IS2_HEAD_LEN);
return c->write(self, c, buf, blen);
}
@ -84,12 +84,12 @@ static int is2_write_message(struct worker_t *self, struct client_t *c, IS2Messa
* Write an UDP message to a client, return result from c->write
*/
static int is2_corepeer_write_message(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_corepeer_write_message(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
m->sequence = c->corepeer_is2_sequence++;
m->has_sequence = 1;
int len = is2_message__get_packed_size(m);
int len = aprsis2__is2_message__get_packed_size(m);
int blen = len + IS2_HEAD_LEN + IS2_TAIL_LEN;
if (blen > c->obuf_size) {
hlog(LOG_DEBUG, "%s/%s: IS2 UDP: serialized IS2 frame length %d does not fit in obuf", c->addr_rem, c->username, blen);
@ -97,7 +97,7 @@ static int is2_corepeer_write_message(struct worker_t *self, struct client_t *c,
}
is2_setup_buffer(c->obuf, len);
is2_message__pack(m, (void *)c->obuf + IS2_HEAD_LEN);
aprsis2__is2_message__pack(m, (void *)c->obuf + IS2_HEAD_LEN);
int r = udp_client_write(self, c, c->obuf, blen);
hlog(LOG_DEBUG, "%s/%s: IS2 UDP: serialized length %d, frame %d, wrote %d", c->addr_rem, c->username, len, len + IS2_HEAD_LEN + IS2_TAIL_LEN, r);
@ -110,15 +110,16 @@ static int is2_corepeer_write_message(struct worker_t *self, struct client_t *c,
int is2_out_server_signature(struct worker_t *self, struct client_t *c)
{
IS2ServerSignature sig = IS2_SERVER_SIGNATURE__INIT;
Aprsis2__IS2ServerSignature sig = APRSIS2__IS2_SERVER_SIGNATURE__INIT;
sig.username = serverid;
sig.app_name = verstr_progname;
sig.app_version = version_build;
sig.n_features = 0;
sig.features = NULL;
IS2Message m = IS2_MESSAGE__INIT;
m.type = IS2_MESSAGE__TYPE__SERVER_SIGNATURE;
Aprsis2__IS2Message m = APRSIS2__IS2_MESSAGE__INIT;
m.has_type = 1;
m.type = APRSIS2__IS2_MESSAGE__TYPE__SERVER_SIGNATURE;
m.server_signature = &sig;
return is2_write_message(self, c, &m);
@ -128,15 +129,19 @@ int is2_out_server_signature(struct worker_t *self, struct client_t *c)
* Transmit a login reply to a new client
*/
int is2_out_login_reply(struct worker_t *self, struct client_t *c, IS2LoginReply__LoginResult result, IS2LoginReply__LoginResultReason reason, VerificationStatus verified)
int is2_out_login_reply(struct worker_t *self, struct client_t *c, Aprsis2__IS2LoginReply__LoginResult result, Aprsis2__IS2LoginReply__LoginResultReason reason, Aprsis2__VerificationStatus verified)
{
IS2LoginReply lr = IS2_LOGIN_REPLY__INIT;
Aprsis2__IS2LoginReply lr = APRSIS2__IS2_LOGIN_REPLY__INIT;
lr.has_result = 1;
lr.has_result_code = 1;
lr.has_verified = 1;
lr.result = result;
lr.result_code = reason;
lr.verified = verified;
IS2Message m = IS2_MESSAGE__INIT;
m.type = IS2_MESSAGE__TYPE__LOGIN_REPLY;
Aprsis2__IS2Message m = APRSIS2__IS2_MESSAGE__INIT;
m.has_type = 1;
m.type = APRSIS2__IS2_MESSAGE__TYPE__LOGIN_REPLY;
m.login_reply = &lr;
return is2_write_message(self, c, &m);
@ -146,16 +151,16 @@ int is2_out_login_reply(struct worker_t *self, struct client_t *c, IS2LoginReply
* Receive a login reply
*/
static int is2_in_login_reply(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_login_reply(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
IS2LoginReply *lr = m->login_reply;
Aprsis2__IS2LoginReply *lr = m->login_reply;
if (!lr) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of login reply failed",
c->addr_rem, c->username);
return -1;
}
if (lr->result != IS2_LOGIN_REPLY__LOGIN_RESULT__OK) {
if (lr->result != APRSIS2__IS2_LOGIN_REPLY__LOGIN_RESULT__OK) {
hlog(LOG_INFO, "%s/%s: IS2: Login failed: '%s' (%d)",
c->addr_rem, c->username,
(lr->result_message) ? lr->result_message : "no reason", lr->result_code);
@ -180,9 +185,9 @@ static int is2_in_login_reply(struct worker_t *self, struct client_t *c, IS2Mess
* - if ok, continue by sending a login command
*/
static int is2_in_server_signature(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_server_signature(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
IS2ServerSignature *sig = m->server_signature;
Aprsis2__IS2ServerSignature *sig = m->server_signature;
if (!sig) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of server signature failed",
c->addr_rem, c->username);
@ -219,15 +224,16 @@ static int is2_in_server_signature(struct worker_t *self, struct client_t *c, IS
#endif
/* Ok, we're happy with the uplink's server signature, let us login! */
IS2LoginRequest lr = IS2_LOGIN_REQUEST__INIT;
Aprsis2__IS2LoginRequest lr = APRSIS2__IS2_LOGIN_REQUEST__INIT;
lr.username = serverid;
lr.app_name = verstr_progname;
lr.app_version = version_build;
lr.n_features_req = 0;
lr.features_req = NULL;
IS2Message mr = IS2_MESSAGE__INIT;
mr.type = IS2_MESSAGE__TYPE__LOGIN_REQUEST;
Aprsis2__IS2Message mr = APRSIS2__IS2_MESSAGE__INIT;
mr.has_type = 1;
mr.type = APRSIS2__IS2_MESSAGE__TYPE__LOGIN_REQUEST;
mr.login_request = &lr;
is2_write_message(self, c, &mr);
@ -272,11 +278,11 @@ static int is2_login_client_validate_cert(struct worker_t *self, struct client_t
* Incoming login request
*/
static int is2_in_login_request(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_login_request(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
int rc = 0;
IS2LoginRequest *lr = m->login_request;
Aprsis2__IS2LoginRequest *lr = m->login_request;
if (!lr) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of login request failed",
c->addr_rem, c->username);
@ -381,20 +387,20 @@ static int is2_in_login_request(struct worker_t *self, struct client_t *c, IS2Me
(*c->app_version) ? c->app_version : ""
);
VerificationStatus vs;
Aprsis2__VerificationStatus vs;
switch (c->validated) {
case VALIDATED_WEAK:
vs = VERIFICATION_STATUS__WEAK;
vs = APRSIS2__VERIFICATION_STATUS__WEAK;
break;
case VALIDATED_STRONG:
vs = VERIFICATION_STATUS__WEAK;
vs = APRSIS2__VERIFICATION_STATUS__STRONG;
break;
default:
vs = VERIFICATION_STATUS__NONE;
vs = APRSIS2__VERIFICATION_STATUS__NONE;
}
/* tell the client he's good */
is2_out_login_reply(self, c, IS2_LOGIN_REPLY__LOGIN_RESULT__OK, IS2_LOGIN_REPLY__LOGIN_RESULT_REASON__NONE, vs);
is2_out_login_reply(self, c, APRSIS2__IS2_LOGIN_REPLY__LOGIN_RESULT__OK, APRSIS2__IS2_LOGIN_REPLY__LOGIN_RESULT_REASON__NONE, vs);
/* mark as connected and classify */
worker_mark_client_connected(self, c);
@ -443,11 +449,11 @@ failed_login:
* Incoming packet handler
*/
static int is2_in_packet(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_packet(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
int i;
int r = 0;
ISPacket *p;
Aprsis2__ISPacket *p;
//hlog(LOG_DEBUG, "%s/%s: IS2: %d packets received in message", c->addr_rem, c->username, m->n_is_packet);
@ -456,7 +462,7 @@ static int is2_in_packet(struct worker_t *self, struct client_t *c, IS2Message *
//hlog(LOG_DEBUG, "%s/%s: IS2: packet type %d len %d", c->addr_rem, c->username, p->type, p->is_packet_data.len);
if (p->type == ISPACKET__TYPE__IS_PACKET && p->has_is_packet_data) {
if (p->type == APRSIS2__ISPACKET__TYPE__IS_PACKET && p->has_is_packet_data) {
incoming_handler(self, c, IPPROTO_TCP, (char *)p->is_packet_data.data, p->is_packet_data.len);
}
}
@ -490,14 +496,17 @@ int is2_out_ping(struct worker_t *self, struct client_t *c)
c->ping_timeout = tick + IS2_PING_TIMEOUT;
IS2KeepalivePing ping = IS2_KEEPALIVE_PING__INIT;
ping.ping_type = IS2_KEEPALIVE_PING__PING_TYPE__REQUEST;
Aprsis2__IS2KeepalivePing ping = APRSIS2__IS2_KEEPALIVE_PING__INIT;
ping.ping_type = APRSIS2__IS2_KEEPALIVE_PING__PING_TYPE__REQUEST;
ping.has_ping_type = 1;
ping.request_id = c->ping_request_id = random();
ping.has_request_id = 1;
ping.request_data = rdata;
ping.has_request_data = 1;
IS2Message m = IS2_MESSAGE__INIT;
m.type = IS2_MESSAGE__TYPE__KEEPALIVE_PING;
Aprsis2__IS2Message m = APRSIS2__IS2_MESSAGE__INIT;
m.has_type = 1;
m.type = APRSIS2__IS2_MESSAGE__TYPE__KEEPALIVE_PING;
m.keepalive_ping = &ping;
return is2_write_message(self, c, &m);
@ -507,11 +516,11 @@ int is2_out_ping(struct worker_t *self, struct client_t *c)
* Incoming ping handler, responds with a reply when a request is received
*/
static int is2_in_ping(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_ping(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
int r = 0;
IS2KeepalivePing *ping = m->keepalive_ping;
Aprsis2__IS2KeepalivePing *ping = m->keepalive_ping;
if (!ping) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of ping failed",
c->addr_rem, c->username);
@ -521,16 +530,16 @@ static int is2_in_ping(struct worker_t *self, struct client_t *c, IS2Message *m)
hlog(LOG_DEBUG, "%s/%s: IS2: Ping %s received: request_id %lu",
c->addr_rem, c->username,
(ping->ping_type == IS2_KEEPALIVE_PING__PING_TYPE__REQUEST) ? "request" : "reply",
(ping->ping_type == APRSIS2__IS2_KEEPALIVE_PING__PING_TYPE__REQUEST) ? "request" : "reply",
ping->request_id);
if (ping->ping_type == IS2_KEEPALIVE_PING__PING_TYPE__REQUEST) {
ping->ping_type = IS2_KEEPALIVE_PING__PING_TYPE__REPLY;
if (ping->ping_type == APRSIS2__IS2_KEEPALIVE_PING__PING_TYPE__REQUEST) {
ping->ping_type = APRSIS2__IS2_KEEPALIVE_PING__PING_TYPE__REPLY;
r = is2_write_message(self, c, m);
}
if (ping->ping_type == IS2_KEEPALIVE_PING__PING_TYPE__REPLY && ping->request_id == c->ping_request_id) {
if (ping->ping_type == APRSIS2__IS2_KEEPALIVE_PING__PING_TYPE__REPLY && ping->request_id == c->ping_request_id) {
double diff;
#ifdef USE_CLOCK_GETTIME
struct timespec ts;
@ -578,11 +587,11 @@ done:
* Incoming parameter set handler
*/
static int is2_in_parameter(struct worker_t *self, struct client_t *c, IS2Message *m)
static int is2_in_parameter(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
int r = 0;
IS2Parameter *par = m->parameter;
Aprsis2__IS2Parameter *par = m->parameter;
if (!par) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of parameter message failed: no parameter payload",
c->addr_rem, c->username);
@ -590,7 +599,7 @@ static int is2_in_parameter(struct worker_t *self, struct client_t *c, IS2Messag
goto done;
}
if (par->type != IS2_PARAMETER__TYPE__PARAMETER_SET) {
if (par->type != APRSIS2__IS2_PARAMETER__TYPE__PARAMETER_SET) {
hlog(LOG_WARNING, "%s/%s: IS2: unpacking of parameter message failed: wrong type %d (not PARAMETER_SET)",
c->addr_rem, c->username, par->type);
r = -1;
@ -602,19 +611,21 @@ static int is2_in_parameter(struct worker_t *self, struct client_t *c, IS2Messag
(par->filter_string) ? " filter_string" : "");
/* prepare reply message */
IS2Parameter prep = IS2_PARAMETER__INIT;
prep.type = IS2_PARAMETER__TYPE__PARAMETER_FAILED;
Aprsis2__IS2Parameter prep = APRSIS2__IS2_PARAMETER__INIT;
prep.has_type = 1;
prep.type = APRSIS2__IS2_PARAMETER__TYPE__PARAMETER_FAILED;
prep.has_request_id = par->has_request_id;
if (prep.has_request_id)
prep.request_id = par->request_id;
IS2Message rm = IS2_MESSAGE__INIT;
rm.type = IS2_MESSAGE__TYPE__PARAMETER;
Aprsis2__IS2Message rm = APRSIS2__IS2_MESSAGE__INIT;
rm.has_type = 1;
rm.type = APRSIS2__IS2_MESSAGE__TYPE__PARAMETER;
rm.parameter = &prep;
if (par->filter_string) {
filter_set(c, par->filter_string, strlen(par->filter_string));
prep.type = IS2_PARAMETER__TYPE__PARAMETER_APPLIED;
prep.type = APRSIS2__IS2_PARAMETER__TYPE__PARAMETER_APPLIED;
prep.filter_string = c->filter_s;
} else {
hlog(LOG_WARNING, "%s/%s: IS2: PARAMETER_SET: No parameters found for setting",
@ -632,14 +643,14 @@ done:
* transmit a server signature
*/
int is2_input_handler_uplink_wait_signature(struct worker_t *self, struct client_t *c, IS2Message *m)
int is2_input_handler_uplink_wait_signature(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
switch (m->type) {
case IS2_MESSAGE__TYPE__SERVER_SIGNATURE:
case APRSIS2__IS2_MESSAGE__TYPE__SERVER_SIGNATURE:
return is2_in_server_signature(self, c, m);
case IS2_MESSAGE__TYPE__KEEPALIVE_PING:
case APRSIS2__IS2_MESSAGE__TYPE__KEEPALIVE_PING:
return is2_in_ping(self, c, m);
case IS2_MESSAGE__TYPE__LOGIN_REPLY:
case APRSIS2__IS2_MESSAGE__TYPE__LOGIN_REPLY:
return is2_in_login_reply(self, c, m);
default:
hlog(LOG_WARNING, "%s/%s: IS2: connect: unknown message type %d",
@ -654,13 +665,13 @@ int is2_input_handler_uplink_wait_signature(struct worker_t *self, struct client
* IS2 input handler, when waiting for a login command
*/
int is2_input_handler_login(struct worker_t *self, struct client_t *c, IS2Message *m)
int is2_input_handler_login(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
switch (m->type) {
case IS2_MESSAGE__TYPE__KEEPALIVE_PING:
case APRSIS2__IS2_MESSAGE__TYPE__KEEPALIVE_PING:
return is2_in_ping(self, c, m);
break;
case IS2_MESSAGE__TYPE__LOGIN_REQUEST:
case APRSIS2__IS2_MESSAGE__TYPE__LOGIN_REQUEST:
return is2_in_login_request(self, c, m);
break;
default:
@ -676,16 +687,16 @@ int is2_input_handler_login(struct worker_t *self, struct client_t *c, IS2Messag
* IS2 input handler, connected state
*/
int is2_input_handler(struct worker_t *self, struct client_t *c, IS2Message *m)
int is2_input_handler(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
switch (m->type) {
case IS2_MESSAGE__TYPE__KEEPALIVE_PING:
case APRSIS2__IS2_MESSAGE__TYPE__KEEPALIVE_PING:
return is2_in_ping(self, c, m);
break;
case IS2_MESSAGE__TYPE__PARAMETER:
case APRSIS2__IS2_MESSAGE__TYPE__PARAMETER:
return is2_in_parameter(self, c, m);
break;
case IS2_MESSAGE__TYPE__IS_PACKET:
case APRSIS2__IS2_MESSAGE__TYPE__IS_PACKET:
return is2_in_packet(self, c, m);
break;
default:
@ -701,13 +712,13 @@ int is2_input_handler(struct worker_t *self, struct client_t *c, IS2Message *m)
* IS2 input handler, corepeer state
*/
int is2_input_handler_corepeer(struct worker_t *self, struct client_t *c, IS2Message *m)
int is2_input_handler_corepeer(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m)
{
switch (m->type) {
case IS2_MESSAGE__TYPE__KEEPALIVE_PING:
case APRSIS2__IS2_MESSAGE__TYPE__KEEPALIVE_PING:
return is2_in_ping(self, c, m);
break;
case IS2_MESSAGE__TYPE__IS_PACKET:
case APRSIS2__IS2_MESSAGE__TYPE__IS_PACKET:
return is2_in_packet(self, c, m);
break;
default:
@ -725,7 +736,7 @@ int is2_input_handler_corepeer(struct worker_t *self, struct client_t *c, IS2Mes
static int is2_unpack_message(struct worker_t *self, struct client_t *c, void *buf, int len)
{
IS2Message *m = is2_message__unpack(NULL, len, buf);
Aprsis2__IS2Message *m = aprsis2__is2_message__unpack(NULL, len, buf);
if (!m) {
hlog_packet(LOG_WARNING, buf, len, "%s/%s: IS2: unpacking of message failed: ",
c->addr_rem, c->username);
@ -735,7 +746,7 @@ static int is2_unpack_message(struct worker_t *self, struct client_t *c, void *b
/* Call the current input message handler */
int r = c->is2_input_handler(self, c, m);
is2_message__free_unpacked(m, NULL);
aprsis2__is2_message__free_unpacked(m, NULL);
return r;
}
@ -845,31 +856,33 @@ int is2_corepeer_deframe_input(struct worker_t *self, struct client_t *c, char *
* OPTIMIZE: generate packet once, or reuse incoming prepacked buffer
*/
static int is2_encode_packet(IS2Message *m, ProtobufCBinaryData *data, char *p, int len)
static int is2_encode_packet(Aprsis2__IS2Message *m, ProtobufCBinaryData *data, char *p, int len)
{
data->data = (uint8_t *)p;
data->len = len;
int n = 1; // just one packet
int i;
ISPacket **subs = hmalloc(sizeof(ISPacket*) * n);
Aprsis2__ISPacket **subs = hmalloc(sizeof(Aprsis2__ISPacket*) * n);
for (i = 0; i < n; i++) {
//hlog(LOG_DEBUG, "packing packet %d", i);
subs[i] = hmalloc(sizeof(ISPacket));
ispacket__init(subs[i]);
subs[i]->type = ISPACKET__TYPE__IS_PACKET;
subs[i] = hmalloc(sizeof(Aprsis2__ISPacket));
aprsis2__ispacket__init(subs[i]);
subs[i]->has_type = 1;
subs[i]->type = APRSIS2__ISPACKET__TYPE__IS_PACKET;
subs[i]->has_is_packet_data = 1;
subs[i]->is_packet_data = *data;
}
m->type = IS2_MESSAGE__TYPE__IS_PACKET;
m->has_type = 1;
m->type = APRSIS2__IS2_MESSAGE__TYPE__IS_PACKET;
m->n_is_packet = n;
m->is_packet = subs;
return i;
}
void is2_free_encoded_packets(IS2Message *m)
void is2_free_encoded_packets(Aprsis2__IS2Message *m)
{
int i;
@ -886,7 +899,7 @@ int is2_write_packet(struct worker_t *self, struct client_t *c, char *p, int len
//hlog(LOG_DEBUG, "%s/%s: IS2: writing IS packet of %d bytes", c->addr_rem, c->username, len);
IS2Message m = IS2_MESSAGE__INIT;
Aprsis2__IS2Message m = APRSIS2__IS2_MESSAGE__INIT;
ProtobufCBinaryData data;
is2_encode_packet(&m, &data, p, len);
@ -910,7 +923,7 @@ int is2_corepeer_write_packet(struct worker_t *self, struct client_t *c, char *p
//hlog(LOG_DEBUG, "%s/%s: IS2: writing IS packet of %d bytes", c->addr_rem, c->username, len);
IS2Message m = IS2_MESSAGE__INIT;
Aprsis2__IS2Message m = APRSIS2__IS2_MESSAGE__INIT;
ProtobufCBinaryData data;
is2_encode_packet(&m, &data, p, len);

View File

@ -4,9 +4,9 @@
#include "worker.h"
extern int is2_input_handler_login(struct worker_t *self, struct client_t *c, IS2Message *m);
extern int is2_input_handler_uplink_wait_signature(struct worker_t *self, struct client_t *c, IS2Message *m);
extern int is2_input_handler(struct worker_t *self, struct client_t *c, IS2Message *m);
extern int is2_input_handler_login(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m);
extern int is2_input_handler_uplink_wait_signature(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m);
extern int is2_input_handler(struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *m);
extern int is2_out_server_signature(struct worker_t *self, struct client_t *c);
extern int is2_deframe_input(struct worker_t *self, struct client_t *c, int start_at);

View File

@ -1,4 +1,6 @@
syntax = "proto2";
syntax = "proto3";
package aprsis2;
//
// A server sends an IS2ServerSignature to all new clients.
@ -9,9 +11,9 @@ syntax = "proto2";
//
message IS2ServerSignature {
required string username = 1; // callsign-SSID
required string app_name = 2;
required string app_version = 3;
string username = 1; // callsign-SSID
string app_name = 2;
string app_version = 3;
repeated string features = 4; // list of supported optional features
}
@ -24,10 +26,10 @@ message IS2ServerSignature {
//
message IS2LoginRequest {
required string username = 1; // callsign-SSID
optional string password = 2; // passcode or password
required string app_name = 3;
required string app_version = 4;
string username = 1; // callsign-SSID
string password = 2; // passcode or password
string app_name = 3;
string app_version = 4;
// 5: unused
repeated string features_req = 6; // list of requested optional features
}
@ -83,10 +85,10 @@ message IS2LoginReply {
CERT_EXPIRED = 5;
}
required LoginResult result = 1;
required VerificationStatus verified = 2;
optional LoginResultReason result_code = 3;
optional string result_message = 4; // english descriptive
LoginResult result = 1;
VerificationStatus verified = 2;
LoginResultReason result_code = 3;
string result_message = 4; // english descriptive
repeated string features_ack = 5; // list of agreed optional features
}
@ -105,13 +107,14 @@ message IS2LoginReply {
message IS2KeepalivePing {
enum PingType {
UNDEFINED = 0;
REQUEST = 1;
REPLY = 2;
}
required PingType ping_type = 1;
required uint32 request_id = 2;
optional bytes request_data = 3;
PingType ping_type = 1;
uint32 request_id = 2;
bytes request_data = 3;
}
//
@ -120,15 +123,16 @@ message IS2KeepalivePing {
message ISPacket {
enum Type {
UNDEFINED = 0;
// Traditional APRS-IS format with embedded Q construct
IS_PACKET = 2;
}
// Identifies which message is filled in.
required Type type = 1;
Type type = 1;
// packet data in traditional APRS-IS format, without CRLF
optional bytes is_packet_data = 2;
bytes is_packet_data = 2;
}
//
@ -156,16 +160,17 @@ message ISPacket {
message IS2Parameter {
enum Type {
PARAMETER_UNDEFINED = 0;
PARAMETER_CURRENT = 1; // this is the current value of the parameter
PARAMETER_SET = 2; // set a parameter to this value
PARAMETER_APPLIED = 3; // parameter has been set successfully
PARAMETER_FAILED = 4; // parameter change failed
}
required Type type = 1;
optional int32 request_id = 2;
Type type = 1;
int32 request_id = 2;
optional string filter_string = 3;
string filter_string = 3;
}
//
@ -180,6 +185,7 @@ message IS2Parameter {
message IS2Message {
enum Type {
UNDEFINED = 0;
SERVER_SIGNATURE = 2;
LOGIN_REQUEST = 3;
LOGIN_REPLY = 4;
@ -189,19 +195,19 @@ message IS2Message {
}
// Identifies which message is filled in.
required Type type = 1;
Type type = 1;
// For UDP packets, a sequence number may be transmitted
optional uint32 sequence = 2;
uint32 sequence = 2;
// For UDP packets, a HMAC signature may be transmitted
optional bytes signature = 3;
bytes signature = 3;
// One of the following will be filled in. Just one.
optional IS2ServerSignature server_signature = 21;
optional IS2LoginRequest login_request = 22;
optional IS2LoginReply login_reply = 23;
optional IS2KeepalivePing keepalive_ping = 24;
IS2ServerSignature server_signature = 21;
IS2LoginRequest login_request = 22;
IS2LoginReply login_reply = 23;
IS2KeepalivePing keepalive_ping = 24;
repeated ISPacket is_packet = 25;
optional IS2Parameter parameter = 26;
IS2Parameter parameter = 26;
}

View File

@ -368,7 +368,7 @@ struct client_t {
/* the current handler function for incoming lines */
int (*handler_line_in) (struct worker_t *self, struct client_t *c, int l4proto, char *s, int len);
int (*is2_input_handler) (struct worker_t *self, struct client_t *c, IS2Message *message);
int (*is2_input_handler) (struct worker_t *self, struct client_t *c, Aprsis2__IS2Message *message);
int (*handler_consume_input) (struct worker_t *self, struct client_t *c, int start_at);
int (*write) (struct worker_t *self, struct client_t *c, char *p, int len);
int (*write_packet) (struct worker_t *self, struct client_t *c, char *p, int len);

View File

@ -11,9 +11,11 @@ use IO::Socket::INET;
use IO::Select;
use Data::Dumper;
use Google::ProtocolBuffers;
use Google::ProtocolBuffers::Dynamic;
Google::ProtocolBuffers->parsefile("../src/aprsis2.proto", { create_accessors => 1 });
my $pf = Google::ProtocolBuffers::Dynamic->new("../src");
$pf->load_file("aprsis2.proto");
$pf->map({package => "aprsis2", prefix => "APRSIS2"});
our $VERSION = '0.01';
@ -184,15 +186,15 @@ sub connect($;%)
}
# send login request
my $lm = IS2LoginRequest->new({
my $lm = APRSIS2::IS2LoginRequest->new({
'username' => $self->{'mycall'},
'password' => $self->{'aprspass'},
'app_name' => $aprs_appname,
'app_version' => $VERSION
});
my $im = IS2Message->new({
'type' => IS2Message::Type::LOGIN_REQUEST(),
my $im = APRSIS2::IS2Message->new({
'type' => APRSIS2::IS2Message::Type::LOGIN_REQUEST(),
'login_request' => $lm
});
@ -200,8 +202,8 @@ sub connect($;%)
my $t = time();
while (my $l = $self->is2_frame_in()) {
my $rep = $l->login_reply;
if ($l->type == IS2Message::Type::LOGIN_REPLY()) {
if ($l->get_type() == APRSIS2::IS2Message::Type::LOGIN_REPLY()) {
my $rep = $l->get_login_reply();
if (!$rep) {
$self->{'error'} = "LOGIN_REPLY type, but no login_reply message";
return 0;
@ -212,18 +214,18 @@ sub connect($;%)
# defined $rep->result_code ? $rep->result_code : 0,
# defined $rep->result_message ? $rep->result_message : '');
if ($rep->result != IS2LoginReply::LoginResult::OK()) {
if ($rep->get_result() != APRSIS2::IS2LoginReply::LoginResult::OK()) {
$self->{'error'} = sprintf("Login reply: login failed, code %d: %s",
defined $rep->result_code ? $rep->result_code : 0,
defined $rep->result_message ? $rep->result_message : '');
defined $rep->get_result_code() ? $rep->get_result_code() : 0,
defined $rep->get_result_message() ? $rep->get_result_message() : '');
return 0;
}
if ($self->{'aprspass'} != -1 && $rep->verified < 1) {
if ($self->{'aprspass'} != -1 && $rep->get_verified() < 1) {
$self->{'error'} = sprintf("Login reply: login not verified (%d), code %d: %s",
$rep->verified,
defined $rep->result_code ? $rep->result_code : 0,
defined $rep->result_message ? $rep->result_message : '');
$rep->get_verified(),
defined $rep->get_result_code() ? $rep->get_result_code() : 0,
defined $rep->get_result_message() ? $rep->get_result_message() : '');
return 0;
}
@ -253,14 +255,14 @@ sub send_packets($$)
my @pq;
foreach my $p (@{ $packets }) {
push @pq, ISPacket->new({
'type' => ISPacket::Type::IS_PACKET(),
push @pq, APRSIS2::ISPacket->new({
'type' => APRSIS2::ISPacket::Type::IS_PACKET(),
'is_packet_data' => $p
});
}
my $im = IS2Message->new({
'type' => IS2Message::Type::IS_PACKET(),
my $im = APRSIS2::IS2Message->new({
'type' => APRSIS2::IS2Message::Type::IS_PACKET(),
'is_packet' => \@pq
});
@ -274,9 +276,9 @@ sub wait_signature($)
# wait for server signature
my $t = time();
while (my $l = $self->is2_frame_in()) {
my $sig = $l->server_signature;
my $sig = $l->get_server_signature();
if ($l->type == IS2Message::Type::SERVER_SIGNATURE()) {
if ($l->get_type() == APRSIS2::IS2Message::Type::SERVER_SIGNATURE()) {
if (!$sig) {
$self->{'error'} = "SERVER_SIGNATURE type, but no server signature message";
return 0;
@ -285,7 +287,7 @@ sub wait_signature($)
#warn sprintf("got server signature: serverid '%s' app '%s' version '%s'\n",
# $sig->username, $sig->app_name, $sig->app_version);
} else {
$self->{'error'} = "Wrong type of message received instead of SERVER_SIGNATURE: " . $l->type;
$self->{'error'} = "Wrong type of message received instead of SERVER_SIGNATURE: " . $l->get_type();
return 0;
}
@ -306,10 +308,10 @@ sub ping($)
my $timeout = 2;
my $reqid = int(rand(2**30));
my $im = IS2Message->new({
'type' => IS2Message::Type::KEEPALIVE_PING(),
'keepalive_ping' => IS2KeepalivePing->new({
'ping_type' => IS2KeepalivePing::PingType::REQUEST(),
my $im = APRSIS2::IS2Message->new({
'type' => APRSIS2::IS2Message::Type::KEEPALIVE_PING(),
'keepalive_ping' => APRSIS2::IS2KeepalivePing->new({
'ping_type' => APRSIS2::IS2KeepalivePing::PingType::REQUEST(),
'request_id' => $reqid,
})
});
@ -319,23 +321,24 @@ sub ping($)
my $t = time();
while (my $l = $self->is2_frame_in($timeout)) {
if ($l->type != IS2Message::Type::KEEPALIVE_PING()) {
warn "IS2 ping: Unexpected type of frame received: " . $l->type . "\n";
if ($l->get_type() != APRSIS2::IS2Message::Type::KEEPALIVE_PING()) {
warn "IS2 ping: Unexpected type of frame received: " . $l->get_type() . "\n";
next;
}
if (!defined $l->keepalive_ping) {
my $ping = $l->get_keepalive_ping();
if (!defined $ping) {
$self->{'error'} = "IS2 ping reply does not have keepalive_ping payload";
return undef;
}
if ($l->keepalive_ping->ping_type != IS2KeepalivePing::PingType::REPLY()) {
$self->{'error'} = "IS2 ping: Wrong type of frame received: " . $l->type;
if ($ping->get_ping_type() != APRSIS2::IS2KeepalivePing::PingType::REPLY()) {
$self->{'error'} = "IS2 ping: Wrong type of ping frame received: " . $ping->get_ping_time();
return undef;
}
if ($l->keepalive_ping->request_id != $reqid) {
$self->{'error'} = "IS2 ping: Request id mismatch, sent $reqid, got " . $l->keepalive_ping->request_id;
if ($ping->get_request_id() != $reqid) {
$self->{'error'} = "IS2 ping: Request id mismatch, sent $reqid, got " . $ping->get_request_id();
return undef;
}
@ -359,8 +362,8 @@ sub get_packets($;$)
my $t = time();
while (my $l = $self->is2_frame_in($timeout)) {
my $ips = $l->is_packet;
if ($l->type == IS2Message::Type::IS_PACKET()) {
if ($l->get_type() == APRSIS2::IS2Message::Type::IS_PACKET()) {
my $ips = $l->get_is_packet_list();
if (!$ips) {
$self->{'error'} = "IS_PACKET type, but no packets";
return undef;
@ -369,17 +372,17 @@ sub get_packets($;$)
my @pa;
foreach my $ip (@{ $ips }) {
if ($ip->type != ISPacket::Type::IS_PACKET()) {
$self->{'error'} = sprintf("ISPacket type %d unsupported", $ip->type);
if ($ip->get_type() != APRSIS2::ISPacket::Type::IS_PACKET()) {
$self->{'error'} = sprintf("ISPacket type %d unsupported", $ip->get_type());
return undef;
}
push @pa, $ip->is_packet_data;
push @pa, $ip->get_is_packet_data();
}
return @pa;
} else {
$self->{'error'} = "Wrong type of frame received: " . $l->type;
$self->{'error'} = "Wrong type of frame received: " . $l->get_type();
return undef;
}
@ -415,10 +418,10 @@ sub set_filter($$)
my $reqid = int(rand(2**30));
my $im = IS2Message->new({
'type' => IS2Message::Type::PARAMETER(),
'parameter' => IS2Parameter->new({
'type' => IS2Parameter::Type::PARAMETER_SET(),
my $im = APRSIS2::IS2Message->new({
'type' => APRSIS2::IS2Message::Type::PARAMETER(),
'parameter' => APRSIS2::IS2Parameter->new({
'type' => APRSIS2::IS2Parameter::Type::PARAMETER_SET(),
'request_id' => $reqid, # todo: sequential
'filter_string' => $filter
})
@ -428,19 +431,19 @@ sub set_filter($$)
my $t = time();
while (my $l = $self->is2_frame_in()) {
my $rep = $l->parameter;
if ($l->type == IS2Message::Type::PARAMETER()) {
if ($l->get_type() == APRSIS2::IS2Message::Type::PARAMETER()) {
my $rep = $l->get_parameter();
if (!$rep) {
$self->{'error'} = "PARAMETER type, but no parameter message";
return 0;
}
if ($rep->request_id != $reqid) {
$self->{'error'} = "PARAMETER reply, wrong request id " . $rep->request_id . ", expected $reqid";
if ($rep->get_request_id() != $reqid) {
$self->{'error'} = "PARAMETER reply, wrong request id " . $rep->get_request_id() . ", expected $reqid";
return 0;
}
if ($rep->type != IS2Parameter::Type::PARAMETER_APPLIED()) {
if ($rep->get_type() != APRSIS2::IS2Parameter::Type::PARAMETER_APPLIED()) {
$self->{'error'} = sprintf("filter set reply: not applied");
return 0;
}
@ -448,7 +451,7 @@ sub set_filter($$)
# todo: check sequence
return 1;
} else {
$self->{'error'} = "Wrong type of response received for PARAMETER_SET: " . $l->type;
$self->{'error'} = "Wrong type of response received for PARAMETER_SET: " . $l->get_type();
return 0;
}
@ -528,8 +531,8 @@ sub is2_frame_in($;$)
my $frame = substr($self->{'ibuf'}, 4, $frame_len);
$self->{'ibuf'} = substr($self->{'ibuf'}, $need_bytes);
my $is2_msg = IS2Message->decode($frame);
my $is2_msg = APRSIS2::IS2Message->decode($frame);
#warn "decoded: " . Dumper($is2_msg) . "\n";
#warn "left in ibuf: " . length($self->{'ibuf'}) . "\n";
return $is2_msg;
}