Author: astitcher
Date: Tue Jun 3 20:43:20 2014
New Revision: 1599793
URL: http://svn.apache.org/r1599793
Log:
PROTON-591, PROTON-590: Change frame dispatch to use switch statement
- Rather than an explicit function table
- This reduces the per connection memory use significantly
- Fixes a possible crash if Proton receives an unknown performative
Added:
qpid/proton/trunk/proton-c/src/dispatch_actions.h
Modified:
qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h
qpid/proton/trunk/proton-c/src/sasl/sasl.c
qpid/proton/trunk/proton-c/src/transport/transport.c
Added: qpid/proton/trunk/proton-c/src/dispatch_actions.h
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatch_actions.h?rev=1599793&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatch_actions.h (added)
+++ qpid/proton/trunk/proton-c/src/dispatch_actions.h Tue Jun 3 20:43:20 2014
@@ -0,0 +1,45 @@
+#ifndef _PROTON_DISPATCH_ACTIONS_H
+#define _PROTON_DISPATCH_ACTIONS_H 1
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "dispatcher/dispatcher.h"
+
+/* Transport actions */
+int pn_do_open(pn_dispatcher_t *disp);
+int pn_do_begin(pn_dispatcher_t *disp);
+int pn_do_attach(pn_dispatcher_t *disp);
+int pn_do_transfer(pn_dispatcher_t *disp);
+int pn_do_flow(pn_dispatcher_t *disp);
+int pn_do_disposition(pn_dispatcher_t *disp);
+int pn_do_detach(pn_dispatcher_t *disp);
+int pn_do_end(pn_dispatcher_t *disp);
+int pn_do_close(pn_dispatcher_t *disp);
+
+/* SASL actions */
+int pn_do_init(pn_dispatcher_t *disp);
+int pn_do_mechanisms(pn_dispatcher_t *disp);
+int pn_do_challenge(pn_dispatcher_t *disp);
+int pn_do_response(pn_dispatcher_t *disp);
+int pn_do_outcome(pn_dispatcher_t *disp);
+
+#endif // _PROTON_DISPATCH_ACTIONS_H
Modified: qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c (original)
+++ qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.c Tue Jun 3 20:43:20
2014
@@ -30,6 +30,41 @@
#include "../util.h"
#include "../platform_fmt.h"
+#include "dispatch_actions.h"
+
+int pni_bad_frame(pn_dispatcher_t* disp) {
+ pn_transport_log(disp->transport, "Error dispatching frame: Unknown
performative");
+ return PN_ERR;
+}
+
+// We could use a table based approach here if we needed to dynamically
+// add new performatives
+inline int pni_dispatch_action(pn_dispatcher_t* disp, uint64_t lcode)
+{
+ pn_action_t *action;
+ switch (lcode) {
+ /* Regular AMQP fames */
+ case OPEN: action = pn_do_open; break;
+ case BEGIN: action = pn_do_begin; break;
+ case ATTACH: action = pn_do_attach; break;
+ case FLOW: action = pn_do_flow; break;
+ case TRANSFER: action = pn_do_transfer; break;
+ case DISPOSITION: action = pn_do_disposition; break;
+ case DETACH: action = pn_do_detach; break;
+ case END: action = pn_do_end; break;
+ case CLOSE: action = pn_do_close; break;
+
+ /* SASL frames */
+ case SASL_MECHANISMS: action = pn_do_mechanisms; break;
+ case SASL_INIT: action = pn_do_init; break;
+ case SASL_CHALLENGE: action = pn_do_challenge; break;
+ case SASL_RESPONSE: action = pn_do_response; break;
+ case SASL_OUTCOME: action = pn_do_outcome; break;
+ default: action = pni_bad_frame; break;
+ };
+ return action(disp);
+}
+
pn_dispatcher_t *pn_dispatcher(uint8_t frame_type, pn_transport_t *transport)
{
pn_dispatcher_t *disp = (pn_dispatcher_t *) calloc(sizeof(pn_dispatcher_t),
1);
@@ -44,7 +79,6 @@ pn_dispatcher_t *pn_dispatcher(uint8_t f
disp->fragment = 0;
disp->channel = 0;
- disp->code = 0;
disp->args = pn_data(16);
disp->payload = NULL;
disp->size = 0;
@@ -77,12 +111,6 @@ void pn_dispatcher_free(pn_dispatcher_t
}
}
-void pn_dispatcher_action(pn_dispatcher_t *disp, uint8_t code,
- pn_action_t *action)
-{
- disp->actions[code] = action;
-}
-
typedef enum {IN, OUT} pn_dir_t;
static void pn_do_trace(pn_dispatcher_t *disp, uint16_t ch, pn_dir_t dir,
@@ -122,7 +150,8 @@ int pn_dispatch_frame(pn_dispatcher_t *d
}
disp->channel = frame.channel;
- // XXX: assuming numeric
+ // XXX: assuming numeric -
+ // if we get a symbol we should map it to the numeric value and dispatch on
that
uint64_t lcode;
bool scanned;
int e = pn_data_scan(disp->args, "D?L.", &scanned, &lcode);
@@ -134,19 +163,15 @@ int pn_dispatch_frame(pn_dispatcher_t *d
pn_transport_log(disp->transport, "Error dispatching frame");
return PN_ERR;
}
- uint8_t code = lcode;
- disp->code = code;
disp->size = frame.size - dsize;
if (disp->size)
disp->payload = frame.payload + dsize;
pn_do_trace(disp, disp->channel, IN, disp->args, disp->payload, disp->size);
- pn_action_t *action = disp->actions[code];
- int err = action(disp);
+ int err = pni_dispatch_action(disp, lcode);
disp->channel = 0;
- disp->code = 0;
pn_data_clear(disp->args);
disp->size = 0;
disp->payload = NULL;
Modified: qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h (original)
+++ qpid/proton/trunk/proton-c/src/dispatcher/dispatcher.h Tue Jun 3 20:43:20
2014
@@ -34,7 +34,6 @@ typedef struct pn_dispatcher_t pn_dispat
typedef int (pn_action_t)(pn_dispatcher_t *disp);
struct pn_dispatcher_t {
- pn_action_t *actions[256];
pn_buffer_t *input;
size_t fragment;
pn_data_t *args;
@@ -48,22 +47,19 @@ struct pn_dispatcher_t {
size_t capacity;
size_t available; /* number of raw bytes pending output */
char *output;
- pn_transport_t *transport;
+ pn_transport_t *transport; // TODO: We keep this to get access to logging -
perhaps move logging
uint64_t output_frames_ct;
uint64_t input_frames_ct;
pn_string_t *scratch;
pn_trace_t trace;
uint16_t channel;
- uint8_t frame_type;
- uint8_t code;
+ uint8_t frame_type; // Used when constructing outgoing frames
bool halt;
bool batch;
};
pn_dispatcher_t *pn_dispatcher(uint8_t frame_type, pn_transport_t *transport);
void pn_dispatcher_free(pn_dispatcher_t *disp);
-void pn_dispatcher_action(pn_dispatcher_t *disp, uint8_t code,
- pn_action_t *action);
int pn_scan_args(pn_dispatcher_t *disp, const char *fmt, ...);
void pn_set_payload(pn_dispatcher_t *disp, const char *data, size_t size);
int pn_post_frame(pn_dispatcher_t *disp, uint16_t ch, const char *fmt, ...);
Modified: qpid/proton/trunk/proton-c/src/sasl/sasl.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/sasl/sasl.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/sasl/sasl.c (original)
+++ qpid/proton/trunk/proton-c/src/sasl/sasl.c Tue Jun 3 20:43:20 2014
@@ -27,6 +27,7 @@
#include <proton/engine.h> // XXX: just needed for PN_EOS
#include <proton/sasl.h>
#include "protocol.h"
+#include "dispatch_actions.h"
#include "../dispatcher/dispatcher.h"
#include "../engine/engine-internal.h"
#include "../util.h"
@@ -55,12 +56,6 @@ static ssize_t pn_input_read_sasl(pn_io_
static ssize_t pn_output_write_sasl_header(pn_io_layer_t *io_layer, char
*bytes, size_t available);
static ssize_t pn_output_write_sasl(pn_io_layer_t *io_layer, char *bytes,
size_t available);
-int pn_do_init(pn_dispatcher_t *disp);
-int pn_do_mechanisms(pn_dispatcher_t *disp);
-int pn_do_challenge(pn_dispatcher_t *disp);
-int pn_do_response(pn_dispatcher_t *disp);
-int pn_do_outcome(pn_dispatcher_t *disp);
-
pn_sasl_t *pn_sasl(pn_transport_t *transport)
{
if (!transport->sasl) {
@@ -68,12 +63,6 @@ pn_sasl_t *pn_sasl(pn_transport_t *trans
sasl->disp = pn_dispatcher(1, transport);
sasl->disp->batch = false;
- pn_dispatcher_action(sasl->disp, SASL_INIT, pn_do_init);
- pn_dispatcher_action(sasl->disp, SASL_MECHANISMS, pn_do_mechanisms);
- pn_dispatcher_action(sasl->disp, SASL_CHALLENGE, pn_do_challenge);
- pn_dispatcher_action(sasl->disp, SASL_RESPONSE, pn_do_response);
- pn_dispatcher_action(sasl->disp, SASL_OUTCOME, pn_do_outcome);
-
sasl->client = false;
sasl->configured = false;
sasl->mechanisms = NULL;
Modified: qpid/proton/trunk/proton-c/src/transport/transport.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/transport/transport.c?rev=1599793&r1=1599792&r2=1599793&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/transport/transport.c (original)
+++ qpid/proton/trunk/proton-c/src/transport/transport.c Tue Jun 3 20:43:20
2014
@@ -24,6 +24,7 @@
#include <string.h>
#include <proton/framing.h>
#include "protocol.h"
+#include "dispatch_actions.h"
#include <assert.h>
#include <stdarg.h>
@@ -92,16 +93,6 @@ void pn_delivery_map_clear(pn_delivery_m
}
}
-int pn_do_open(pn_dispatcher_t *disp);
-int pn_do_begin(pn_dispatcher_t *disp);
-int pn_do_attach(pn_dispatcher_t *disp);
-int pn_do_transfer(pn_dispatcher_t *disp);
-int pn_do_flow(pn_dispatcher_t *disp);
-int pn_do_disposition(pn_dispatcher_t *disp);
-int pn_do_detach(pn_dispatcher_t *disp);
-int pn_do_end(pn_dispatcher_t *disp);
-int pn_do_close(pn_dispatcher_t *disp);
-
static ssize_t pn_input_read_amqp_header(pn_io_layer_t *io_layer, const char
*bytes, size_t available);
static ssize_t pn_input_read_amqp(pn_io_layer_t *io_layer, const char *bytes,
size_t available);
static ssize_t pn_output_write_amqp_header(pn_io_layer_t *io_layer, char
*bytes, size_t available);
@@ -150,16 +141,6 @@ static void pn_transport_initialize(void
amqp->buffered_input = NULL;
amqp->next = NULL;
- pn_dispatcher_action(transport->disp, OPEN, pn_do_open);
- pn_dispatcher_action(transport->disp, BEGIN, pn_do_begin);
- pn_dispatcher_action(transport->disp, ATTACH, pn_do_attach);
- pn_dispatcher_action(transport->disp, TRANSFER, pn_do_transfer);
- pn_dispatcher_action(transport->disp, FLOW, pn_do_flow);
- pn_dispatcher_action(transport->disp, DISPOSITION, pn_do_disposition);
- pn_dispatcher_action(transport->disp, DETACH, pn_do_detach);
- pn_dispatcher_action(transport->disp, END, pn_do_end);
- pn_dispatcher_action(transport->disp, CLOSE, pn_do_close);
-
transport->open_sent = false;
transport->open_rcvd = false;
transport->close_sent = false;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]