src/lib/transport.c
branchnew-lib-errors
changeset 219 cefec18b8268
parent 183 7bfbe9070c50
equal deleted inserted replaced
218:5229a5d098b2 219:cefec18b8268
       
     1 #include "transport_internal.h"
       
     2 
       
     3 #include <assert.h>
       
     4 #include <stdlib.h>
       
     5 
       
     6 const struct error_list transport_errors = ERROR_LIST("transport",
       
     7     ERROR_TYPE(         ERR_TRANSPORT_EOF,              "EOF"                       ),
       
     8     ERROR_TYPE(         ERR_TRANSPORT_READABLE,         "transport not readable"    ),
       
     9     ERROR_TYPE(         ERR_TRANSPORT_WRITEABLE,        "transport not writeable"   )
       
    10 );
       
    11 
       
    12 /**
       
    13  * Our own object_type
       
    14  */
       
    15 const struct object_type transport_type_type = {
       
    16     .parent     = NULL,
       
    17 };
       
    18 
       
    19 /*
       
    20  * Internal API
       
    21  */
       
    22 void transport_init (transport_t *transport, const struct transport_type *type, const struct transport_info *info)
       
    23 {
       
    24     // init object
       
    25     object_init(&transport->base_obj, &type->base_type);
       
    26     
       
    27     // store
       
    28     if (info)
       
    29         transport->info = *info;
       
    30 }
       
    31 
       
    32 void* transport_check (transport_t *transport, const struct transport_type *type)
       
    33 {
       
    34     // trip as a bug
       
    35     assert(object_check(&transport->base_obj, &type->base_type));
       
    36 
       
    37     // ok, cast via void*
       
    38     return transport;
       
    39 }
       
    40 
       
    41 void transport_connected (transport_t *transport, const error_t *err, bool direct)
       
    42 {
       
    43     const struct transport_type *type = object_type(&transport->base_obj, &transport_type_type);
       
    44 
       
    45     if (direct || !type->methods._connected) {
       
    46         // user callback
       
    47         if (err) {
       
    48             // connect failed
       
    49             transport->info.cb_tbl->on_error(transport, err, transport->info.cb_arg);
       
    50 
       
    51         } else {
       
    52             // update state
       
    53             transport->connected = true;
       
    54 
       
    55             // connect succesfull
       
    56             transport->info.cb_tbl->on_connect(transport, transport->info.cb_arg);
       
    57         }
       
    58 
       
    59     } else {
       
    60         // wrapper method
       
    61         type->methods._connected(transport, err);
       
    62 
       
    63     }
       
    64 }
       
    65 
       
    66 void transport_invoke (transport_t *transport, short what)
       
    67 {
       
    68     // on_ready
       
    69     if (what & TRANSPORT_READ && transport->info.cb_tbl->on_read)
       
    70         transport->info.cb_tbl->on_read(transport, transport->info.cb_arg);
       
    71 
       
    72     // on_write
       
    73     if (what & TRANSPORT_WRITE && transport->info.cb_tbl->on_write)
       
    74         transport->info.cb_tbl->on_write(transport, transport->info.cb_arg);
       
    75 
       
    76 }
       
    77 
       
    78 void transport_error (transport_t *transport, const error_t *err)
       
    79 {
       
    80     // update state
       
    81     transport->connected = false;
       
    82 
       
    83     // invoke callback
       
    84     transport->info.cb_tbl->on_error(transport, err, transport->info.cb_arg);
       
    85 }
       
    86 
       
    87 /*
       
    88  * Public API
       
    89  */
       
    90 int transport_read (transport_t *transport, void *buf, size_t len, error_t *err)
       
    91 {
       
    92     const struct transport_type *type = object_type(&transport->base_obj, &transport_type_type);
       
    93 
       
    94     // not readable
       
    95     if (!type->methods.read)
       
    96         return SET_ERROR(err, &transport_errors, ERR_TRANSPORT_READABLE);
       
    97 
       
    98     // proxy off to method handler
       
    99     if (type->methods.read(transport, buf, &len, err))
       
   100         return -error_code(err);
       
   101     
       
   102     // return updated 'bytes-read' len
       
   103     return len;
       
   104 }
       
   105 
       
   106 int transport_write (transport_t *transport, const void *buf, size_t len, error_t *err)
       
   107 {
       
   108     const struct transport_type *type = object_type(&transport->base_obj, &transport_type_type);
       
   109 
       
   110     // not writeable
       
   111     if (!type->methods.write)
       
   112         return SET_ERROR(err, &transport_errors, ERR_TRANSPORT_WRITEABLE);
       
   113 
       
   114     // proxy off to method handler
       
   115     if (type->methods.write(transport, buf, &len, err))
       
   116         return -error_code(err);
       
   117 
       
   118     // return updated 'bytes-written' len
       
   119     return len;
       
   120 }
       
   121 
       
   122 err_t transport_events (transport_t *transport, short mask)
       
   123 {
       
   124     const struct transport_type *type = object_type(&transport->base_obj, &transport_type_type);
       
   125     error_t err;
       
   126 
       
   127     // notify transport
       
   128     if (type->methods.events) {
       
   129         if (type->methods.events(transport, mask, &err))
       
   130             goto error;
       
   131     }
       
   132 
       
   133     // update the event mask
       
   134     transport->info.ev_mask = mask;
       
   135 
       
   136     // ok
       
   137     return SUCCESS;
       
   138 
       
   139 error:
       
   140     return ERROR_CODE(&err);
       
   141 }
       
   142 
       
   143 void transport_set_callbacks (transport_t *transport, const struct transport_callbacks *cb_tbl, void *cb_arg)
       
   144 {
       
   145     transport->info.cb_tbl = cb_tbl;
       
   146     transport->info.cb_arg = cb_arg;
       
   147 }
       
   148 
       
   149 void transport_destroy (transport_t *transport)
       
   150 {
       
   151     const struct transport_type *type = object_type(&transport->base_obj, &transport_type_type);
       
   152 
       
   153     // destroy the transport-specific stuff
       
   154     if (type->methods.deinit)
       
   155         type->methods.deinit(transport);
       
   156 
       
   157     // then the transport itself
       
   158     free(transport);
       
   159 }
       
   160