PageRenderTime 44ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/ruby/trema/error.c

http://github.com/trema/trema
C | 258 lines | 143 code | 35 blank | 80 comment | 20 complexity | bb5aefab87a29098e19aa1002fc1ed0b MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (C) 2008-2012 NEC Corporation
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2, as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include "ruby.h"
  18. #include "trema-ruby-utils.h"
  19. #include "trema.h"
  20. extern VALUE mTrema;
  21. VALUE cError;
  22. static VALUE
  23. error_alloc( VALUE klass ) {
  24. buffer *error = create_error( 0, 0, 0, NULL );
  25. return Data_Wrap_Struct( klass, NULL, free_buffer, error );
  26. }
  27. /*
  28. * @overload initialize(options)
  29. * @example
  30. * Error.new(
  31. * :type => OFPET_BAD_REQUEST,
  32. * :code => OFPBRC_BAD_TYPE,
  33. * )
  34. * Error.new(
  35. * :type => OFPET_BAD_REQUEST,
  36. * :code => OFPBRC_BAD_TYPE,
  37. * :transcation_id => 123
  38. * )
  39. * Error.new(
  40. * :type => OFPET_BAD_REQUEST,
  41. * :code => OFPBRC_BAD_TYPE,
  42. * :transcation_id => 123
  43. * :data => "Error!!"
  44. * )
  45. * @param [Hash] options
  46. * the options to create a message with.
  47. * @option options [Number] :type
  48. * a command or action that failed.
  49. * @option options [Number] :code
  50. * the reason of the failed type error.
  51. * @option options [String] :data
  52. * a more user friendly explanation of the error. Defaults to nil
  53. * if not specified.
  54. * @option options [Number] :xid
  55. * @option options [Number] :transaction_id
  56. * An unsigned 32bit integer number associated with this message.
  57. * If not specified, an auto-generated value is set.
  58. * @raise [ArgumentError] if transaction ID is not an unsigned 32bit integer.
  59. * @raise [ArgumentError] if type and code are not supplied.
  60. * @raise [ArgumentError] if user data is not a string.
  61. * @raise [TypeError] if options is not a hash.
  62. * @return [Error]
  63. */
  64. static VALUE
  65. error_init( int argc, VALUE *argv, VALUE self ) {
  66. buffer *error = NULL;
  67. Data_Get_Struct( self, buffer, error );
  68. VALUE options;
  69. if ( rb_scan_args( argc, argv, "01", &options ) == 1 ) {
  70. Check_Type( options, T_HASH );
  71. VALUE tmp = Qnil;
  72. tmp = rb_hash_aref( options, ID2SYM( rb_intern( "type" ) ) );
  73. if ( tmp != Qnil ) {
  74. ( ( struct ofp_error_msg * ) error->data )->type = htons( ( uint16_t ) NUM2UINT( tmp ) );
  75. }
  76. else {
  77. rb_raise( rb_eArgError, "Type is a mandatory option" );
  78. }
  79. tmp = rb_hash_aref( options, ID2SYM( rb_intern( "code" ) ) );
  80. if ( tmp != Qnil ) {
  81. ( ( struct ofp_error_msg * ) error->data )->code = htons( ( uint16_t ) NUM2UINT( tmp ) );
  82. }
  83. else {
  84. rb_raise( rb_eArgError, "Code is a mandatory option" );
  85. }
  86. VALUE xid = Qnil;
  87. tmp = rb_hash_aref( options, ID2SYM( rb_intern( "transaction_id" ) ) );
  88. if ( tmp != Qnil ) {
  89. xid = tmp;
  90. }
  91. tmp = rb_hash_aref( options, ID2SYM( rb_intern( "xid" ) ) );
  92. if ( tmp != Qnil ) {
  93. xid = tmp;
  94. }
  95. if ( xid != Qnil ) {
  96. validate_xid( xid );
  97. set_xid( error, ( uint32_t ) NUM2UINT( xid ) );
  98. }
  99. else {
  100. set_xid( error, get_transaction_id() );
  101. }
  102. VALUE data = rb_hash_aref( options, ID2SYM( rb_intern( "data" ) ) );
  103. if ( data != Qnil ) {
  104. Check_Type( data, T_STRING );
  105. uint16_t length = ( u_int16_t ) RSTRING_LEN( data );
  106. append_back_buffer( error, length );
  107. ( ( struct ofp_header * ) ( error->data ) )->length = htons( ( uint16_t ) ( offsetof( struct ofp_error_msg, data ) + length ) );
  108. memcpy( ( char * ) error->data + offsetof( struct ofp_error_msg, data ), RSTRING_PTR( data ), length );
  109. }
  110. }
  111. else {
  112. rb_raise( rb_eArgError, "Type and code are mandatory options" );
  113. }
  114. return self;
  115. }
  116. static struct ofp_error_msg *
  117. get_error( VALUE self ) {
  118. buffer *error;
  119. Data_Get_Struct( self, buffer, error );
  120. return ( struct ofp_error_msg * ) error->data;
  121. }
  122. /*
  123. * Transaction ids, message sequence numbers matching requests to replies.
  124. *
  125. * @return [Number] the value of transaction id.
  126. */
  127. static VALUE
  128. error_transaction_id( VALUE self ) {
  129. struct ofp_error_msg *error = get_error( self );
  130. uint32_t xid = ntohl( error->header.xid );
  131. return UINT2NUM( xid );
  132. }
  133. /*
  134. * An optional user data payload field, possibly detailed explanation of the error.
  135. *
  136. * @return [String] user data payload is set.
  137. * @return [nil] user data payload is not set.
  138. */
  139. static VALUE
  140. error_data( VALUE self ) {
  141. struct ofp_error_msg *error = get_error( self );
  142. long length = ( long ) ( ntohs( error->header.length ) - sizeof( struct ofp_error_msg ) );
  143. if ( length > 0 ) {
  144. return rb_str_new( ( char * ) error->data, length );
  145. }
  146. else {
  147. return Qnil;
  148. }
  149. }
  150. /*
  151. * Indicates the command or action that failed.
  152. *
  153. * @return [Number] the value of error type.
  154. */
  155. static VALUE
  156. error_type( VALUE self ) {
  157. struct ofp_error_msg *error = get_error( self );
  158. return UINT2NUM( ntohs( error->type ) );
  159. }
  160. /*
  161. * Reason of the failed type error.
  162. *
  163. * @return [Number] the value of error code.
  164. */
  165. static VALUE
  166. error_code( VALUE self ) {
  167. struct ofp_error_msg *error = get_error( self );
  168. return UINT2NUM( ntohs( error->code ) );
  169. }
  170. void
  171. Init_error() {
  172. rb_define_const( mTrema, "OFPET_HELLO_FAILED", INT2NUM( OFPET_HELLO_FAILED ) );
  173. rb_define_const( mTrema, "OFPHFC_INCOMPATIBLE", INT2NUM( OFPHFC_INCOMPATIBLE ) );
  174. rb_define_const( mTrema, "OFPHFC_EPERM", INT2NUM( OFPHFC_EPERM ) );
  175. rb_define_const( mTrema, "OFPET_BAD_REQUEST", INT2NUM( OFPET_BAD_REQUEST ) );
  176. rb_define_const( mTrema, "OFPBRC_BAD_VERSION", INT2NUM( OFPBRC_BAD_VERSION ) );
  177. rb_define_const( mTrema, "OFPBRC_BAD_TYPE", INT2NUM( OFPBRC_BAD_TYPE ) );
  178. rb_define_const( mTrema, "OFPBRC_BAD_STAT", INT2NUM( OFPBRC_BAD_STAT ) );
  179. rb_define_const( mTrema, "OFPBRC_BAD_VENDOR", INT2NUM( OFPBRC_BAD_VENDOR ) );
  180. rb_define_const( mTrema, "OFPBRC_BAD_SUBTYPE", INT2NUM( OFPBRC_BAD_SUBTYPE ) );
  181. rb_define_const( mTrema, "OFPBRC_EPERM", INT2NUM( OFPBRC_EPERM ) );
  182. rb_define_const( mTrema, "OFPBRC_BAD_LEN", INT2NUM( OFPBRC_BAD_LEN ) );
  183. rb_define_const( mTrema, "OFPBRC_BUFFER_EMPTY", INT2NUM( OFPBRC_BUFFER_EMPTY ) );
  184. rb_define_const( mTrema, "OFPBRC_BUFFER_UNKNOWN", INT2NUM( OFPBRC_BUFFER_UNKNOWN ) );
  185. rb_define_const( mTrema, "OFPET_BAD_ACTION", INT2NUM( OFPET_BAD_ACTION ) );
  186. rb_define_const( mTrema, "OFPBAC_BAD_TYPE", INT2NUM( OFPBAC_BAD_TYPE ) );
  187. rb_define_const( mTrema, "OFPBAC_BAD_LEN", INT2NUM( OFPBAC_BAD_LEN ) );
  188. rb_define_const( mTrema, "OFPBAC_BAD_VENDOR", INT2NUM( OFPBAC_BAD_VENDOR ) );
  189. rb_define_const( mTrema, "OFPBAC_BAD_VENDOR_TYPE", INT2NUM( OFPBAC_BAD_VENDOR_TYPE ) );
  190. rb_define_const( mTrema, "OFPBAC_BAD_OUT_PORT", INT2NUM( OFPBAC_BAD_OUT_PORT ) );
  191. rb_define_const( mTrema, "OFPBAC_BAD_ARGUMENT", INT2NUM( OFPBAC_BAD_ARGUMENT ) );
  192. rb_define_const( mTrema, "OFPBAC_EPERM", INT2NUM( OFPBAC_EPERM ) );
  193. rb_define_const( mTrema, "OFPBAC_TOO_MANY", INT2NUM( OFPBAC_TOO_MANY ) );
  194. rb_define_const( mTrema, "OFPBAC_BAD_QUEUE", INT2NUM( OFPBAC_BAD_QUEUE ) );
  195. rb_define_const( mTrema, "OFPET_FLOW_MOD_FAILED", INT2NUM( OFPET_FLOW_MOD_FAILED ) );
  196. rb_define_const( mTrema, "OFPFMFC_ALL_TABLES_FULL", INT2NUM( OFPFMFC_ALL_TABLES_FULL ) );
  197. rb_define_const( mTrema, "OFPFMFC_OVERLAP", INT2NUM( OFPFMFC_OVERLAP ) );
  198. rb_define_const( mTrema, "OFPFMFC_EPERM", INT2NUM( OFPFMFC_EPERM ) );
  199. rb_define_const( mTrema, "OFPFMFC_BAD_EMERG_TIMEOUT", INT2NUM( OFPFMFC_BAD_EMERG_TIMEOUT ) );
  200. rb_define_const( mTrema, "OFPFMFC_BAD_COMMAND", INT2NUM( OFPFMFC_BAD_COMMAND ) );
  201. rb_define_const( mTrema, "OFPFMFC_UNSUPPORTED", INT2NUM( OFPFMFC_UNSUPPORTED ) );
  202. rb_define_const( mTrema, "OFPET_PORT_MOD_FAILED", INT2NUM( OFPET_PORT_MOD_FAILED ) );
  203. rb_define_const( mTrema, "OFPPMFC_BAD_PORT", INT2NUM( OFPPMFC_BAD_PORT ) );
  204. rb_define_const( mTrema, "OFPPMFC_BAD_HW_ADDR", INT2NUM( OFPPMFC_BAD_HW_ADDR ) );
  205. rb_define_const( mTrema, "OFPET_QUEUE_OP_FAILED", INT2NUM( OFPET_QUEUE_OP_FAILED ) );
  206. rb_define_const( mTrema, "OFPQOFC_BAD_PORT", INT2NUM(OFPQOFC_BAD_PORT));
  207. rb_define_const( mTrema, "OFPQOFC_BAD_QUEUE", INT2NUM(OFPQOFC_BAD_QUEUE));
  208. rb_define_const( mTrema, "OFPQOFC_EPERM", INT2NUM(OFPQOFC_EPERM));
  209. cError = rb_define_class_under( mTrema, "Error", rb_cObject );
  210. rb_define_alloc_func( cError, error_alloc );
  211. rb_define_method( cError, "initialize", error_init, -1 );
  212. rb_define_method( cError, "transaction_id", error_transaction_id, 0 );
  213. rb_alias( cError, rb_intern( "xid" ), rb_intern( "transaction_id" ) );
  214. rb_define_method( cError, "data", error_data, 0 );
  215. rb_define_method( cError, "error_type", error_type, 0 );
  216. rb_define_method( cError, "code", error_code, 0 );
  217. }
  218. /*
  219. * Local variables:
  220. * c-basic-offset: 2
  221. * indent-tabs-mode: nil
  222. * End:
  223. */