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: [email protected] For additional commands, e-mail: [email protected]
