From 1dfba6333a8897c50d2f0cf589155beffdb2f80c Mon Sep 17 00:00:00 2001 From: Heikki Hannikainen Date: Wed, 26 Oct 2022 01:51:38 +0300 Subject: [PATCH] IS2: Go to protobuf v3 --- src/aprsis2.c | 161 ++++++++++++++++++---------------- src/aprsis2.h | 6 +- src/aprsis2.proto | 62 +++++++------ src/worker.h | 2 +- tests/libperl/Ham/APRS/IS2.pm | 103 +++++++++++----------- 5 files changed, 178 insertions(+), 156 deletions(-) diff --git a/src/aprsis2.c b/src/aprsis2.c index 4d09492..76b7b98 100644 --- a/src/aprsis2.c +++ b/src/aprsis2.c @@ -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); diff --git a/src/aprsis2.h b/src/aprsis2.h index f77d626..c43b40e 100644 --- a/src/aprsis2.h +++ b/src/aprsis2.h @@ -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); diff --git a/src/aprsis2.proto b/src/aprsis2.proto index b3eb9eb..59e8f28 100644 --- a/src/aprsis2.proto +++ b/src/aprsis2.proto @@ -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; } diff --git a/src/worker.h b/src/worker.h index a378c44..da9e1f8 100644 --- a/src/worker.h +++ b/src/worker.h @@ -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); diff --git a/tests/libperl/Ham/APRS/IS2.pm b/tests/libperl/Ham/APRS/IS2.pm index 411b481..026d413 100644 --- a/tests/libperl/Ham/APRS/IS2.pm +++ b/tests/libperl/Ham/APRS/IS2.pm @@ -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; }