Changeset 4629

Show
Ignore:
Timestamp:
02/14/07 23:17:09 (2 years ago)
Author:
morris
Message:

More p7 fixes:

* Handle * ? + in reply count field
* When checking compatibility, only do commutative check on reply order, not full reply compatibility
* Add WI_INTEGER_MIN/MAX
* Add name/bits accessors to cipher

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • libwired/trunk/libwired/base/wi-base.h

    r4556 r4629  
    6060#endif 
    6161 
    62 #define _WI_STRINGIFY(s)                        #s 
    63 #define WI_STRINGIFY(s)                         _WI_STRINGIFY(s) 
    64  
    6562#if __LP64__ 
    6663#define WI_64                                           1 
     
    6865typedef int64_t                                         wi_integer_t; 
    6966typedef uint64_t                                        wi_uinteger_t; 
     67 
     68#define WI_INTEGER_MIN                          INT64_MIN 
     69#define WI_INTEGER_MAX                          INT64_MAX 
     70#define WI_UINTEGER_MAX                         UINT64_MAX 
    7071#else 
    7172#define WI_32                                           1 
     
    7374typedef int32_t                                         wi_integer_t; 
    7475typedef uint32_t                                        wi_uinteger_t; 
     76 
     77#define WI_INTEGER_MIN                          INT32_MIN 
     78#define WI_INTEGER_MAX                          INT32_MAX 
     79#define WI_UINTEGER_MAX                         UINT32_MAX 
    7580#endif 
    7681 
    7782 
    7883enum { 
    79 #if WI_32 
    80         WI_NOT_FOUND                                    = 0x7FFFFFFF 
    81 #else 
    82         WI_NOT_FOUND                                    = 0x7FFFFFFFFFFFFFFF 
    83 #endif 
     84        WI_NOT_FOUND                                    = WI_INTEGER_MAX 
    8485}; 
    8586 
  • libwired/trunk/libwired/file/wi-file.c

    r4623 r4629  
    7272#include <wired/wi-string.h> 
    7373 
    74 #ifndef UINT_MAX 
    75 #define UINT_MAX 4294967295U 
    76 #endif 
    77  
    7874#define _WI_FILE_ASSERT_OPEN(file) \ 
    7975        WI_ASSERT((file)->fd >= 0, "%@ is not open", (file)) 
  • libwired/trunk/libwired/p7/wi-p7-base.h

    r4623 r4629  
    3434typedef struct _wi_p7_spec                      wi_p7_spec_t; 
    3535 
    36 #endif /* WI_ARRAY_H */ 
     36#endif /* WI_P7_BASE_H */ 
  • libwired/trunk/libwired/p7/wi-p7-crypto.c

    r4627 r4629  
    5151static wi_string_t *                                    _wi_p7_rsa_description(wi_runtime_instance_t *); 
    5252 
     53static wi_data_t *                                              _wi_p7_rsa_public_key_data(wi_p7_rsa_t *); 
     54 
    5355static wi_runtime_id_t                                  _wi_p7_rsa_runtime_id = WI_RUNTIME_ID_NULL; 
    5456static wi_runtime_class_t                               _wi_p7_rsa_runtime_class = { 
     
    119121 
    120122 
    121 wi_p7_rsa_t * wi_p7_rsa_init_with_size(wi_p7_rsa_t *p7_rsa, wi_uinteger_t size) { 
     123wi_p7_rsa_t * wi_p7_rsa_init_with_bits(wi_p7_rsa_t *p7_rsa, wi_uinteger_t size) { 
    122124        p7_rsa->rsa = RSA_generate_key(size, RSA_F4, NULL, NULL); 
    123125         
     
    128130        } 
    129131         
     132        p7_rsa->public_key_data = wi_retain(_wi_p7_rsa_public_key_data(p7_rsa)); 
     133         
     134        if(!p7_rsa->public_key_data) { 
     135                wi_release(p7_rsa); 
     136 
     137                return NULL; 
     138        } 
     139         
    130140        return p7_rsa; 
    131141} 
     
    134144 
    135145wi_p7_rsa_t * wi_p7_rsa_init_with_pem_file(wi_p7_rsa_t *p7_rsa, wi_string_t *path) { 
    136         unsigned char   *buffer; 
    137         int                             length; 
    138         FILE                    *fp; 
     146        FILE            *fp; 
    139147         
    140148        fp = fopen(wi_string_cstring(path), "r"); 
     
    150158        p7_rsa->rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); 
    151159         
     160        fclose(fp); 
     161         
    152162        if(!p7_rsa->rsa) { 
    153163                wi_error_set_openssl_error(); 
     
    158168        } 
    159169         
    160         buffer = NULL; 
    161         length = i2d_RSA_PUBKEY(p7_rsa->rsa, &buffer); 
    162          
    163         if(length <= 0) { 
    164                 wi_error_set_openssl_error(); 
    165                  
     170        p7_rsa->public_key_data = wi_retain(_wi_p7_rsa_public_key_data(p7_rsa)); 
     171         
     172        if(!p7_rsa->public_key_data) { 
    166173                wi_release(p7_rsa); 
    167174 
    168175                return NULL; 
    169176        } 
    170          
    171         p7_rsa->public_key_data = wi_data_init_with_bytes(wi_data_alloc(), buffer, length); 
    172  
    173         OPENSSL_free(buffer); 
    174177         
    175178        return p7_rsa; 
     
    225228#pragma mark - 
    226229 
     230static wi_data_t * _wi_p7_rsa_public_key_data(wi_p7_rsa_t *p7_rsa) { 
     231        wi_data_t               *data; 
     232        unsigned char   *buffer; 
     233        int                             length; 
     234 
     235        buffer = NULL; 
     236        length = i2d_RSA_PUBKEY(p7_rsa->rsa, &buffer); 
     237         
     238        if(length <= 0) { 
     239                wi_error_set_openssl_error(); 
     240                 
     241                return NULL; 
     242        } 
     243         
     244        data = wi_data_with_bytes(buffer, length); 
     245 
     246        OPENSSL_free(buffer); 
     247         
     248        return data; 
     249} 
     250 
     251 
     252 
     253#pragma mark - 
    227254 
    228255wi_data_t * wi_p7_rsa_public_key_data(wi_p7_rsa_t *p7_rsa) { 
     
    429456        wi_p7_cipher_t          *p7_cipher = instance; 
    430457         
    431         return wi_string_with_format(WI_STR("<%@ %p>{bits = %u}"), 
     458        return wi_string_with_format(WI_STR("<%@ %p>{name = %@, bits = %u}"), 
    432459        wi_runtime_class_name(p7_cipher), 
    433460                p7_cipher, 
    434                 EVP_CIPHER_key_length(&p7_cipher->cipher_ctx) * 8); 
     461                wi_p7_cipher_name(p7_cipher), 
     462                wi_p7_cipher_bits(p7_cipher)); 
    435463} 
    436464 
     
    474502#pragma mark - 
    475503 
     504wi_string_t * wi_p7_cipher_name(wi_p7_cipher_t *p7_cipher) { 
     505        return wi_string_with_cstring(EVP_CIPHER_name(p7_cipher->cipher)); 
     506} 
     507 
     508 
     509 
     510wi_uinteger_t wi_p7_cipher_bits(wi_p7_cipher_t *p7_cipher) { 
     511        return EVP_CIPHER_key_length(&p7_cipher->cipher_ctx) * 8; 
     512} 
     513 
     514 
     515 
     516#pragma mark - 
     517 
    476518wi_boolean_t wi_p7_cipher_encrypt_bytes(wi_p7_cipher_t *p7_cipher, const void *decrypted_buffer, wi_uinteger_t decrypted_length, void **out_buffer, wi_uinteger_t *out_length) { 
    477519        void                    *encrypted_buffer; 
  • libwired/trunk/libwired/p7/wi-p7-crypto.h

    r4627 r4629  
    4949 
    5050WI_EXPORT wi_p7_rsa_t *                                 wi_p7_rsa_alloc(void); 
    51 WI_EXPORT wi_p7_rsa_t *                                 wi_p7_rsa_init_with_size(wi_p7_rsa_t *, wi_uinteger_t); 
     51WI_EXPORT wi_p7_rsa_t *                                 wi_p7_rsa_init_with_bits(wi_p7_rsa_t *, wi_uinteger_t); 
    5252WI_EXPORT wi_p7_rsa_t *                                 wi_p7_rsa_init_with_pem_file(wi_p7_rsa_t *, wi_string_t *); 
    5353WI_EXPORT wi_p7_rsa_t *                                 wi_p7_rsa_init_with_public_key_data(wi_p7_rsa_t *, wi_data_t *); 
     
    7070WI_EXPORT wi_data_t *                                   wi_p7_cipher_iv_data(wi_p7_cipher_t *); 
    7171 
     72WI_EXPORT wi_string_t *                                 wi_p7_cipher_name(wi_p7_cipher_t *); 
     73WI_EXPORT wi_uinteger_t                                 wi_p7_cipher_bits(wi_p7_cipher_t *); 
     74 
    7275WI_EXPORT wi_boolean_t                                  wi_p7_cipher_encrypt_bytes(wi_p7_cipher_t *, const void *, wi_uinteger_t, void **, wi_uinteger_t *); 
    7376WI_EXPORT wi_data_t *                                   wi_p7_cipher_encrypt_data(wi_p7_cipher_t *, wi_data_t *); 
     
    7578WI_EXPORT wi_data_t *                                   wi_p7_cipher_decrypt_data(wi_p7_cipher_t *, wi_data_t *); 
    7679 
    77 #endif /* WI_ARRAY_H */ 
     80#endif /* WI_P7_CRYPTO_H */ 
  • libwired/trunk/libwired/p7/wi-p7-message.h

    r4623 r4629  
    110110WI_EXPORT wi_date_t *                           wi_p7_message_date_for_name(wi_p7_message_t *, wi_string_t *); 
    111111 
    112 #endif /* WI_ARRAY_H */ 
     112#endif /* WI_P7_MESSAGE_H */ 
  • libwired/trunk/libwired/p7/wi-p7-private.h

    r4623 r4629  
    6666WI_EXPORT wi_integer_t                          wi_p7_xml_integer_for_attribute(xmlNodePtr, wi_string_t *); 
    6767 
    68 #endif /* WI_ARRAY_H */ 
     68#endif /* WI_P7_PRIVATE_H */ 
  • libwired/trunk/libwired/p7/wi-p7-socket.c

    r4626 r4629  
    218218 
    219219 
     220wi_p7_cipher_t * wi_p7_socket_cipher(wi_p7_socket_t *p7_socket) { 
     221        return p7_socket->cipher; 
     222} 
     223 
     224 
     225 
    220226wi_p7_options_t wi_p7_socket_options(wi_p7_socket_t *p7_socket) { 
    221227        return p7_socket->options; 
     
    240246        p7_message = wi_p7_message_with_name(WI_STR("p7.handshake"), p7_socket); 
    241247         
    242         if(!p7_message) 
    243                 return false; 
     248        if(!p7_message) { 
     249                wi_log_info(WI_STR("couldn't create message")); 
     250 
     251                return false; 
     252        } 
    244253 
    245254        wi_p7_message_set_uint32_for_name(p7_message, WI_P7_VERSION, WI_STR("p7.handshake.version")); 
     
    308317        p7_message = wi_p7_message_with_name(WI_STR("p7.handshake.acknowledge"), p7_socket); 
    309318         
    310         if(!p7_message) 
    311                 return false; 
     319        if(!p7_message) { 
     320                wi_log_info(WI_STR("couldn't create message")); 
     321                 
     322                return false; 
     323        } 
    312324         
    313325        if(p7_socket->local_compatibility_check) 
     
    378390        p7_message = wi_p7_message_with_name(WI_STR("p7.handshake.reply"), p7_socket); 
    379391 
    380         if(!p7_message) 
    381                 return false; 
     392        if(!p7_message) { 
     393                wi_log_info(WI_STR("couldn't create message")); 
     394                 
     395                return false; 
     396        } 
    382397         
    383398        wi_p7_message_set_uint32_for_name(p7_message, WI_P7_VERSION, WI_STR("p7.handshake.version")); 
     
    430445        p7_message = wi_p7_socket_read_message(p7_socket, timeout); 
    431446         
    432         if(!p7_message) 
    433                 return false; 
     447        if(!p7_message) { 
     448                wi_log_warn(WI_STR("couldn't read message")); 
     449 
     450                return false; 
     451        } 
    434452         
    435453        if(!wi_is_equal(p7_message->name, WI_STR("p7.encryption"))) { 
     
    467485        p7_message = wi_p7_message_with_name(WI_STR("p7.encryption.reply"), p7_socket); 
    468486 
    469         if(!p7_message) 
    470                 return false; 
     487        if(!p7_message) { 
     488                wi_log_info(WI_STR("couldn't create message")); 
     489 
     490                return false; 
     491        } 
    471492         
    472493        wi_p7_message_set_data_for_name(p7_message, wi_p7_cipher_key_data(p7_socket->cipher), WI_STR("p7.encryption.cipher_key")); 
     
    496517        wi_p7_message_set_data_for_name(p7_message, data, WI_STR("p7.encryption.client_password")); 
    497518         
    498         if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) 
    499                 return false; 
     519        if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) { 
     520                wi_log_warn(WI_STR("couldn't write message")); 
     521 
     522                return false; 
     523        } 
    500524 
    501525        p7_message = wi_p7_socket_read_message(p7_socket, timeout); 
    502526         
    503         if(!p7_message) 
    504                 return false; 
     527        if(!p7_message) { 
     528                wi_log_warn(WI_STR("couldn't read message")); 
     529                 
     530                return false; 
     531        } 
    505532         
    506533        if(!wi_is_equal(p7_message->name, WI_STR("p7.encryption.acknowledge"))) { 
     
    554581        rsa_data = wi_p7_rsa_public_key_data(p7_socket->rsa); 
    555582         
    556         if(!rsa_data) 
    557                 return false; 
     583        wi_log_info(WI_STR("rsa_data = %@"), rsa_data); 
    558584 
    559585        p7_message = wi_p7_message_with_name(WI_STR("p7.encryption"), p7_socket); 
    560586 
    561         if(!p7_message) 
    562                 return false; 
     587        if(!p7_message) { 
     588                wi_log_info(WI_STR("couldn't create message")); 
     589 
     590                return false; 
     591        } 
    563592         
    564593        wi_p7_message_set_data_for_name(p7_message, rsa_data, WI_STR("p7.encryption.envelope_key")); 
    565594         
    566         if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) 
    567                 return false; 
     595        if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) { 
     596                wi_log_warn(WI_STR("couldn't write message")); 
     597         
     598                return false; 
     599        } 
    568600         
    569601        p7_message = wi_p7_socket_read_message(p7_socket, timeout); 
    570602         
    571         if(!p7_message) 
    572                 return false; 
     603        if(!p7_message) { 
     604                wi_log_info(WI_STR("couldn't create message")); 
     605 
     606                return false; 
     607        } 
    573608         
    574609        if(!wi_is_equal(p7_message->name, WI_STR("p7.encryption.reply"))) { 
     
    593628                                                                                                                   iv_data); 
    594629 
    595         if(!p7_socket->cipher) 
    596                 return false; 
     630        if(!p7_socket->cipher) { 
     631                wi_log_warn(WI_STR("couldn't create cipher")); 
     632         
     633                return false; 
     634        } 
    597635         
    598636        data = wi_p7_message_data_for_name(p7_message, WI_STR("p7.encryption.username")); 
     
    606644        data = wi_p7_rsa_private_decrypt_data(p7_socket->rsa, data); 
    607645         
    608         if(!data) 
    609                 return false; 
     646        if(!data) { 
     647                wi_log_warn(WI_STR("couldn't rsa decrypt")); 
     648         
     649                return false; 
     650        } 
    610651         
    611652        username = wi_string_with_data(data); 
     
    621662        data = wi_p7_rsa_private_decrypt_data(p7_socket->rsa, data); 
    622663         
    623         if(!data) 
    624                 return false; 
     664        if(!data) { 
     665                wi_log_warn(WI_STR("couldn't rsa decrypt")); 
     666         
     667                return false; 
     668        } 
    625669 
    626670        client_password = wi_string_with_data(data); 
     
    649693        p7_message = wi_p7_message_with_name(WI_STR("p7.encryption.acknowledge"), p7_socket); 
    650694         
    651         if(!p7_message) 
    652                 return false; 
     695        if(!p7_message) { 
     696                wi_log_info(WI_STR("couldn't create message")); 
     697 
     698                return false; 
     699        } 
    653700         
    654701        data = wi_p7_cipher_encrypt_data(p7_socket->cipher, wi_string_data(server_password2)); 
    655702         
    656         wi_log_info(WI_STR("crypted %@ with %@"), data, p7_socket->cipher); 
    657          
    658         if(!data) 
    659                 return false; 
     703        if(!data) { 
     704                wi_log_warn(WI_STR("couldn't cipher encrypt")); 
     705         
     706                return false; 
     707        } 
    660708 
    661709        wi_p7_message_set_data_for_name(p7_message, data, WI_STR("p7.encryption.server_password")); 
    662710 
    663         if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) 
    664                 return false; 
     711        if(!wi_p7_socket_write_message(p7_socket, timeout, p7_message)) { 
     712                wi_log_warn(WI_STR("couldn't write message")); 
     713         
     714                return false; 
     715        } 
    665716 
    666717        p7_socket->encryption_enabled = true; 
     
    677728        p7_message = wi_p7_message_with_name(WI_STR("p7.compatibility_check.specification"), p7_socket); 
    678729         
    679         if(!p7_message) 
    680                 return false; 
     730        if(!p7_message) { 
     731                wi_log_info(WI_STR("couldn't create message")); 
     732 
     733                return false; 
     734        } 
    681735         
    682736        wi_p7_message_set_string_for_name(p7_message, wi_p7_spec_xml(p7_socket->spec), WI_STR("p7.compatibility_check.specification")); 
     
    754808        p7_message = wi_p7_message_with_name(WI_STR("p7.compatibility_check.status"), p7_socket); 
    755809         
    756         if(!p7_message) 
    757                 return false; 
     810        if(!p7_message) { 
     811                wi_log_info(WI_STR("couldn't create message")); 
     812                 
     813                return false; 
     814        } 
    758815         
    759816        wi_p7_message_set_bool_for_name(p7_message, compatible, WI_STR("p7.compatibility_check.status")); 
     
    11211178                                prefix = WI_STR("<?xm"); 
    11221179                        } 
    1123                         else if(length == _WI_P7_SOCKET_BINARY_MAGIC_LENGTH) { 
     1180                        else if(length <= _WI_P7_SOCKET_BINARY_MAGIC_LENGTH) { 
    11241181                                p7_socket->serialization = WI_P7_BINARY; 
    11251182                        } 
     
    11311188        else if(p7_socket->serialization == WI_P7_XML) 
    11321189                p7_message = _wi_p7_socket_read_xml_message(p7_socket, timeout, prefix); 
    1133         else 
    1134                 p7_message = NULL; 
    1135  
    1136         if(!p7_message) 
     1190        else { 
     1191                wi_log_info(WI_STR("unknown serialization")); 
     1192                 
    11371193                return NULL; 
     1194        } 
     1195 
     1196        if(!p7_message) { 
     1197                wi_log_info(WI_STR("unable to extract message")); 
     1198                 
     1199                return NULL; 
     1200        } 
    11381201         
    11391202        wi_p7_message_deserialize(p7_message); 
  • libwired/trunk/libwired/p7/wi-p7-socket.h

    r4623 r4629  
    6565WI_EXPORT wi_socket_t *                                                         wi_p7_socket_socket(wi_p7_socket_t *); 
    6666WI_EXPORT wi_p7_spec_t *                                                        wi_p7_socket_spec(wi_p7_socket_t *); 
     67WI_EXPORT wi_p7_cipher_t *                                                      wi_p7_socket_cipher(wi_p7_socket_t *); 
    6768WI_EXPORT wi_p7_options_t                                                       wi_p7_socket_options(wi_p7_socket_t *); 
    6869WI_EXPORT wi_p7_serialization_t                                         wi_p7_socket_serialization(wi_p7_socket_t *); 
     
    7879WI_EXPORT wi_p7_socket_password_provider_func_t         *wi_p7_socket_password_provider; 
    7980 
    80 #endif /* WI_ARRAY_H */ 
     81#endif /* WI_P7_SOCKET_H */ 
  • libwired/trunk/libwired/p7/wi-p7-spec.c

    r4623 r4629  
    217217 
    218218 
     219#define _WI_P7_SPEC_REPLY_ONE_OR_ZERO           -1 
     220#define _WI_P7_SPEC_REPLY_ZERO_OR_MORE          -2 
     221#define _WI_P7_SPEC_REPLY_ONE_OR_MORE           -3 
     222 
    219223struct _wi_p7_spec_reply { 
    220224        wi_runtime_base_t                                               base; 
     
    226230 
    227231static _wi_p7_spec_reply_t *                            _wi_p7_spec_reply_with_node(wi_p7_spec_t *, xmlNodePtr, _wi_p7_spec_transaction_t *); 
     232static wi_string_t *                                            _wi_p7_spec_reply_count(_wi_p7_spec_reply_t *); 
    228233static void                                                                     _wi_p7_spec_reply_dealloc(wi_runtime_instance_t *); 
    229234static wi_string_t *                                            _wi_p7_spec_reply_description(wi_runtime_instance_t *); 
     
    273278static wi_boolean_t                                                     _wi_p7_spec_transaction_is_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_transaction_t *); 
    274279static wi_boolean_t                                                     _wi_p7_spec_andor_is_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_andor_t *, _wi_p7_spec_andor_t *); 
    275 static wi_boolean_t                                                     _wi_p7_spec_reply_is_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_reply_t *, _wi_p7_spec_reply_t *); 
     280static wi_boolean_t                                                     _wi_p7_spec_replies_are_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_andor_t *, _wi_p7_spec_andor_t *, wi_boolean_t); 
     281static wi_boolean_t                                                     _wi_p7_spec_reply_is_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_reply_t *, _wi_p7_spec_reply_t *, wi_boolean_t); 
    276282static wi_boolean_t                                                     _wi_p7_spec_message_is_compatible(wi_p7_spec_t *, _wi_p7_spec_transaction_t *, _wi_p7_spec_message_t *, _wi_p7_spec_message_t *); 
    277283 
     
    868874        wi_boolean_t    compatible; 
    869875         
    870         compatible = (_wi_p7_spec_is_compatible(p7_spec, other_p7_spec) && _wi_p7_spec_is_compatible(other_p7_spec, p7_spec)); 
     876        compatible = _wi_p7_spec_is_compatible(p7_spec, other_p7_spec); 
    871877         
    872878        if(compatible) 
     
    914920         
    915921        if(other_transaction) { 
    916                 if(!_wi_p7_spec_message_is_compatible(p7_spec, transaction, transaction->message, other_transaction->message)) 
    917                         return false; 
    918                  
    919922                if(transaction->originator != other_transaction->originator) { 
    920923                        _wi_p7_spec_log_debug(p7_spec, WI_STR("Transaction \"%@\" should be sent by %@, but peer sends it by %@"), 
     
    926929                } 
    927930                 
     931                if(!_wi_p7_spec_message_is_compatible(p7_spec, transaction, transaction->message, other_transaction->message)) 
     932                        return false; 
     933                 
    928934                if(!_wi_p7_spec_andor_is_compatible(p7_spec, transaction, transaction->andor, other_transaction->andor)) 
    929935                        return false; 
     
    936942 
    937943static wi_boolean_t _wi_p7_spec_andor_is_compatible(wi_p7_spec_t *p7_spec, _wi_p7_spec_transaction_t *transaction, _wi_p7_spec_andor_t *andor, _wi_p7_spec_andor_t *other_andor) { 
    938         wi_enumerator_t                                 *enumerator; 
    939         _wi_p7_spec_reply_t                             *reply, *other_reply, *each_reply; 
    940         wi_uinteger_t                                   i, count, other_count, index; 
     944        wi_uinteger_t           i, count, other_count; 
     945         
     946        if(andor->type != other_andor->type) 
     947                return false; 
     948         
     949        if(!_wi_p7_spec_replies_are_compatible(p7_spec, transaction, andor, other_andor, false) || 
     950           !_wi_p7_spec_replies_are_compatible(p7_spec, transaction, other_andor, andor, true)) 
     951                return false; 
     952         
     953        count = wi_array_count(andor->children); 
     954        other_count = wi_array_count(other_andor->children); 
     955         
     956        if(count != other_count) { 
     957                _wi_p7_spec_log_debug(p7_spec, WI_STR("Transaction \"%@\" should have %u %@, but peer has %u"), 
     958                        transaction->message->name, 
     959                        count, 
     960                        count == 1 
     961                                ? WI_STR("child") 
     962                                : WI_STR("children"), 
     963                        other_count); 
     964                 
     965                return false; 
     966        } 
     967         
     968        for(i = 0; i < count; i++) { 
     969                if(!_wi_p7_spec_andor_is_compatible(p7_spec, transaction, WI_ARRAY(andor->children, i), WI_ARRAY(other_andor->children, i))) 
     970                        return false; 
     971        } 
     972         
     973        return true; 
     974
     975 
     976 
     977 
     978static wi_boolean_t _wi_p7_spec_replies_are_compatible(wi_p7_spec_t *p7_spec, _wi_p7_spec_transaction_t *transaction, _wi_p7_spec_andor_t *andor, _wi_p7_spec_andor_t *other_andor, wi_boolean_t commutativity) { 
     979        wi_enumerator_t                 *enumerator; 
     980        _wi_p7_spec_reply_t             *reply, *other_reply, *each_reply; 
     981        wi_uinteger_t                   i, count, index; 
    941982         
    942983        if(andor->type != other_andor->type) 
     
    9631004                        index = i + 1; 
    9641005                         
    965                         if(other_reply && !_wi_p7_spec_reply_is_compatible(p7_spec, transaction, reply, other_reply)) 
     1006                        if(!_wi_p7_spec_reply_is_compatible(p7_spec, transaction, reply, other_reply, commutativity)) 
    9661007                                return false; 
    9671008                } else { 
    9681009                        other_reply = wi_hash_data_for_key(other_andor->replies_hash, reply->message->name); 
    9691010                         
    970                         if(!_wi_p7_spec_reply_is_compatible(p7_spec, transaction, reply, other_reply)) 
     1011                        if(!_wi_p7_spec_reply_is_compatible(p7_spec, transaction, reply, other_reply, commutativity)) 
    9711012                                return false; 
    9721013                } 
    9731014        } 
    9741015         
    975         count = wi_array_count(andor->children); 
    976         other_count = wi_array_count(other_andor->children); 
    977          
    978         if(count != other_count) { 
    979                 _wi_p7_spec_log_debug(p7_spec, WI_STR("Transaction \"%@\" should have %u %@, but peer has %u"), 
    980                         transaction->message->name, 
    981                         count, 
    982                         count == 1 
    983                                 ? WI_STR("child") 
    984                                 : WI_STR("children"), 
    985                         other_count); 
    986                  
    987                 return false; 
    988         } 
    989          
    990         for(i = 0; i < count; i++) { 
    991                 if(!_wi_p7_spec_andor_is_compatible(p7_spec, transaction, WI_ARRAY(andor->children, i), WI_ARRAY(other_andor->children, i))) 
    992                         return false; 
    993         } 
    994          
    9951016        return true; 
    9961017} 
     
    9981019 
    9991020 
    1000 static wi_boolean_t _wi_p7_spec_reply_is_compatible(wi_p7_spec_t *p7_spec, _wi_p7_spec_transaction_t *transaction, _wi_p7_spec_reply_t *reply, _wi_p7_spec_reply_t *other_reply) { 
     1021static wi_boolean_t _wi_p7_spec_reply_is_compatible(wi_p7_spec_t *p7_spec, _wi_p7_spec_transaction_t *transaction, _wi_p7_spec_reply_t *reply, _wi_p7_spec_reply_t *other_reply, wi_boolean_t commutativity) { 
     1022        wi_boolean_t    compatible; 
     1023         
    10011024        if(reply->required) { 
    10021025                if(!other_reply || !other_reply->required) { 
     
    10131036        } 
    10141037         
    1015         if(other_reply) { 
    1016                 if(reply->count != other_reply->count) { 
    1017                         _wi_p7_spec_log_debug(p7_spec, WI_STR("Reply \"%@\" in transaction \"%@\" should be sent %u %@, but peer sends it %u %@"), 
    1018                                 reply->message->name, 
    1019                                 reply->count, 
    1020                                 reply->count == 1 
    1021                                         ? WI_STR("time") 
    1022                                         : WI_STR("times"), 
    1023                                 other_reply->count, 
    1024                                 other_reply->count == 1 
    1025                                         ? WI_STR("time") 
    1026                                         : WI_STR("times")); 
    1027                          
    1028                         return false; 
    1029                 } 
    1030                  
    1031                 if(!_wi_p7_spec_message_is_compatible(p7_spec, transaction, reply->message, other_reply->message)) 
    1032                         return false; 
     1038        if(!commutativity) { 
     1039                if(other_reply) { 
     1040                        if(reply->count == _WI_P7_SPEC_REPLY_ONE_OR_ZERO) 
     1041                                compatible = (other_reply->count == _WI_P7_SPEC_REPLY_ONE_OR_ZERO); 
     1042                        else if(reply->count == _WI_P7_SPEC_REPLY_ZERO_OR_MORE) 
     1043                                compatible = (other_reply->count == _WI_P7_SPEC_REPLY_ONE_OR_ZERO || other_reply->count == _WI_P7_SPEC_REPLY_ZERO_OR_MORE); 
     1044                        else if(reply->count == _WI_P7_SPEC_REPLY_ONE_OR_MORE) 
     1045                                compatible = (other_reply->count == _WI_P7_SPEC_REPLY_ONE_OR_MORE || other_reply->count > 0); 
     1046                        else 
     1047                                compatible = (reply->count == other_reply->count); 
     1048                         
     1049                        if(!compatible) { 
     1050                                _wi_p7_spec_log_debug(p7_spec, WI_STR("Reply \"%@\" in transaction \"%@\" should be sent %@, but peer sends it %@"), 
     1051                                        reply->message->name, 
     1052                                        transaction->message->name, 
     1053                                        _wi_p7_spec_reply_count(reply), 
     1054                                        _wi_p7_spec_reply_count(other_reply)); 
     1055                                 
     1056                                return false; 
     1057                        } 
     1058                         
     1059                        if(!_wi_p7_spec_message_is_compatible(p7_spec, transaction, reply->message, other_reply->message)) 
     1060                                return false; 
     1061                } 
    10331062        } 
    10341063         
     
    10431072        _wi_p7_spec_parameter_t *parameter, *other_parameter; 
    10441073        _wi_p7_spec_field_t             *field, *other_field; 
     1074         
     1075        if(!wi_is_equal(message->name, other_message->name)) { 
     1076                _wi_p7_spec_log_debug(p7_spec, 
     1077                        WI_STR("Reply in transaction \"%@\" should be \"%@\", but peer has \"%@\""), 
     1078                                transaction->message->name, message->name, other_message->name); 
     1079                 
     1080                return false; 
     1081        } 
    10451082         
    10461083        if(message->id != other_message->id) { 
     
    17891826static _wi_p7_spec_reply_t * _wi_p7_spec_reply_with_node(wi_p7_spec_t *p7_spec, xmlNodePtr node, _wi_p7_spec_transaction_t *transaction) { 
    17901827        _wi_p7_spec_reply_t             *reply; 
    1791         wi_string_t                             *message, *use
     1828        wi_string_t                             *message, *use, *count
    17921829 
    17931830    reply = wi_autorelease(wi_runtime_create_instance(_wi_p7_spec_reply_runtime_id, sizeof(_wi_p7_spec_reply_t))); 
     
    18281865                reply->required = (wi_string_case_insensitive_compare(use, WI_STR("required")) == 0); 
    18291866        } 
    1830  
    1831         reply->count = wi_p7_xml_integer_for_attribute(node, WI_STR("count")); 
     1867         
     1868        count = wi_p7_xml_string_for_attribute(node, WI_STR("count")); 
     1869         
     1870        if(!count) { 
     1871                _wi_p7_spec_log_debug(p7_spec, WI_STR("Reply in transaction \"%@\" has no \"count\""), 
     1872                        transaction->message->name); 
     1873                 
     1874                return NULL; 
     1875        } 
     1876         
     1877        if(wi_string_compare(count, WI_STR("?")) == 0) 
     1878                reply->count = _WI_P7_SPEC_REPLY_ONE_OR_ZERO; 
     1879        else if(wi_string_compare(count, WI_STR("*")) == 0) 
     1880                reply->count = _WI_P7_SPEC_REPLY_ZERO_OR_MORE; 
     1881        else if(wi_string_compare(count, WI_STR("+")) == 0) 
     1882                reply->count = _WI_P7_SPEC_REPLY_ONE_OR_MORE; 
     1883        else 
     1884                reply->count = wi_string_integer(count); 
     1885         
     1886        if(reply->count == 0) { 
     1887                _wi_p7_spec_log_debug(p7_spec, WI_STR("Reply in transaction \"%@\" has an invalid \"count\" (\"%@\")"), 
     1888                        transaction->message->name, count); 
     1889                 
     1890                return NULL; 
     1891        } 
    18321892 
    18331893        return reply; 
     1894} 
     1895 
     1896 
     1897 
     1898static wi_string_t * _wi_p7_spec_reply_count(_wi_p7_spec_reply_t *reply) { 
     1899        if(reply->count == _WI_P7_SPEC_REPLY_ONE_OR_ZERO) 
     1900                return WI_STR("one or zero times"); 
     1901        if(reply->count == _WI_P7_SPEC_REPLY_ZERO_OR_MORE) 
     1902                return WI_STR("zero or more times"); 
     1903        else if(reply->count == _WI_P7_SPEC_REPLY_ONE_OR_MORE) 
     1904                return WI_STR("one or more times"); 
     1905 
     1906        return wi_string_with_format(WI_STR("%u %@"), reply->count, (reply->count == 1) ? WI_STR("time") : WI_STR("times")); 
    18341907} 
    18351908 
  • libwired/trunk/libwired/p7/wi-p7-spec.h

    r4623 r4629  
    6262WI_EXPORT wi_p7_enum_t                                  wi_p7_spec_enum_value(wi_p7_spec_t *, wi_integer_t, wi_string_t *); 
    6363 
    64 #endif /* WI_ARRAY_H */ 
     64#endif /* WI_P7_SPEC_H */