You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2016/11/14 18:28:29 UTC
[08/20] qpid-proton git commit: PROTON-1350 PROTON-1351: Introduce
proton-c core library - Created new core proton library qpid-proton-core
which only contains protocol processsing and no IO. - Rearranged source tree
to separate core protocol code and
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/object.c
----------------------------------------------------------------------
diff --git a/proton-c/src/object/object.c b/proton-c/src/object/object.c
deleted file mode 100644
index b0c1b33..0000000
--- a/proton-c/src/object/object.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- *
- * 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 <proton/object.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#define pn_object_initialize NULL
-#define pn_object_finalize NULL
-#define pn_object_inspect NULL
-uintptr_t pn_object_hashcode(void *object) { return (uintptr_t) object; }
-intptr_t pn_object_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
-
-const pn_class_t PN_OBJECT[] = {PN_CLASS(pn_object)};
-
-#define pn_void_initialize NULL
-static void *pn_void_new(const pn_class_t *clazz, size_t size) { return malloc(size); }
-static void pn_void_incref(void *object) {}
-static void pn_void_decref(void *object) {}
-static int pn_void_refcount(void *object) { return -1; }
-#define pn_void_finalize NULL
-static void pn_void_free(void *object) { free(object); }
-static const pn_class_t *pn_void_reify(void *object) { return PN_VOID; }
-uintptr_t pn_void_hashcode(void *object) { return (uintptr_t) object; }
-intptr_t pn_void_compare(void *a, void *b) { return (intptr_t) a - (intptr_t) b; }
-int pn_void_inspect(void *object, pn_string_t *dst) { return pn_string_addf(dst, "%p", object); }
-
-const pn_class_t PN_VOID[] = {PN_METACLASS(pn_void)};
-
-const char *pn_class_name(const pn_class_t *clazz)
-{
- return clazz->name;
-}
-
-pn_cid_t pn_class_id(const pn_class_t *clazz)
-{
- return clazz->cid;
-}
-
-void *pn_class_new(const pn_class_t *clazz, size_t size)
-{
- assert(clazz);
- void *object = clazz->newinst(clazz, size);
- if (clazz->initialize) {
- clazz->initialize(object);
- }
- return object;
-}
-
-void *pn_class_incref(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
- if (object) {
- clazz = clazz->reify(object);
- clazz->incref(object);
- }
- return object;
-}
-
-int pn_class_refcount(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
- clazz = clazz->reify(object);
- return clazz->refcount(object);
-}
-
-int pn_class_decref(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
-
- if (object) {
- clazz = clazz->reify(object);
- clazz->decref(object);
- int rc = clazz->refcount(object);
- if (rc == 0) {
- if (clazz->finalize) {
- clazz->finalize(object);
- // check the refcount again in case the finalizer created a
- // new reference
- rc = clazz->refcount(object);
- }
- if (rc == 0) {
- clazz->free(object);
- return 0;
- }
- } else {
- return rc;
- }
- }
-
- return 0;
-}
-
-void pn_class_free(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
- if (object) {
- clazz = clazz->reify(object);
- int rc = clazz->refcount(object);
- assert(rc == 1 || rc == -1);
- if (rc == 1) {
- rc = pn_class_decref(clazz, object);
- assert(rc == 0);
- } else {
- if (clazz->finalize) {
- clazz->finalize(object);
- }
- clazz->free(object);
- }
- }
-}
-
-const pn_class_t *pn_class_reify(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
- return clazz->reify(object);
-}
-
-uintptr_t pn_class_hashcode(const pn_class_t *clazz, void *object)
-{
- assert(clazz);
-
- if (!object) return 0;
-
- clazz = clazz->reify(object);
-
- if (clazz->hashcode) {
- return clazz->hashcode(object);
- } else {
- return (uintptr_t) object;
- }
-}
-
-intptr_t pn_class_compare(const pn_class_t *clazz, void *a, void *b)
-{
- assert(clazz);
-
- if (a == b) return 0;
-
- clazz = clazz->reify(a);
-
- if (a && b && clazz->compare) {
- return clazz->compare(a, b);
- } else {
- return (intptr_t) a - (intptr_t) b;
- }
-}
-
-bool pn_class_equals(const pn_class_t *clazz, void *a, void *b)
-{
- return pn_class_compare(clazz, a, b) == 0;
-}
-
-int pn_class_inspect(const pn_class_t *clazz, void *object, pn_string_t *dst)
-{
- assert(clazz);
-
- clazz = clazz->reify(object);
-
- if (!pn_string_get(dst)) {
- pn_string_set(dst, "");
- }
-
- if (object && clazz->inspect) {
- return clazz->inspect(object, dst);
- }
-
- const char *name = clazz->name ? clazz->name : "<anon>";
-
- return pn_string_addf(dst, "%s<%p>", name, object);
-}
-
-typedef struct {
- const pn_class_t *clazz;
- int refcount;
-} pni_head_t;
-
-#define pni_head(PTR) \
- (((pni_head_t *) (PTR)) - 1)
-
-void *pn_object_new(const pn_class_t *clazz, size_t size)
-{
- void *object = NULL;
- pni_head_t *head = (pni_head_t *) malloc(sizeof(pni_head_t) + size);
- if (head != NULL) {
- object = head + 1;
- head->clazz = clazz;
- head->refcount = 1;
- }
- return object;
-}
-
-const pn_class_t *pn_object_reify(void *object)
-{
- if (object) {
- return pni_head(object)->clazz;
- } else {
- return PN_OBJECT;
- }
-}
-
-void pn_object_incref(void *object)
-{
- if (object) {
- pni_head(object)->refcount++;
- }
-}
-
-int pn_object_refcount(void *object)
-{
- assert(object);
- return pni_head(object)->refcount;
-}
-
-void pn_object_decref(void *object)
-{
- pni_head_t *head = pni_head(object);
- assert(head->refcount > 0);
- head->refcount--;
-}
-
-void pn_object_free(void *object)
-{
- pni_head_t *head = pni_head(object);
- free(head);
-}
-
-void *pn_incref(void *object)
-{
- return pn_class_incref(PN_OBJECT, object);
-}
-
-int pn_decref(void *object)
-{
- return pn_class_decref(PN_OBJECT, object);
-}
-
-int pn_refcount(void *object)
-{
- return pn_class_refcount(PN_OBJECT, object);
-}
-
-void pn_free(void *object)
-{
- pn_class_free(PN_OBJECT, object);
-}
-
-const pn_class_t *pn_class(void *object)
-{
- return pn_class_reify(PN_OBJECT, object);
-}
-
-uintptr_t pn_hashcode(void *object)
-{
- return pn_class_hashcode(PN_OBJECT, object);
-}
-
-intptr_t pn_compare(void *a, void *b)
-{
- return pn_class_compare(PN_OBJECT, a, b);
-}
-
-bool pn_equals(void *a, void *b)
-{
- return !pn_compare(a, b);
-}
-
-int pn_inspect(void *object, pn_string_t *dst)
-{
- return pn_class_inspect(PN_OBJECT, object, dst);
-}
-
-#define pn_weakref_new NULL
-#define pn_weakref_initialize NULL
-#define pn_weakref_finalize NULL
-#define pn_weakref_free NULL
-
-static void pn_weakref_incref(void *object) {}
-static void pn_weakref_decref(void *object) {}
-static int pn_weakref_refcount(void *object) { return -1; }
-static const pn_class_t *pn_weakref_reify(void *object) {
- return PN_WEAKREF;
-}
-static uintptr_t pn_weakref_hashcode(void *object) {
- return pn_hashcode(object);
-}
-static intptr_t pn_weakref_compare(void *a, void *b) {
- return pn_compare(a, b);
-}
-static int pn_weakref_inspect(void *object, pn_string_t *dst) {
- return pn_inspect(object, dst);
-}
-
-const pn_class_t PN_WEAKREF[] = {PN_METACLASS(pn_weakref)};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/record.c
----------------------------------------------------------------------
diff --git a/proton-c/src/object/record.c b/proton-c/src/object/record.c
deleted file mode 100644
index 6f4fe0a..0000000
--- a/proton-c/src/object/record.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *
- * 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 <proton/object.h>
-#include <stdlib.h>
-#include <assert.h>
-
-typedef struct {
- pn_handle_t key;
- const pn_class_t *clazz;
- void *value;
-} pni_field_t;
-
-struct pn_record_t {
- size_t size;
- size_t capacity;
- pni_field_t *fields;
-};
-
-static void pn_record_initialize(void *object)
-{
- pn_record_t *record = (pn_record_t *) object;
- record->size = 0;
- record->capacity = 0;
- record->fields = NULL;
-}
-
-static void pn_record_finalize(void *object)
-{
- pn_record_t *record = (pn_record_t *) object;
- for (size_t i = 0; i < record->size; i++) {
- pni_field_t *v = &record->fields[i];
- pn_class_decref(v->clazz, v->value);
- }
- free(record->fields);
-}
-
-#define pn_record_hashcode NULL
-#define pn_record_compare NULL
-#define pn_record_inspect NULL
-
-pn_record_t *pn_record(void)
-{
- static const pn_class_t clazz = PN_CLASS(pn_record);
- pn_record_t *record = (pn_record_t *) pn_class_new(&clazz, sizeof(pn_record_t));
- pn_record_def(record, PN_LEGCTX, PN_VOID);
- return record;
-}
-
-static pni_field_t *pni_record_find(pn_record_t *record, pn_handle_t key) {
- for (size_t i = 0; i < record->size; i++) {
- pni_field_t *field = &record->fields[i];
- if (field->key == key) {
- return field;
- }
- }
- return NULL;
-}
-
-static pni_field_t *pni_record_create(pn_record_t *record) {
- record->size++;
- if (record->size > record->capacity) {
- record->fields = (pni_field_t *) realloc(record->fields, record->size * sizeof(pni_field_t));
- record->capacity = record->size;
- }
- pni_field_t *field = &record->fields[record->size - 1];
- field->key = 0;
- field->clazz = NULL;
- field->value = NULL;
- return field;
-}
-
-void pn_record_def(pn_record_t *record, pn_handle_t key, const pn_class_t *clazz)
-{
- assert(record);
- assert(clazz);
-
- pni_field_t *field = pni_record_find(record, key);
- if (field) {
- assert(field->clazz == clazz);
- } else {
- field = pni_record_create(record);
- field->key = key;
- field->clazz = clazz;
- }
-}
-
-bool pn_record_has(pn_record_t *record, pn_handle_t key)
-{
- assert(record);
- pni_field_t *field = pni_record_find(record, key);
- if (field) {
- return true;
- } else {
- return false;
- }
-}
-
-void *pn_record_get(pn_record_t *record, pn_handle_t key)
-{
- assert(record);
- pni_field_t *field = pni_record_find(record, key);
- if (field) {
- return field->value;
- } else {
- return NULL;
- }
-}
-
-void pn_record_set(pn_record_t *record, pn_handle_t key, void *value)
-{
- assert(record);
-
- pni_field_t *field = pni_record_find(record, key);
- if (field) {
- void *old = field->value;
- field->value = value;
- pn_class_incref(field->clazz, value);
- pn_class_decref(field->clazz, old);
- }
-}
-
-void pn_record_clear(pn_record_t *record)
-{
- assert(record);
- for (size_t i = 0; i < record->size; i++) {
- pni_field_t *field = &record->fields[i];
- pn_class_decref(field->clazz, field->value);
- field->key = 0;
- field->clazz = NULL;
- field->value = NULL;
- }
- record->size = 0;
- pn_record_def(record, PN_LEGCTX, PN_VOID);
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/object/string.c
----------------------------------------------------------------------
diff --git a/proton-c/src/object/string.c b/proton-c/src/object/string.c
deleted file mode 100644
index 7b900ca..0000000
--- a/proton-c/src/object/string.c
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- *
- * 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 "platform.h"
-
-#include <proton/error.h>
-#include <proton/object.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <ctype.h>
-
-#define PNI_NULL_SIZE (-1)
-
-struct pn_string_t {
- char *bytes;
- ssize_t size; // PNI_NULL_SIZE (-1) means null
- size_t capacity;
-};
-
-static void pn_string_finalize(void *object)
-{
- pn_string_t *string = (pn_string_t *) object;
- free(string->bytes);
-}
-
-static uintptr_t pn_string_hashcode(void *object)
-{
- pn_string_t *string = (pn_string_t *) object;
- if (string->size == PNI_NULL_SIZE) {
- return 0;
- }
-
- uintptr_t hashcode = 1;
- for (ssize_t i = 0; i < string->size; i++) {
- hashcode = hashcode * 31 + string->bytes[i];
- }
- return hashcode;
-}
-
-static intptr_t pn_string_compare(void *oa, void *ob)
-{
- pn_string_t *a = (pn_string_t *) oa;
- pn_string_t *b = (pn_string_t *) ob;
- if (a->size != b->size) {
- return b->size - a->size;
- }
-
- if (a->size == PNI_NULL_SIZE) {
- return 0;
- } else {
- return memcmp(a->bytes, b->bytes, a->size);
- }
-}
-
-static int pn_string_inspect(void *obj, pn_string_t *dst)
-{
- pn_string_t *str = (pn_string_t *) obj;
- if (str->size == PNI_NULL_SIZE) {
- return pn_string_addf(dst, "null");
- }
-
- int err = pn_string_addf(dst, "\"");
-
- for (int i = 0; i < str->size; i++) {
- uint8_t c = str->bytes[i];
- if (isprint(c)) {
- err = pn_string_addf(dst, "%c", c);
- if (err) return err;
- } else {
- err = pn_string_addf(dst, "\\x%.2x", c);
- if (err) return err;
- }
- }
-
- return pn_string_addf(dst, "\"");
-}
-
-pn_string_t *pn_string(const char *bytes)
-{
- return pn_stringn(bytes, bytes ? strlen(bytes) : 0);
-}
-
-#define pn_string_initialize NULL
-
-
-pn_string_t *pn_stringn(const char *bytes, size_t n)
-{
- static const pn_class_t clazz = PN_CLASS(pn_string);
- pn_string_t *string = (pn_string_t *) pn_class_new(&clazz, sizeof(pn_string_t));
- string->capacity = n ? n * sizeof(char) : 16;
- string->bytes = (char *) malloc(string->capacity);
- pn_string_setn(string, bytes, n);
- return string;
-}
-
-const char *pn_string_get(pn_string_t *string)
-{
- assert(string);
- if (string->size == PNI_NULL_SIZE) {
- return NULL;
- } else {
- return string->bytes;
- }
-}
-
-size_t pn_string_size(pn_string_t *string)
-{
- assert(string);
- if (string->size == PNI_NULL_SIZE) {
- return 0;
- } else {
- return string->size;
- }
-}
-
-int pn_string_set(pn_string_t *string, const char *bytes)
-{
- return pn_string_setn(string, bytes, bytes ? strlen(bytes) : 0);
-}
-
-int pn_string_grow(pn_string_t *string, size_t capacity)
-{
- bool grow = false;
- while (string->capacity < (capacity*sizeof(char) + 1)) {
- string->capacity *= 2;
- grow = true;
- }
-
- if (grow) {
- char *growed = (char *) realloc(string->bytes, string->capacity);
- if (growed) {
- string->bytes = growed;
- } else {
- return PN_ERR;
- }
- }
-
- return 0;
-}
-
-int pn_string_setn(pn_string_t *string, const char *bytes, size_t n)
-{
- int err = pn_string_grow(string, n);
- if (err) return err;
-
- if (bytes) {
- memcpy(string->bytes, bytes, n*sizeof(char));
- string->bytes[n] = '\0';
- string->size = n;
- } else {
- string->size = PNI_NULL_SIZE;
- }
-
- return 0;
-}
-
-ssize_t pn_string_put(pn_string_t *string, char *dst)
-{
- assert(string);
- assert(dst);
-
- if (string->size != PNI_NULL_SIZE) {
- memcpy(dst, string->bytes, string->size + 1);
- }
-
- return string->size;
-}
-
-void pn_string_clear(pn_string_t *string)
-{
- pn_string_set(string, NULL);
-}
-
-int pn_string_format(pn_string_t *string, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- int err = pn_string_vformat(string, format, ap);
- va_end(ap);
- return err;
-}
-
-int pn_string_vformat(pn_string_t *string, const char *format, va_list ap)
-{
- pn_string_set(string, "");
- return pn_string_vaddf(string, format, ap);
-}
-
-int pn_string_addf(pn_string_t *string, const char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- int err = pn_string_vaddf(string, format, ap);
- va_end(ap);
- return err;
-}
-
-int pn_string_vaddf(pn_string_t *string, const char *format, va_list ap)
-{
- va_list copy;
-
- if (string->size == PNI_NULL_SIZE) {
- return PN_ERR;
- }
-
- while (true) {
- va_copy(copy, ap);
- int err = vsnprintf(string->bytes + string->size, string->capacity - string->size, format, copy);
- va_end(copy);
- if (err < 0) {
- return err;
- } else if ((size_t) err >= string->capacity - string->size) {
- pn_string_grow(string, string->size + err);
- } else {
- string->size += err;
- return 0;
- }
- }
-}
-
-char *pn_string_buffer(pn_string_t *string)
-{
- assert(string);
- return string->bytes;
-}
-
-size_t pn_string_capacity(pn_string_t *string)
-{
- assert(string);
- return string->capacity - 1;
-}
-
-int pn_string_resize(pn_string_t *string, size_t size)
-{
- assert(string);
- int err = pn_string_grow(string, size);
- if (err) return err;
- string->size = size;
- string->bytes[size] = '\0';
- return 0;
-}
-
-int pn_string_copy(pn_string_t *string, pn_string_t *src)
-{
- assert(string);
- return pn_string_setn(string, pn_string_get(src), pn_string_size(src));
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/parser.c
----------------------------------------------------------------------
diff --git a/proton-c/src/parser.c b/proton-c/src/parser.c
deleted file mode 100644
index 87cb758..0000000
--- a/proton-c/src/parser.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- *
- * 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 <proton/parser.h>
-#include <proton/scanner.h>
-#include <proton/error.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include "platform.h"
-
-struct pn_parser_t {
- pn_scanner_t *scanner;
- char *atoms;
- size_t size;
- size_t capacity;
- int error_code;
-};
-
-pn_parser_t *pn_parser()
-{
- pn_parser_t *parser = (pn_parser_t *) malloc(sizeof(pn_parser_t));
- if (parser != NULL) {
- parser->scanner = pn_scanner();
- parser->atoms = NULL;
- parser->size = 0;
- parser->capacity = 0;
- }
- return parser;
-}
-
-static void pni_parser_ensure(pn_parser_t *parser, size_t size)
-{
- while (parser->capacity - parser->size < size) {
- parser->capacity = parser->capacity ? 2 * parser->capacity : 1024;
- parser->atoms = (char *) realloc(parser->atoms, parser->capacity);
- }
-}
-
-int pn_parser_err(pn_parser_t *parser, int code, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- int err = pn_scanner_verr(parser->scanner, code, fmt, ap);
- va_end(ap);
- return err;
-}
-
-int pn_parser_errno(pn_parser_t *parser)
-{
- return pn_scanner_errno(parser->scanner);
-}
-
-const char *pn_parser_error(pn_parser_t *parser)
-{
- return pn_scanner_error(parser->scanner);
-}
-
-void pn_parser_free(pn_parser_t *parser)
-{
- if (parser) {
- pn_scanner_free(parser->scanner);
- free(parser->atoms);
- free(parser);
- }
-}
-
-static int pni_parser_shift(pn_parser_t *parser)
-{
- return pn_scanner_shift(parser->scanner);
-}
-
-static pn_token_t pni_parser_token(pn_parser_t *parser)
-{
- return pn_scanner_token(parser->scanner);
-}
-
-static int pni_parser_value(pn_parser_t *parser, pn_data_t *data);
-
-static int pni_parser_descriptor(pn_parser_t *parser, pn_data_t *data)
-{
- if (pni_parser_token(parser).type == PN_TOK_AT) {
- int err = pni_parser_shift(parser);
- if (err) return err;
-
- err = pn_data_put_described(data);
- if (err) return pn_parser_err(parser, err, "error writing described");
- pn_data_enter(data);
- for (int i = 0; i < 2; i++) {
- err = pni_parser_value(parser, data);
- if (err) return err;
- }
- pn_data_exit(data);
- return 0;
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting '@'");
- }
-}
-
-static int pni_parser_map(pn_parser_t *parser, pn_data_t *data)
-{
- if (pni_parser_token(parser).type == PN_TOK_LBRACE) {
- int err = pni_parser_shift(parser);
- if (err) return err;
-
- err = pn_data_put_map(data);
- if (err) return pn_parser_err(parser, err, "error writing map");
-
- pn_data_enter(data);
-
- if (pni_parser_token(parser).type != PN_TOK_RBRACE) {
- while (true) {
- err = pni_parser_value(parser, data);
- if (err) return err;
-
- if (pni_parser_token(parser).type == PN_TOK_EQUAL) {
- err = pni_parser_shift(parser);
- if (err) return err;
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting '='");
- }
-
- err = pni_parser_value(parser, data);
- if (err) return err;
-
- if (pni_parser_token(parser).type == PN_TOK_COMMA) {
- err = pni_parser_shift(parser);
- if (err) return err;
- } else {
- break;
- }
- }
- }
-
- pn_data_exit(data);
-
- if (pni_parser_token(parser).type == PN_TOK_RBRACE) {
- return pni_parser_shift(parser);
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting '}'");
- }
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting '{'");
- }
-}
-
-static int pni_parser_list(pn_parser_t *parser, pn_data_t *data)
-{
- int err;
-
- if (pni_parser_token(parser).type == PN_TOK_LBRACKET) {
- err = pni_parser_shift(parser);
- if (err) return err;
-
- err = pn_data_put_list(data);
- if (err) return pn_parser_err(parser, err, "error writing list");
-
- pn_data_enter(data);
-
- if (pni_parser_token(parser).type != PN_TOK_RBRACKET) {
- while (true) {
- err = pni_parser_value(parser, data);
- if (err) return err;
-
- if (pni_parser_token(parser).type == PN_TOK_COMMA) {
- err = pni_parser_shift(parser);
- if (err) return err;
- } else {
- break;
- }
- }
- }
-
- pn_data_exit(data);
-
- if (pni_parser_token(parser).type == PN_TOK_RBRACKET) {
- return pni_parser_shift(parser);
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting ']'");
- }
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting '['");
- }
-}
-
-static void pni_parser_append_tok(pn_parser_t *parser, char *dst, int *idx)
-{
- memcpy(dst + *idx, pni_parser_token(parser).start, pni_parser_token(parser).size);
- *idx += pni_parser_token(parser).size;
-}
-
-static int pni_parser_number(pn_parser_t *parser, pn_data_t *data)
-{
- bool dbl = false;
- char number[1024];
- int idx = 0;
- int err;
-
- bool negate = false;
-
- if (pni_parser_token(parser).type == PN_TOK_NEG || pni_parser_token(parser).type == PN_TOK_POS) {
- if (pni_parser_token(parser).type == PN_TOK_NEG)
- negate = !negate;
- err = pni_parser_shift(parser);
- if (err) return err;
- }
-
- if (pni_parser_token(parser).type == PN_TOK_FLOAT || pni_parser_token(parser).type == PN_TOK_INT) {
- dbl = pni_parser_token(parser).type == PN_TOK_FLOAT;
- pni_parser_append_tok(parser, number, &idx);
- err = pni_parser_shift(parser);
- if (err) return err;
- } else {
- return pn_parser_err(parser, PN_ERR, "expecting FLOAT or INT");
- }
-
- number[idx] = '\0';
-
- if (dbl) {
- double value = atof(number);
- if (negate) {
- value = -value;
- }
- err = pn_data_put_double(data, value);
- if (err) return pn_parser_err(parser, err, "error writing double");
- } else {
- int64_t value = pn_i_atoll(number);
- if (negate) {
- value = -value;
- }
- err = pn_data_put_long(data, value);
- if (err) return pn_parser_err(parser, err, "error writing long");
- }
-
- return 0;
-}
-
-static int pni_parser_unquote(pn_parser_t *parser, char *dst, const char *src, size_t *n)
-{
- size_t idx = 0;
- bool escape = false;
- int start, end;
- if (src[0] != '"') {
- if (src[1] == '"') {
- start = 2;
- end = *n - 1;
- } else {
- start = 1;
- end = *n;
- }
- } else {
- start = 1;
- end = *n - 1;
- }
- for (int i = start; i < end; i++)
- {
- char c = src[i];
- if (escape) {
- switch (c) {
- case '"':
- case '\\':
- case '/':
- dst[idx++] = c;
- escape = false;
- break;
- case 'b':
- dst[idx++] = '\b';
- break;
- case 'f':
- dst[idx++] = '\f';
- break;
- case 'n':
- dst[idx++] = '\n';
- break;
- case 'r':
- dst[idx++] = '\r';
- break;
- case 't':
- dst[idx++] = '\t';
- break;
- case 'x':
- {
- char n1 = toupper(src[i+1]);
- char n2 = n1 ? toupper(src[i+2]) : 0;
- if (!n2) {
- return pn_parser_err(parser, PN_ERR, "truncated escape code");
- }
- int d1 = isdigit(n1) ? n1 - '0' : n1 - 'A' + 10;
- int d2 = isdigit(n2) ? n2 - '0' : n2 - 'A' + 10;
- dst[idx++] = d1*16 + d2;
- i += 2;
- }
- break;
- // XXX: need to handle unicode escapes: 'u'
- default:
- return pn_parser_err(parser, PN_ERR, "unrecognized escape code");
- }
- escape = false;
- } else {
- switch (c)
- {
- case '\\':
- escape = true;
- break;
- default:
- dst[idx++] = c;
- break;
- }
- }
- }
- dst[idx++] = '\0';
- *n = idx;
- return 0;
-}
-
-static int pni_parser_value(pn_parser_t *parser, pn_data_t *data)
-{
- int err;
- size_t n;
- char *dst;
-
- pn_token_t tok = pni_parser_token(parser);
-
- switch (tok.type)
- {
- case PN_TOK_AT:
- return pni_parser_descriptor(parser, data);
- case PN_TOK_LBRACE:
- return pni_parser_map(parser, data);
- case PN_TOK_LBRACKET:
- return pni_parser_list(parser, data);
- case PN_TOK_BINARY:
- case PN_TOK_SYMBOL:
- case PN_TOK_STRING:
- n = tok.size;
- pni_parser_ensure(parser, n);
- dst = parser->atoms + parser->size;
- err = pni_parser_unquote(parser, dst, tok.start, &n);
- if (err) return err;
- parser->size += n;
- switch (tok.type) {
- case PN_TOK_BINARY:
- err = pn_data_put_binary(data, pn_bytes(n - 1, dst));
- break;
- case PN_TOK_STRING:
- err = pn_data_put_string(data, pn_bytes(n - 1, dst));
- break;
- case PN_TOK_SYMBOL:
- err = pn_data_put_symbol(data, pn_bytes(n - 1, dst));
- break;
- default:
- return pn_parser_err(parser, PN_ERR, "internal error");
- }
- if (err) return pn_parser_err(parser, err, "error writing string/binary/symbol");
- return pni_parser_shift(parser);
- case PN_TOK_POS:
- case PN_TOK_NEG:
- case PN_TOK_FLOAT:
- case PN_TOK_INT:
- return pni_parser_number(parser, data);
- case PN_TOK_TRUE:
- err = pn_data_put_bool(data, true);
- if (err) return pn_parser_err(parser, err, "error writing boolean");
- return pni_parser_shift(parser);
- case PN_TOK_FALSE:
- err = pn_data_put_bool(data, false);
- if (err) return pn_parser_err(parser, err, "error writing boolean");
- return pni_parser_shift(parser);
- case PN_TOK_NULL:
- err = pn_data_put_null(data);
- if (err) return pn_parser_err(parser, err, "error writing null");
- return pni_parser_shift(parser);
- default:
- return pn_parser_err(parser, PN_ERR, "expecting one of '[', '{', STRING, "
- "SYMBOL, BINARY, true, false, null, NUMBER");
- }
-}
-
-static int pni_parser_parse_r(pn_parser_t *parser, pn_data_t *data)
-{
- while (true) {
- int err;
- switch (pni_parser_token(parser).type)
- {
- case PN_TOK_EOS:
- return 0;
- case PN_TOK_ERR:
- return PN_ERR;
- default:
- err = pni_parser_value(parser, data);
- if (err) return err;
- }
- }
-}
-
-int pn_parser_parse(pn_parser_t *parser, const char *str, pn_data_t *data)
-{
- int err = pn_scanner_start(parser->scanner, str);
- if (err) return err;
- parser->size = 0;
- return pni_parser_parse_r(parser, data);
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform.c
----------------------------------------------------------------------
diff --git a/proton-c/src/platform.c b/proton-c/src/platform.c
deleted file mode 100644
index 3a8cade..0000000
--- a/proton-c/src/platform.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * 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 "platform.h"
-#include "util.h"
-
-#ifdef PN_WINAPI
-#include <windows.h>
-int pn_i_getpid() {
- return (int) GetCurrentProcessId();
-}
-#else
-#include <unistd.h>
-int pn_i_getpid() {
- return (int) getpid();
-}
-#endif
-
-/* Allow for systems that do not implement clock_gettime()*/
-#ifdef USE_CLOCK_GETTIME
-#include <time.h>
-pn_timestamp_t pn_i_now(void)
-{
- struct timespec now;
- if (clock_gettime(CLOCK_REALTIME, &now)) pni_fatal("clock_gettime() failed\n");
- return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_nsec / 1000000);
-}
-#elif defined(USE_WIN_FILETIME)
-#include <windows.h>
-pn_timestamp_t pn_i_now(void)
-{
- FILETIME now;
- GetSystemTimeAsFileTime(&now);
- ULARGE_INTEGER t;
- t.u.HighPart = now.dwHighDateTime;
- t.u.LowPart = now.dwLowDateTime;
- // Convert to milliseconds and adjust base epoch
- return t.QuadPart / 10000 - 11644473600000;
-}
-#else
-#include <sys/time.h>
-pn_timestamp_t pn_i_now(void)
-{
- struct timeval now;
- if (gettimeofday(&now, NULL)) pni_fatal("gettimeofday failed\n");
- return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000);
-}
-#endif
-
-#include <string.h>
-#include <stdio.h>
-static void pn_i_strerror(int errnum, char *buf, size_t buflen)
-{
- // PROTON-1029 provide a simple default in case strerror fails
- snprintf(buf, buflen, "errno: %d", errnum);
-#ifdef USE_STRERROR_R
- strerror_r(errnum, buf, buflen);
-#elif USE_STRERROR_S
- strerror_s(buf, buflen, errnum);
-#elif USE_OLD_STRERROR
- strncpy(buf, strerror(errnum), buflen);
-#endif
-}
-
-int pn_i_error_from_errno(pn_error_t *error, const char *msg)
-{
- char err[1024];
- pn_i_strerror(errno, err, 1024);
- int code = PN_ERR;
- if (errno == EINTR)
- code = PN_INTR;
- return pn_error_format(error, code, "%s: %s", msg, err);
-}
-
-#ifdef USE_ATOLL
-#include <stdlib.h>
-int64_t pn_i_atoll(const char* num) {
- return atoll(num);
-}
-#elif USE_ATOI64
-#include <stdlib.h>
-int64_t pn_i_atoll(const char* num) {
- return _atoi64(num);
-}
-#else
-#error "Don't know how to convert int64_t values on this platform"
-#endif
-
-#ifdef _MSC_VER
-// [v]snprintf on Windows only matches C99 when no errors or overflow.
-int pn_i_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap) {
- if (fmt == NULL)
- return -1;
- if ((buf == NULL) && (count > 0))
- return -1;
- if (count > 0) {
- int n = vsnprintf_s(buf, count, _TRUNCATE, fmt, ap);
- if (n >= 0) // no overflow
- return n; // same as C99
- buf[count-1] = '\0';
- }
- // separate call to get needed buffer size on overflow
- int n = _vscprintf(fmt, ap);
- if (n >= (int) count)
- return n;
- return -1;
-}
-
-int pn_i_snprintf(char *buf, size_t count, const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- int n = pn_i_vsnprintf(buf, count, fmt, ap);
- va_end(ap);
- return n;
-}
-#endif
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform.h
----------------------------------------------------------------------
diff --git a/proton-c/src/platform.h b/proton-c/src/platform.h
deleted file mode 100644
index 6a0bbc1..0000000
--- a/proton-c/src/platform.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef PROTON_PLATFORM_H
-#define PROTON_PLATFORM_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 "proton/types.h"
-#include "proton/error.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Get the current PID
- *
- * @return process id
- * @internal
- */
-int pn_i_getpid(void);
-
-
-/** Get the current time in pn_timestamp_t format.
- *
- * Returns current time in milliseconds since Unix Epoch,
- * as defined by AMQP 1.0
- *
- * @return current time
- * @internal
- */
-pn_timestamp_t pn_i_now(void);
-
-/** Generate system error message.
- *
- * Populate the proton error structure based on the last system error
- * code.
- *
- * @param[in] error the proton error structure
- * @param[in] msg the descriptive context message
- * @return error->code
- *
- * @internal
- */
-int pn_i_error_from_errno(pn_error_t *error, const char *msg);
-
-/** Provide C99 atoll functinality.
- *
- * @param[in] num the string representation of the number.
- * @return the integer value.
- *
- * @internal
- */
-int64_t pn_i_atoll(const char* num);
-
-#ifdef _MSC_VER
-/** Windows snprintf and vsnprintf substitutes.
- *
- * Provide the expected C99 behavior for these functions.
- */
-#include <stdio.h>
-
-#define snprintf pn_i_snprintf
-#define vsnprintf pn_i_vsnprintf
-
-int pn_i_snprintf(char *buf, size_t count, const char *fmt, ...);
-int pn_i_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap);
-
-#if !defined(S_ISDIR)
-# define S_ISDIR(X) ((X) & _S_IFDIR)
-#endif
-
-#endif
-
-#if defined _MSC_VER || defined _OPENVMS
-#if !defined(va_copy)
-#define va_copy(d,s) ((d) = (s))
-#endif
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* platform.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform/platform.c
----------------------------------------------------------------------
diff --git a/proton-c/src/platform/platform.c b/proton-c/src/platform/platform.c
new file mode 100644
index 0000000..393f75c
--- /dev/null
+++ b/proton-c/src/platform/platform.c
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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 "platform.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef PN_WINAPI
+#include <windows.h>
+int pn_i_getpid() {
+ return (int) GetCurrentProcessId();
+}
+#else
+#include <unistd.h>
+int pn_i_getpid() {
+ return (int) getpid();
+}
+#endif
+
+void pni_vfatal(const char *fmt, va_list ap)
+{
+ vfprintf(stderr, fmt, ap);
+ abort();
+}
+
+void pni_fatal(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ pni_vfatal(fmt, ap);
+ va_end(ap);
+}
+
+/* Allow for systems that do not implement clock_gettime()*/
+#ifdef USE_CLOCK_GETTIME
+#include <time.h>
+pn_timestamp_t pn_i_now(void)
+{
+ struct timespec now;
+ if (clock_gettime(CLOCK_REALTIME, &now)) pni_fatal("clock_gettime() failed\n");
+ return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_nsec / 1000000);
+}
+#elif defined(USE_WIN_FILETIME)
+#include <windows.h>
+pn_timestamp_t pn_i_now(void)
+{
+ FILETIME now;
+ GetSystemTimeAsFileTime(&now);
+ ULARGE_INTEGER t;
+ t.u.HighPart = now.dwHighDateTime;
+ t.u.LowPart = now.dwLowDateTime;
+ // Convert to milliseconds and adjust base epoch
+ return t.QuadPart / 10000 - 11644473600000;
+}
+#else
+#include <sys/time.h>
+pn_timestamp_t pn_i_now(void)
+{
+ struct timeval now;
+ if (gettimeofday(&now, NULL)) pni_fatal("gettimeofday failed\n");
+ return ((pn_timestamp_t)now.tv_sec) * 1000 + (now.tv_usec / 1000);
+}
+#endif
+
+#include <string.h>
+#include <stdio.h>
+static void pn_i_strerror(int errnum, char *buf, size_t buflen)
+{
+ // PROTON-1029 provide a simple default in case strerror fails
+ pni_snprintf(buf, buflen, "errno: %d", errnum);
+#ifdef USE_STRERROR_R
+ strerror_r(errnum, buf, buflen);
+#elif USE_STRERROR_S
+ strerror_s(buf, buflen, errnum);
+#elif USE_OLD_STRERROR
+ strncpy(buf, strerror(errnum), buflen);
+#endif
+}
+
+int pn_i_error_from_errno(pn_error_t *error, const char *msg)
+{
+ char err[1024];
+ pn_i_strerror(errno, err, 1024);
+ int code = PN_ERR;
+ if (errno == EINTR)
+ code = PN_INTR;
+ return pn_error_format(error, code, "%s: %s", msg, err);
+}
+
+#ifdef USE_ATOLL
+#include <stdlib.h>
+int64_t pn_i_atoll(const char* num) {
+ return atoll(num);
+}
+#elif USE_ATOI64
+#include <stdlib.h>
+int64_t pn_i_atoll(const char* num) {
+ return _atoi64(num);
+}
+#else
+#error "Don't know how to convert int64_t values on this platform"
+#endif
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform/platform.h
----------------------------------------------------------------------
diff --git a/proton-c/src/platform/platform.h b/proton-c/src/platform/platform.h
new file mode 100644
index 0000000..d846cda
--- /dev/null
+++ b/proton-c/src/platform/platform.h
@@ -0,0 +1,93 @@
+#ifndef PROTON_PLATFORM_H
+#define PROTON_PLATFORM_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 "proton/types.h"
+#include "proton/error.h"
+
+/** Get the current PID
+ *
+ * @return process id
+ * @internal
+ */
+int pn_i_getpid(void);
+
+
+/** Get the current time in pn_timestamp_t format.
+ *
+ * Returns current time in milliseconds since Unix Epoch,
+ * as defined by AMQP 1.0
+ *
+ * @return current time
+ * @internal
+ */
+pn_timestamp_t pn_i_now(void);
+
+/** Generate system error message.
+ *
+ * Populate the proton error structure based on the last system error
+ * code.
+ *
+ * @param[in] error the proton error structure
+ * @param[in] msg the descriptive context message
+ * @return error->code
+ *
+ * @internal
+ */
+int pn_i_error_from_errno(pn_error_t *error, const char *msg);
+
+/** Provide C99 atoll functinality.
+ *
+ * @param[in] num the string representation of the number.
+ * @return the integer value.
+ *
+ * @internal
+ */
+int64_t pn_i_atoll(const char* num);
+
+int pni_snprintf(char *buf, size_t count, const char *fmt, ...);
+int pni_vsnprintf(char *buf, size_t count, const char *fmt, va_list ap);
+
+#ifndef _MSC_VER
+
+#define pni_snprintf snprintf
+#define pni_vsnprintf vsnprintf
+
+#else
+
+#if !defined(S_ISDIR)
+# define S_ISDIR(X) ((X) & _S_IFDIR)
+#endif
+
+#endif
+
+#if defined _MSC_VER || defined _OPENVMS
+#if !defined(va_copy)
+#define va_copy(d,s) ((d) = (s))
+#endif
+#endif
+
+// Low level pretty rubbish URL parser
+void pni_parse_url(char *url, char **scheme, char **user, char **pass, char **host, char **port, char **path);
+
+#endif /* platform.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform/platform_fmt.h
----------------------------------------------------------------------
diff --git a/proton-c/src/platform/platform_fmt.h b/proton-c/src/platform/platform_fmt.h
new file mode 100644
index 0000000..17f95f3
--- /dev/null
+++ b/proton-c/src/platform/platform_fmt.h
@@ -0,0 +1,85 @@
+#ifndef _PROTON_SRC_PLATFORM_FMT_H
+#define _PROTON_SRC_PLATFORM_FMT_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.
+ *
+ */
+
+/*
+ * Platform dependent type-specific format specifiers for PRIx and %z
+ * for use with printf. PRIx defs are normally available in
+ * inttypes.h (C99), but extra steps are required for C++, and they
+ * are not available in Visual Studio at all.
+ * Visual studio uses "%I" for size_t instead of "%z".
+ */
+
+#ifndef __cplusplus
+
+// normal case
+#include <inttypes.h>
+#define PN_ZI "zi"
+#define PN_ZU "zu"
+
+#ifdef _OPENVMS
+
+#undef PN_ZI
+#undef PN_ZU
+#define PN_ZI "i"
+#define PN_ZU "u"
+#define PRIu64 "llu"
+#define PRIu8 "u"
+#define PRIu16 "u"
+#define PRIu32 "u"
+#define PRIu64 "llu"
+
+#define PRIi8 "i"
+#define PRIi16 "i"
+#define PRIi32 "i"
+#define PRIi64 "lli"
+
+#endif /* _OPENVMS */
+
+#else
+
+#ifdef _MSC_VER
+#define PRIu8 "u"
+#define PRIu16 "u"
+#define PRIu32 "u"
+#define PRIu64 "I64u"
+
+#define PRIi8 "i"
+#define PRIi16 "i"
+#define PRIi32 "i"
+#define PRIi64 "I64i"
+
+#define PN_ZI "Ii"
+#define PN_ZU "Iu"
+#else
+// Normal C++
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#define PN_ZI "zi"
+#define PN_ZU "zu"
+
+#endif /* _MSC_VER */
+
+#endif /* __cplusplus */
+
+#endif /* platform_fmt.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/platform_fmt.h
----------------------------------------------------------------------
diff --git a/proton-c/src/platform_fmt.h b/proton-c/src/platform_fmt.h
deleted file mode 100644
index 17f95f3..0000000
--- a/proton-c/src/platform_fmt.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef _PROTON_SRC_PLATFORM_FMT_H
-#define _PROTON_SRC_PLATFORM_FMT_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.
- *
- */
-
-/*
- * Platform dependent type-specific format specifiers for PRIx and %z
- * for use with printf. PRIx defs are normally available in
- * inttypes.h (C99), but extra steps are required for C++, and they
- * are not available in Visual Studio at all.
- * Visual studio uses "%I" for size_t instead of "%z".
- */
-
-#ifndef __cplusplus
-
-// normal case
-#include <inttypes.h>
-#define PN_ZI "zi"
-#define PN_ZU "zu"
-
-#ifdef _OPENVMS
-
-#undef PN_ZI
-#undef PN_ZU
-#define PN_ZI "i"
-#define PN_ZU "u"
-#define PRIu64 "llu"
-#define PRIu8 "u"
-#define PRIu16 "u"
-#define PRIu32 "u"
-#define PRIu64 "llu"
-
-#define PRIi8 "i"
-#define PRIi16 "i"
-#define PRIi32 "i"
-#define PRIi64 "lli"
-
-#endif /* _OPENVMS */
-
-#else
-
-#ifdef _MSC_VER
-#define PRIu8 "u"
-#define PRIu16 "u"
-#define PRIu32 "u"
-#define PRIu64 "I64u"
-
-#define PRIi8 "i"
-#define PRIi16 "i"
-#define PRIi32 "i"
-#define PRIi64 "I64i"
-
-#define PN_ZI "Ii"
-#define PN_ZU "Iu"
-#else
-// Normal C++
-#define __STDC_FORMAT_MACROS
-#include <inttypes.h>
-#define PN_ZI "zi"
-#define PN_ZU "zu"
-
-#endif /* _MSC_VER */
-
-#endif /* __cplusplus */
-
-#endif /* platform_fmt.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/posix/io.c
----------------------------------------------------------------------
diff --git a/proton-c/src/posix/io.c b/proton-c/src/posix/io.c
deleted file mode 100644
index 27d1a35..0000000
--- a/proton-c/src/posix/io.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- *
- * 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 <proton/io.h>
-#include <proton/object.h>
-#include <proton/selector.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <assert.h>
-
-#include "platform.h"
-
-#define MAX_HOST (1024)
-#define MAX_SERV (64)
-
-struct pn_io_t {
- char host[MAX_HOST];
- char serv[MAX_SERV];
- pn_error_t *error;
- pn_selector_t *selector;
- bool wouldblock;
-};
-
-void pn_io_initialize(void *obj)
-{
- pn_io_t *io = (pn_io_t *) obj;
- io->error = pn_error();
- io->wouldblock = false;
- io->selector = NULL;
-}
-
-void pn_io_finalize(void *obj)
-{
- pn_io_t *io = (pn_io_t *) obj;
- pn_error_free(io->error);
-}
-
-#define pn_io_hashcode NULL
-#define pn_io_compare NULL
-#define pn_io_inspect NULL
-
-pn_io_t *pn_io(void)
-{
- static const pn_class_t clazz = PN_CLASS(pn_io);
- pn_io_t *io = (pn_io_t *) pn_class_new(&clazz, sizeof(pn_io_t));
- return io;
-}
-
-void pn_io_free(pn_io_t *io)
-{
- pn_free(io);
-}
-
-pn_error_t *pn_io_error(pn_io_t *io)
-{
- assert(io);
- return io->error;
-}
-
-int pn_pipe(pn_io_t *io, pn_socket_t *dest)
-{
- int n = pipe(dest);
- if (n) {
- pn_i_error_from_errno(io->error, "pipe");
- }
-
- return n;
-}
-
-static void pn_configure_sock(pn_io_t *io, pn_socket_t sock) {
- // this would be nice, but doesn't appear to exist on linux
- /*
- int set = 1;
- if (!setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int))) {
- pn_i_error_from_errno(io->error, "setsockopt");
- };
- */
-
- int flags = fcntl(sock, F_GETFL);
- flags |= O_NONBLOCK;
-
- if (fcntl(sock, F_SETFL, flags) < 0) {
- pn_i_error_from_errno(io->error, "fcntl");
- }
-
- //
- // Disable the Nagle algorithm on TCP connections.
- //
- // Note: It would be more correct for the "level" argument to be SOL_TCP. However, there
- // are portability issues with this macro so we use IPPROTO_TCP instead.
- //
- int tcp_nodelay = 1;
- if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*) &tcp_nodelay, sizeof(tcp_nodelay)) < 0) {
- pn_i_error_from_errno(io->error, "setsockopt");
- }
-}
-
-static inline int pn_create_socket(int af, int protocol);
-
-pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port)
-{
- struct addrinfo *addr;
- struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
- int code = getaddrinfo(host, port, &hints, &addr);
- if (code) {
- pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s\n", host, port, gai_strerror(code));
- return PN_INVALID_SOCKET;
- }
-
- pn_socket_t sock = pn_create_socket(addr->ai_family, addr->ai_protocol);
- if (sock == PN_INVALID_SOCKET) {
- freeaddrinfo(addr);
- pn_i_error_from_errno(io->error, "pn_create_socket");
- return PN_INVALID_SOCKET;
- }
-
- int optval = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
- pn_i_error_from_errno(io->error, "setsockopt");
- freeaddrinfo(addr);
- close(sock);
- return PN_INVALID_SOCKET;
- }
-
- if (bind(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
- pn_i_error_from_errno(io->error, "bind");
- freeaddrinfo(addr);
- close(sock);
- return PN_INVALID_SOCKET;
- }
-
- freeaddrinfo(addr);
-
- if (listen(sock, 50) == -1) {
- pn_i_error_from_errno(io->error, "listen");
- close(sock);
- return PN_INVALID_SOCKET;
- }
-
- return sock;
-}
-
-pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port)
-{
- struct addrinfo *addr;
- struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
- int code = getaddrinfo(host, port, &hints, &addr);
- if (code) {
- pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s", host, port, gai_strerror(code));
- return PN_INVALID_SOCKET;
- }
-
- pn_socket_t sock = pn_create_socket(addr->ai_family, addr->ai_protocol);
- if (sock == PN_INVALID_SOCKET) {
- pn_i_error_from_errno(io->error, "pn_create_socket");
- freeaddrinfo(addr);
- return PN_INVALID_SOCKET;
- }
-
- pn_configure_sock(io, sock);
-
- if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
- if (errno != EINPROGRESS) {
- pn_i_error_from_errno(io->error, "connect");
- freeaddrinfo(addr);
- close(sock);
- return PN_INVALID_SOCKET;
- }
- }
-
- freeaddrinfo(addr);
-
- return sock;
-}
-
-pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size)
-{
- struct sockaddr_storage addr;
- socklen_t addrlen = sizeof(addr);
- *name = '\0';
- pn_socket_t sock = accept(socket, (struct sockaddr *) &addr, &addrlen);
- if (sock == PN_INVALID_SOCKET) {
- pn_i_error_from_errno(io->error, "accept");
- return sock;
- } else {
- int code;
- if ((code = getnameinfo((struct sockaddr *) &addr, addrlen, io->host, MAX_HOST, io->serv, MAX_SERV, 0))) {
- pn_error_format(io->error, PN_ERR, "getnameinfo: %s\n", gai_strerror(code));
- if (close(sock) == -1)
- pn_i_error_from_errno(io->error, "close");
- return PN_INVALID_SOCKET;
- } else {
- pn_configure_sock(io, sock);
- snprintf(name, size, "%s:%s", io->host, io->serv);
- return sock;
- }
- }
-}
-
-/* Abstract away turning off SIGPIPE */
-#ifdef MSG_NOSIGNAL
-ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t len) {
- ssize_t count = send(socket, buf, len, MSG_NOSIGNAL);
- io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
- if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
- return count;
-}
-
-static inline int pn_create_socket(int af, int protocol) {
- return socket(af, SOCK_STREAM, protocol);
-}
-#elif defined(SO_NOSIGPIPE)
-ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size) {
- ssize_t count = send(socket, buf, size, 0);
- io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
- if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
- return count;
-}
-
-static inline int pn_create_socket(int af, int protocol) {
- int sock;
- sock = socket(af, SOCK_STREAM, protocol);
- if (sock == -1) return sock;
-
- int optval = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) == -1) {
- close(sock);
- return -1;
- }
- return sock;
-}
-#else
-
-#include <signal.h>
-
-static inline int pn_create_socket(int af, int protocol) {
- return socket(af, SOCK_STREAM, protocol);
-}
-
-static ssize_t nosigpipe_send(int fd, const void *buffer, size_t size) {
- sigset_t pendingSignals, oldSignals, newSignals;
- ssize_t count;
- int sendErrno, sigmaskErr;
-
- sigpending(&pendingSignals);
- int sigpipeIsPending = sigismember(&pendingSignals, SIGPIPE);
- if (!sigpipeIsPending) {
- sigemptyset(&newSignals);
- sigaddset(&newSignals, SIGPIPE);
- if (sigmaskErr = pthread_sigmask(SIG_BLOCK, (const sigset_t *)&newSignals, (sigset_t *)&oldSignals))
- {
- errno = sigmaskErr;
- return -1;
- }
- }
-
- count = send(fd, buffer, size, 0);
- if (!sigpipeIsPending) {
- sendErrno = errno;
- if (count == -1 && errno == EPIPE) {
- while (-1 == sigtimedwait(&newSignals, NULL, &(struct timespec){ 0, 0 }) && errno == EINTR)
- ; //do nothing
- }
- if (sigmaskErr = pthread_sigmask(SIG_SETMASK, (const sigset_t *)&oldSignals, (sigset_t *)NULL))
- {
- errno = sigmaskErr;
- return -1;
- }
- errno = sendErrno;
- }
- return count;
-}
-
-ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size) {
- ssize_t count = nosigpipe_send(socket, buf, size);
- io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
- if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
- return count;
-}
-#endif
-
-ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size)
-{
- ssize_t count = recv(socket, buf, size, 0);
- io->wouldblock = count < 0 && (errno == EAGAIN || errno == EWOULDBLOCK);
- if (count < 0) { pn_i_error_from_errno(io->error, "recv"); }
- return count;
-}
-
-ssize_t pn_write(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size)
-{
- return write(socket, buf, size);
-}
-
-ssize_t pn_read(pn_io_t *io, pn_socket_t socket, void *buf, size_t size)
-{
- return read(socket, buf, size);
-}
-
-void pn_close(pn_io_t *io, pn_socket_t socket)
-{
- close(socket);
-}
-
-bool pn_wouldblock(pn_io_t *io)
-{
- return io->wouldblock;
-}
-
-pn_selector_t *pn_io_selector(pn_io_t *io)
-{
- if (io->selector == NULL)
- io->selector = pni_selector();
- return io->selector;
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/posix/selector.c
----------------------------------------------------------------------
diff --git a/proton-c/src/posix/selector.c b/proton-c/src/posix/selector.c
deleted file mode 100644
index 7f72c84..0000000
--- a/proton-c/src/posix/selector.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *
- * 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 <proton/selector.h>
-#include <proton/error.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "platform.h"
-#include "selectable.h"
-#include "util.h"
-
-struct pn_selector_t {
- struct pollfd *fds;
- pn_timestamp_t *deadlines;
- size_t capacity;
- pn_list_t *selectables;
- size_t current;
- pn_timestamp_t awoken;
- pn_error_t *error;
-};
-
-void pn_selector_initialize(void *obj)
-{
- pn_selector_t *selector = (pn_selector_t *) obj;
- selector->fds = NULL;
- selector->deadlines = NULL;
- selector->capacity = 0;
- selector->selectables = pn_list(PN_WEAKREF, 0);
- selector->current = 0;
- selector->awoken = 0;
- selector->error = pn_error();
-}
-
-void pn_selector_finalize(void *obj)
-{
- pn_selector_t *selector = (pn_selector_t *) obj;
- free(selector->fds);
- free(selector->deadlines);
- pn_free(selector->selectables);
- pn_error_free(selector->error);
-}
-
-#define pn_selector_hashcode NULL
-#define pn_selector_compare NULL
-#define pn_selector_inspect NULL
-
-pn_selector_t *pni_selector(void)
-{
- static const pn_class_t clazz = PN_CLASS(pn_selector);
- pn_selector_t *selector = (pn_selector_t *) pn_class_new(&clazz, sizeof(pn_selector_t));
- return selector;
-}
-
-void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable)
-{
- assert(selector);
- assert(selectable);
- assert(pni_selectable_get_index(selectable) < 0);
-
- if (pni_selectable_get_index(selectable) < 0) {
- pn_list_add(selector->selectables, selectable);
- size_t size = pn_list_size(selector->selectables);
-
- if (selector->capacity < size) {
- selector->fds = (struct pollfd *) realloc(selector->fds, size*sizeof(struct pollfd));
- selector->deadlines = (pn_timestamp_t *) realloc(selector->deadlines, size*sizeof(pn_timestamp_t));
- selector->capacity = size;
- }
-
- pni_selectable_set_index(selectable, size - 1);
- }
-
- pn_selector_update(selector, selectable);
-}
-
-void pn_selector_update(pn_selector_t *selector, pn_selectable_t *selectable)
-{
- int idx = pni_selectable_get_index(selectable);
- assert(idx >= 0);
- selector->fds[idx].fd = pn_selectable_get_fd(selectable);
- selector->fds[idx].events = 0;
- selector->fds[idx].revents = 0;
- if (pn_selectable_is_reading(selectable)) {
- selector->fds[idx].events |= POLLIN;
- }
- if (pn_selectable_is_writing(selectable)) {
- selector->fds[idx].events |= POLLOUT;
- }
- selector->deadlines[idx] = pn_selectable_get_deadline(selectable);
-}
-
-void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable)
-{
- assert(selector);
- assert(selectable);
-
- int idx = pni_selectable_get_index(selectable);
- assert(idx >= 0);
- pn_list_del(selector->selectables, idx, 1);
- size_t size = pn_list_size(selector->selectables);
- for (size_t i = idx; i < size; i++) {
- pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(selector->selectables, i);
- pni_selectable_set_index(sel, i);
- selector->fds[i] = selector->fds[i + 1];
- }
-
- pni_selectable_set_index(selectable, -1);
-
- if (selector->current >= (size_t) idx) {
- selector->current--;
- }
-}
-
-size_t pn_selector_size(pn_selector_t *selector) {
- assert(selector);
- return pn_list_size(selector->selectables);
-}
-
-int pn_selector_select(pn_selector_t *selector, int timeout)
-{
- assert(selector);
-
- size_t size = pn_list_size(selector->selectables);
-
- if (timeout) {
- pn_timestamp_t deadline = 0;
- for (size_t i = 0; i < size; i++) {
- pn_timestamp_t d = selector->deadlines[i];
- if (d)
- deadline = (deadline == 0) ? d : pn_min(deadline, d);
- }
-
- if (deadline) {
- pn_timestamp_t now = pn_i_now();
- int64_t delta = deadline - now;
- if (delta < 0) {
- timeout = 0;
- } else if (delta < timeout) {
- timeout = delta;
- }
- }
- }
-
- int error = 0;
- int result = poll(selector->fds, size, timeout);
- if (result == -1) {
- error = pn_i_error_from_errno(selector->error, "poll");
- } else {
- selector->current = 0;
- selector->awoken = pn_i_now();
- }
-
- return error;
-}
-
-pn_selectable_t *pn_selector_next(pn_selector_t *selector, int *events)
-{
- pn_list_t *l = selector->selectables;
- size_t size = pn_list_size(l);
- while (selector->current < size) {
- pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(l, selector->current);
- struct pollfd *pfd = &selector->fds[selector->current];
- pn_timestamp_t deadline = selector->deadlines[selector->current];
- int ev = 0;
- if (pfd->revents & POLLIN) {
- ev |= PN_READABLE;
- }
- if ((pfd->revents & POLLERR) ||
- (pfd->revents & POLLHUP) ||
- (pfd->revents & POLLNVAL)) {
- ev |= PN_ERROR;
- }
- if (pfd->revents & POLLOUT) {
- ev |= PN_WRITABLE;
- }
- if (deadline && selector->awoken >= deadline) {
- ev |= PN_EXPIRED;
- }
- selector->current++;
- if (ev) {
- *events = ev;
- return sel;
- }
- }
- return NULL;
-}
-
-void pn_selector_free(pn_selector_t *selector)
-{
- assert(selector);
- pn_free(selector);
-}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/reactor/acceptor.c
----------------------------------------------------------------------
diff --git a/proton-c/src/reactor/acceptor.c b/proton-c/src/reactor/acceptor.c
index f56f7bd..a044748 100644
--- a/proton-c/src/reactor/acceptor.c
+++ b/proton-c/src/reactor/acceptor.c
@@ -19,13 +19,14 @@
*
*/
-#include <proton/io.h>
#include <proton/sasl.h>
-#include <proton/selector.h>
#include <proton/transport.h>
#include <proton/connection.h>
+
+#include "io.h"
#include "reactor.h"
#include "selectable.h"
+#include "selector.h"
#include <string.h>
@@ -38,7 +39,7 @@ PN_HANDLE(PNI_ACCEPTOR_CONNECTION)
void pni_acceptor_readable(pn_selectable_t *sel) {
pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
char name[1024];
- pn_socket_t sock = pn_accept(pn_reactor_io(reactor), pn_selectable_get_fd(sel), name, 1024);
+ pn_socket_t sock = pn_accept(pni_reactor_io(reactor), pn_selectable_get_fd(sel), name, 1024);
pn_handler_t *handler = (pn_handler_t *) pn_record_get(pn_selectable_attachments(sel), PNI_ACCEPTOR_HANDLER);
if (!handler) { handler = pn_reactor_get_handler(reactor); }
pn_record_t *record = pn_selectable_attachments(sel);
@@ -67,12 +68,12 @@ void pni_acceptor_readable(pn_selectable_t *sel) {
void pni_acceptor_finalize(pn_selectable_t *sel) {
pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
if (pn_selectable_get_fd(sel) != PN_INVALID_SOCKET) {
- pn_close(pn_reactor_io(reactor), pn_selectable_get_fd(sel));
+ pn_close(pni_reactor_io(reactor), pn_selectable_get_fd(sel));
}
}
pn_acceptor_t *pn_reactor_acceptor(pn_reactor_t *reactor, const char *host, const char *port, pn_handler_t *handler) {
- pn_socket_t socket = pn_listen(pn_reactor_io(reactor), host, port);
+ pn_socket_t socket = pn_listen(pni_reactor_io(reactor), host, port);
if (socket == PN_INVALID_SOCKET) {
return NULL;
}
@@ -94,7 +95,7 @@ void pn_acceptor_close(pn_acceptor_t *acceptor) {
if (!pn_selectable_is_terminal(sel)) {
pn_reactor_t *reactor = (pn_reactor_t *) pni_selectable_get_context(sel);
pn_socket_t socket = pn_selectable_get_fd(sel);
- pn_close(pn_reactor_io(reactor), socket);
+ pn_close(pni_reactor_io(reactor), socket);
pn_selectable_set_fd(sel, PN_INVALID_SOCKET);
pn_selectable_terminate(sel);
pn_reactor_update(reactor, sel);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/reactor/connection.c
----------------------------------------------------------------------
diff --git a/proton-c/src/reactor/connection.c b/proton-c/src/reactor/connection.c
index d73e386..4bc8b8d 100644
--- a/proton-c/src/reactor/connection.c
+++ b/proton-c/src/reactor/connection.c
@@ -28,6 +28,7 @@
#include <assert.h>
#include <stdio.h>
#include <string.h>
+#include "io.h"
#include "selectable.h"
#include "reactor.h"
@@ -187,12 +188,12 @@ void pni_handle_bound(pn_reactor_t *reactor, pn_event_t *event) {
pn_transport_close_tail(transport);
pn_transport_close_head(transport);
} else {
- pn_socket_t sock = pn_connect(pn_reactor_io(reactor), host, port);
+ pn_socket_t sock = pn_connect(pni_reactor_io(reactor), host, port);
// invalid sockets are ignored by poll, so we need to do this manualy
if (sock == PN_INVALID_SOCKET) {
pn_condition_t *cond = pn_transport_condition(transport);
pn_condition_set_name(cond, "proton:io");
- pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+ pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
pn_transport_close_tail(transport);
pn_transport_close_head(transport);
} else {
@@ -215,14 +216,14 @@ static void pni_connection_readable(pn_selectable_t *sel)
pn_transport_t *transport = pni_transport(sel);
ssize_t capacity = pn_transport_capacity(transport);
if (capacity > 0) {
- ssize_t n = pn_recv(pn_reactor_io(reactor), pn_selectable_get_fd(sel),
+ ssize_t n = pn_recv(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
pn_transport_tail(transport), capacity);
if (n <= 0) {
- if (n == 0 || !pn_wouldblock(pn_reactor_io(reactor))) {
+ if (n == 0 || !pn_wouldblock(pni_reactor_io(reactor))) {
if (n < 0) {
pn_condition_t *cond = pn_transport_condition(transport);
pn_condition_set_name(cond, "proton:io");
- pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+ pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
}
pn_transport_close_tail(transport);
}
@@ -246,14 +247,14 @@ static void pni_connection_writable(pn_selectable_t *sel)
pn_transport_t *transport = pni_transport(sel);
ssize_t pending = pn_transport_pending(transport);
if (pending > 0) {
- ssize_t n = pn_send(pn_reactor_io(reactor), pn_selectable_get_fd(sel),
+ ssize_t n = pn_send(pni_reactor_io(reactor), pn_selectable_get_fd(sel),
pn_transport_head(transport), pending);
if (n < 0) {
- if (!pn_wouldblock(pn_reactor_io(reactor))) {
+ if (!pn_wouldblock(pni_reactor_io(reactor))) {
pn_condition_t *cond = pn_transport_condition(transport);
if (!pn_condition_is_set(cond)) {
pn_condition_set_name(cond, "proton:io");
- pn_condition_set_description(cond, pn_error_text(pn_io_error(pn_reactor_io(reactor))));
+ pn_condition_set_description(cond, pn_error_text(pn_reactor_error(reactor)));
}
pn_transport_close_head(transport);
}
@@ -296,7 +297,7 @@ static void pni_connection_finalize(pn_selectable_t *sel) {
pn_record_t *record = pn_transport_attachments(transport);
pn_record_set(record, PN_TRANCTX, NULL);
pn_socket_t fd = pn_selectable_get_fd(sel);
- pn_close(pn_reactor_io(reactor), fd);
+ pn_close(pni_reactor_io(reactor), fd);
}
pn_selectable_t *pn_reactor_selectable_transport(pn_reactor_t *reactor, pn_socket_t sock, pn_transport_t *transport) {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/reactor/io.h
----------------------------------------------------------------------
diff --git a/proton-c/src/reactor/io.h b/proton-c/src/reactor/io.h
new file mode 100644
index 0000000..24596ec
--- /dev/null
+++ b/proton-c/src/reactor/io.h
@@ -0,0 +1,70 @@
+#ifndef PROTON_IO_H
+#define PROTON_IO_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 "selector.h"
+
+#include <proton/import_export.h>
+#include <proton/error.h>
+#include <proton/type_compat.h>
+#include <stddef.h>
+
+/**
+ * A ::pn_io_t manages IO for a group of pn_socket_t handles. A
+ * pn_io_t object may have zero or one pn_selector_t selectors
+ * associated with it (see ::pn_io_selector()). If one is associated,
+ * all the pn_socket_t handles managed by a pn_io_t must use that
+ * pn_selector_t instance.
+ *
+ * The pn_io_t interface is single-threaded. All methods are intended
+ * to be used by one thread at a time, except that multiple threads
+ * may use:
+ *
+ * ::pn_write()
+ * ::pn_send()
+ * ::pn_recv()
+ * ::pn_close()
+ * ::pn_selector_select()
+ *
+ * provided at most one thread is calling ::pn_selector_select() and
+ * the other threads are operating on separate pn_socket_t handles.
+ */
+typedef struct pn_io_t pn_io_t;
+
+pn_io_t *pn_io(void);
+void pn_io_free(pn_io_t *io);
+pn_error_t *pn_io_error(pn_io_t *io);
+pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port);
+pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port);
+
+pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size);
+void pn_close(pn_io_t *io, pn_socket_t socket);
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
+ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
+int pn_pipe(pn_io_t *io, pn_socket_t *dest);
+ssize_t pn_read(pn_io_t *io, pn_socket_t socket, void *buf, size_t size);
+ssize_t pn_write(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size);
+bool pn_wouldblock(pn_io_t *io);
+pn_selector_t *pn_io_selector(pn_io_t *io);
+
+#endif /* io.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/reactor/io/posix/io.c
----------------------------------------------------------------------
diff --git a/proton-c/src/reactor/io/posix/io.c b/proton-c/src/reactor/io/posix/io.c
new file mode 100644
index 0000000..5a0de3b
--- /dev/null
+++ b/proton-c/src/reactor/io/posix/io.c
@@ -0,0 +1,342 @@
+/*
+ *
+ * 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 "reactor/io.h"
+#include "reactor/selector.h"
+#include "platform/platform.h" // pn_i_error_from_errno
+
+#include <proton/object.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#define MAX_HOST (1024)
+#define MAX_SERV (64)
+
+struct pn_io_t {
+ char host[MAX_HOST];
+ char serv[MAX_SERV];
+ pn_error_t *error;
+ pn_selector_t *selector;
+ bool wouldblock;
+};
+
+void pn_io_initialize(void *obj)
+{
+ pn_io_t *io = (pn_io_t *) obj;
+ io->error = pn_error();
+ io->wouldblock = false;
+ io->selector = NULL;
+}
+
+void pn_io_finalize(void *obj)
+{
+ pn_io_t *io = (pn_io_t *) obj;
+ pn_error_free(io->error);
+}
+
+#define pn_io_hashcode NULL
+#define pn_io_compare NULL
+#define pn_io_inspect NULL
+
+pn_io_t *pn_io(void)
+{
+ static const pn_class_t clazz = PN_CLASS(pn_io);
+ pn_io_t *io = (pn_io_t *) pn_class_new(&clazz, sizeof(pn_io_t));
+ return io;
+}
+
+void pn_io_free(pn_io_t *io)
+{
+ pn_free(io);
+}
+
+pn_error_t *pn_io_error(pn_io_t *io)
+{
+ assert(io);
+ return io->error;
+}
+
+int pn_pipe(pn_io_t *io, pn_socket_t *dest)
+{
+ int n = pipe(dest);
+ if (n) {
+ pn_i_error_from_errno(io->error, "pipe");
+ }
+
+ return n;
+}
+
+static void pn_configure_sock(pn_io_t *io, pn_socket_t sock) {
+ // this would be nice, but doesn't appear to exist on linux
+ /*
+ int set = 1;
+ if (!setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int))) {
+ pn_i_error_from_errno(io->error, "setsockopt");
+ };
+ */
+
+ int flags = fcntl(sock, F_GETFL);
+ flags |= O_NONBLOCK;
+
+ if (fcntl(sock, F_SETFL, flags) < 0) {
+ pn_i_error_from_errno(io->error, "fcntl");
+ }
+
+ //
+ // Disable the Nagle algorithm on TCP connections.
+ //
+ // Note: It would be more correct for the "level" argument to be SOL_TCP. However, there
+ // are portability issues with this macro so we use IPPROTO_TCP instead.
+ //
+ int tcp_nodelay = 1;
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*) &tcp_nodelay, sizeof(tcp_nodelay)) < 0) {
+ pn_i_error_from_errno(io->error, "setsockopt");
+ }
+}
+
+static inline int pn_create_socket(int af, int protocol);
+
+pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port)
+{
+ struct addrinfo *addr;
+ struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
+ int code = getaddrinfo(host, port, &hints, &addr);
+ if (code) {
+ pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s\n", host, port, gai_strerror(code));
+ return PN_INVALID_SOCKET;
+ }
+
+ pn_socket_t sock = pn_create_socket(addr->ai_family, addr->ai_protocol);
+ if (sock == PN_INVALID_SOCKET) {
+ freeaddrinfo(addr);
+ pn_i_error_from_errno(io->error, "pn_create_socket");
+ return PN_INVALID_SOCKET;
+ }
+
+ int optval = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
+ pn_i_error_from_errno(io->error, "setsockopt");
+ freeaddrinfo(addr);
+ close(sock);
+ return PN_INVALID_SOCKET;
+ }
+
+ if (bind(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
+ pn_i_error_from_errno(io->error, "bind");
+ freeaddrinfo(addr);
+ close(sock);
+ return PN_INVALID_SOCKET;
+ }
+
+ freeaddrinfo(addr);
+
+ if (listen(sock, 50) == -1) {
+ pn_i_error_from_errno(io->error, "listen");
+ close(sock);
+ return PN_INVALID_SOCKET;
+ }
+
+ return sock;
+}
+
+pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port)
+{
+ struct addrinfo *addr;
+ struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM};
+ int code = getaddrinfo(host, port, &hints, &addr);
+ if (code) {
+ pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s", host, port, gai_strerror(code));
+ return PN_INVALID_SOCKET;
+ }
+
+ pn_socket_t sock = pn_create_socket(addr->ai_family, addr->ai_protocol);
+ if (sock == PN_INVALID_SOCKET) {
+ pn_i_error_from_errno(io->error, "pn_create_socket");
+ freeaddrinfo(addr);
+ return PN_INVALID_SOCKET;
+ }
+
+ pn_configure_sock(io, sock);
+
+ if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
+ if (errno != EINPROGRESS) {
+ pn_i_error_from_errno(io->error, "connect");
+ freeaddrinfo(addr);
+ close(sock);
+ return PN_INVALID_SOCKET;
+ }
+ }
+
+ freeaddrinfo(addr);
+
+ return sock;
+}
+
+pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ *name = '\0';
+ pn_socket_t sock = accept(socket, (struct sockaddr *) &addr, &addrlen);
+ if (sock == PN_INVALID_SOCKET) {
+ pn_i_error_from_errno(io->error, "accept");
+ return sock;
+ } else {
+ int code;
+ if ((code = getnameinfo((struct sockaddr *) &addr, addrlen, io->host, MAX_HOST, io->serv, MAX_SERV, 0))) {
+ pn_error_format(io->error, PN_ERR, "getnameinfo: %s\n", gai_strerror(code));
+ if (close(sock) == -1)
+ pn_i_error_from_errno(io->error, "close");
+ return PN_INVALID_SOCKET;
+ } else {
+ pn_configure_sock(io, sock);
+ pni_snprintf(name, size, "%s:%s", io->host, io->serv);
+ return sock;
+ }
+ }
+}
+
+/* Abstract away turning off SIGPIPE */
+#ifdef MSG_NOSIGNAL
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t len) {
+ ssize_t count = send(socket, buf, len, MSG_NOSIGNAL);
+ io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
+ if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
+ return count;
+}
+
+static inline int pn_create_socket(int af, int protocol) {
+ return socket(af, SOCK_STREAM, protocol);
+}
+#elif defined(SO_NOSIGPIPE)
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size) {
+ ssize_t count = send(socket, buf, size, 0);
+ io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
+ if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
+ return count;
+}
+
+static inline int pn_create_socket(int af, int protocol) {
+ int sock;
+ sock = socket(af, SOCK_STREAM, protocol);
+ if (sock == -1) return sock;
+
+ int optval = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) == -1) {
+ close(sock);
+ return -1;
+ }
+ return sock;
+}
+#else
+
+#include <signal.h>
+
+static inline int pn_create_socket(int af, int protocol) {
+ return socket(af, SOCK_STREAM, protocol);
+}
+
+static ssize_t nosigpipe_send(int fd, const void *buffer, size_t size) {
+ sigset_t pendingSignals, oldSignals, newSignals;
+ ssize_t count;
+ int sendErrno, sigmaskErr;
+
+ sigpending(&pendingSignals);
+ int sigpipeIsPending = sigismember(&pendingSignals, SIGPIPE);
+ if (!sigpipeIsPending) {
+ sigemptyset(&newSignals);
+ sigaddset(&newSignals, SIGPIPE);
+ if (sigmaskErr = pthread_sigmask(SIG_BLOCK, (const sigset_t *)&newSignals, (sigset_t *)&oldSignals))
+ {
+ errno = sigmaskErr;
+ return -1;
+ }
+ }
+
+ count = send(fd, buffer, size, 0);
+ if (!sigpipeIsPending) {
+ sendErrno = errno;
+ if (count == -1 && errno == EPIPE) {
+ while (-1 == sigtimedwait(&newSignals, NULL, &(struct timespec){ 0, 0 }) && errno == EINTR)
+ ; //do nothing
+ }
+ if (sigmaskErr = pthread_sigmask(SIG_SETMASK, (const sigset_t *)&oldSignals, (sigset_t *)NULL))
+ {
+ errno = sigmaskErr;
+ return -1;
+ }
+ errno = sendErrno;
+ }
+ return count;
+}
+
+ssize_t pn_send(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size) {
+ ssize_t count = nosigpipe_send(socket, buf, size);
+ io->wouldblock = (errno == EAGAIN || errno == EWOULDBLOCK);
+ if (count < 0) { pn_i_error_from_errno(io->error, "send"); }
+ return count;
+}
+#endif
+
+ssize_t pn_recv(pn_io_t *io, pn_socket_t socket, void *buf, size_t size)
+{
+ ssize_t count = recv(socket, buf, size, 0);
+ io->wouldblock = count < 0 && (errno == EAGAIN || errno == EWOULDBLOCK);
+ if (count < 0) { pn_i_error_from_errno(io->error, "recv"); }
+ return count;
+}
+
+ssize_t pn_write(pn_io_t *io, pn_socket_t socket, const void *buf, size_t size)
+{
+ return write(socket, buf, size);
+}
+
+ssize_t pn_read(pn_io_t *io, pn_socket_t socket, void *buf, size_t size)
+{
+ return read(socket, buf, size);
+}
+
+void pn_close(pn_io_t *io, pn_socket_t socket)
+{
+ close(socket);
+}
+
+bool pn_wouldblock(pn_io_t *io)
+{
+ return io->wouldblock;
+}
+
+pn_selector_t *pn_io_selector(pn_io_t *io)
+{
+ if (io->selector == NULL)
+ io->selector = pni_selector();
+ return io->selector;
+}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/a5850716/proton-c/src/reactor/io/posix/selector.c
----------------------------------------------------------------------
diff --git a/proton-c/src/reactor/io/posix/selector.c b/proton-c/src/reactor/io/posix/selector.c
new file mode 100644
index 0000000..bf6882a
--- /dev/null
+++ b/proton-c/src/reactor/io/posix/selector.c
@@ -0,0 +1,214 @@
+/*
+ *
+ * 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 "core/util.h"
+#include "platform/platform.h" // pn_i_now, pn_i_error_from_errno
+#include "reactor/io.h"
+#include "reactor/selector.h"
+#include "reactor/selectable.h"
+
+#include <proton/error.h>
+
+#include <poll.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct pn_selector_t {
+ struct pollfd *fds;
+ pn_timestamp_t *deadlines;
+ size_t capacity;
+ pn_list_t *selectables;
+ size_t current;
+ pn_timestamp_t awoken;
+ pn_error_t *error;
+};
+
+void pn_selector_initialize(void *obj)
+{
+ pn_selector_t *selector = (pn_selector_t *) obj;
+ selector->fds = NULL;
+ selector->deadlines = NULL;
+ selector->capacity = 0;
+ selector->selectables = pn_list(PN_WEAKREF, 0);
+ selector->current = 0;
+ selector->awoken = 0;
+ selector->error = pn_error();
+}
+
+void pn_selector_finalize(void *obj)
+{
+ pn_selector_t *selector = (pn_selector_t *) obj;
+ free(selector->fds);
+ free(selector->deadlines);
+ pn_free(selector->selectables);
+ pn_error_free(selector->error);
+}
+
+#define pn_selector_hashcode NULL
+#define pn_selector_compare NULL
+#define pn_selector_inspect NULL
+
+pn_selector_t *pni_selector(void)
+{
+ static const pn_class_t clazz = PN_CLASS(pn_selector);
+ pn_selector_t *selector = (pn_selector_t *) pn_class_new(&clazz, sizeof(pn_selector_t));
+ return selector;
+}
+
+void pn_selector_add(pn_selector_t *selector, pn_selectable_t *selectable)
+{
+ assert(selector);
+ assert(selectable);
+ assert(pni_selectable_get_index(selectable) < 0);
+
+ if (pni_selectable_get_index(selectable) < 0) {
+ pn_list_add(selector->selectables, selectable);
+ size_t size = pn_list_size(selector->selectables);
+
+ if (selector->capacity < size) {
+ selector->fds = (struct pollfd *) realloc(selector->fds, size*sizeof(struct pollfd));
+ selector->deadlines = (pn_timestamp_t *) realloc(selector->deadlines, size*sizeof(pn_timestamp_t));
+ selector->capacity = size;
+ }
+
+ pni_selectable_set_index(selectable, size - 1);
+ }
+
+ pn_selector_update(selector, selectable);
+}
+
+void pn_selector_update(pn_selector_t *selector, pn_selectable_t *selectable)
+{
+ int idx = pni_selectable_get_index(selectable);
+ assert(idx >= 0);
+ selector->fds[idx].fd = pn_selectable_get_fd(selectable);
+ selector->fds[idx].events = 0;
+ selector->fds[idx].revents = 0;
+ if (pn_selectable_is_reading(selectable)) {
+ selector->fds[idx].events |= POLLIN;
+ }
+ if (pn_selectable_is_writing(selectable)) {
+ selector->fds[idx].events |= POLLOUT;
+ }
+ selector->deadlines[idx] = pn_selectable_get_deadline(selectable);
+}
+
+void pn_selector_remove(pn_selector_t *selector, pn_selectable_t *selectable)
+{
+ assert(selector);
+ assert(selectable);
+
+ int idx = pni_selectable_get_index(selectable);
+ assert(idx >= 0);
+ pn_list_del(selector->selectables, idx, 1);
+ size_t size = pn_list_size(selector->selectables);
+ for (size_t i = idx; i < size; i++) {
+ pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(selector->selectables, i);
+ pni_selectable_set_index(sel, i);
+ selector->fds[i] = selector->fds[i + 1];
+ }
+
+ pni_selectable_set_index(selectable, -1);
+
+ if (selector->current >= (size_t) idx) {
+ selector->current--;
+ }
+}
+
+size_t pn_selector_size(pn_selector_t *selector) {
+ assert(selector);
+ return pn_list_size(selector->selectables);
+}
+
+int pn_selector_select(pn_selector_t *selector, int timeout)
+{
+ assert(selector);
+
+ size_t size = pn_list_size(selector->selectables);
+
+ if (timeout) {
+ pn_timestamp_t deadline = 0;
+ for (size_t i = 0; i < size; i++) {
+ pn_timestamp_t d = selector->deadlines[i];
+ if (d)
+ deadline = (deadline == 0) ? d : pn_min(deadline, d);
+ }
+
+ if (deadline) {
+ pn_timestamp_t now = pn_i_now();
+ int64_t delta = deadline - now;
+ if (delta < 0) {
+ timeout = 0;
+ } else if (delta < timeout) {
+ timeout = delta;
+ }
+ }
+ }
+
+ int error = 0;
+ int result = poll(selector->fds, size, timeout);
+ if (result == -1) {
+ error = pn_i_error_from_errno(selector->error, "poll");
+ } else {
+ selector->current = 0;
+ selector->awoken = pn_i_now();
+ }
+
+ return error;
+}
+
+pn_selectable_t *pn_selector_next(pn_selector_t *selector, int *events)
+{
+ pn_list_t *l = selector->selectables;
+ size_t size = pn_list_size(l);
+ while (selector->current < size) {
+ pn_selectable_t *sel = (pn_selectable_t *) pn_list_get(l, selector->current);
+ struct pollfd *pfd = &selector->fds[selector->current];
+ pn_timestamp_t deadline = selector->deadlines[selector->current];
+ int ev = 0;
+ if (pfd->revents & POLLIN) {
+ ev |= PN_READABLE;
+ }
+ if ((pfd->revents & POLLERR) ||
+ (pfd->revents & POLLHUP) ||
+ (pfd->revents & POLLNVAL)) {
+ ev |= PN_ERROR;
+ }
+ if (pfd->revents & POLLOUT) {
+ ev |= PN_WRITABLE;
+ }
+ if (deadline && selector->awoken >= deadline) {
+ ev |= PN_EXPIRED;
+ }
+ selector->current++;
+ if (ev) {
+ *events = ev;
+ return sel;
+ }
+ }
+ return NULL;
+}
+
+void pn_selector_free(pn_selector_t *selector)
+{
+ assert(selector);
+ pn_free(selector);
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org