terom@154: #include "transport_internal.h" terom@154: terom@155: #include terom@154: terom@156: /* terom@156: * Internal API terom@156: */ terom@155: void transport_init (transport_t *transport, const struct transport_type *type, const struct transport_info *info) terom@154: { terom@154: // not already bound terom@155: assert(!transport->type); terom@154: terom@154: // store terom@154: transport->type = type; terom@157: terom@157: if (info) terom@157: transport->info = *info; terom@154: } terom@154: terom@154: void* transport_check (transport_t *transport, const struct transport_type *type) terom@154: { terom@159: const struct transport_type *tp_type; terom@159: terom@154: // sanity check terom@159: assert(type); terom@154: terom@159: // look for a matching type in the transport's type list terom@159: for (tp_type = transport->type; tp_type; tp_type = tp_type->parent) terom@159: if (tp_type == type) terom@159: break; terom@159: terom@159: // make sure we found one terom@159: assert(tp_type); terom@159: terom@154: // ok terom@154: return transport; terom@154: } terom@155: terom@155: void transport_connected (transport_t *transport, const error_t *err, bool direct) terom@155: { terom@155: // update state terom@155: transport->connected = true; terom@155: terom@155: if (direct || !transport->type->methods._connected) { terom@155: // user callback terom@155: if (err) terom@155: // connect failed terom@155: transport->info.cb_tbl->on_error(transport, err, transport->info.cb_arg); terom@155: else terom@155: // connect succesfull terom@155: transport->info.cb_tbl->on_connect(transport, transport->info.cb_arg); terom@155: terom@155: } else { terom@155: // wrapper method terom@155: transport->type->methods._connected(transport, err); terom@155: } terom@155: } terom@155: terom@155: void transport_invoke (transport_t *transport, short what) terom@155: { terom@155: // on_ready terom@155: if (what & TRANSPORT_READ && transport->info.cb_tbl->on_read) terom@155: transport->info.cb_tbl->on_read(transport, transport->info.cb_arg); terom@155: terom@155: // on_write terom@155: if (what & TRANSPORT_WRITE && transport->info.cb_tbl->on_write) terom@155: transport->info.cb_tbl->on_write(transport, transport->info.cb_arg); terom@155: terom@155: } terom@155: terom@155: void transport_error (transport_t *transport, const error_t *err) terom@155: { terom@155: // update state terom@155: transport->connected = false; terom@155: terom@155: // invoke callback terom@155: transport->info.cb_tbl->on_error(transport, err, transport->info.cb_arg); terom@155: } terom@156: terom@156: /* terom@156: * Public API terom@156: */ terom@156: int transport_read (transport_t *transport, void *buf, size_t len, error_t *err) terom@156: { terom@156: // not readable terom@156: if (!transport->type->methods.read) terom@159: return SET_ERROR(err, -1); terom@156: terom@156: // proxy off to method handler terom@156: if (transport->type->methods.read(transport, buf, &len, err)) terom@156: return -ERROR_CODE(err); terom@156: terom@156: // return updated bytes-read len terom@156: return len; terom@156: } terom@156: terom@156: int transport_write (transport_t *transport, const void *buf, size_t len, error_t *err) terom@156: { terom@156: // XXX: not writeable terom@156: if (!transport->type->methods.write) terom@159: return SET_ERROR(err, -1); terom@156: terom@156: // proxy off to method handler terom@156: if (transport->type->methods.write(transport, buf, &len, err)) terom@156: return -ERROR_CODE(err); terom@156: terom@156: // return updated bytes-written len terom@156: return len; terom@156: } terom@156: terom@156: err_t transport_events (transport_t *transport, short mask) terom@156: { terom@156: error_t err; terom@156: terom@156: // notify transport terom@156: if (transport->type->methods.events) { terom@156: if (transport->type->methods.events(transport, mask, &err)) terom@156: goto error; terom@156: } terom@156: terom@156: // update the event mask terom@156: transport->info.ev_mask = mask; terom@156: terom@156: // ok terom@156: return SUCCESS; terom@156: terom@156: error: terom@156: return ERROR_CODE(&err); terom@156: } terom@156: terom@156: void transport_set_callbacks (transport_t *transport, const struct transport_callbacks *cb_tbl, void *cb_arg) terom@156: { terom@156: transport->info.cb_tbl = cb_tbl; terom@156: transport->info.cb_arg = cb_arg; terom@156: } terom@156: terom@156: void transport_destroy (transport_t *transport) terom@156: { terom@156: // destroy the transport-specific stuff terom@156: if (transport->type->methods.destroy) terom@156: transport->type->methods.destroy(transport); terom@156: terom@156: // then the transport itself terom@156: free(transport); terom@156: } terom@156: