Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Files at this revision

API Documentation at this revision

Comitter:
AzureIoTClient
Date:
Wed Nov 16 21:38:39 2016 -0800
Parent:
14:b7e6599cacf5
Child:
16:18e7ebd42bb2
Commit message:
1.0.10

Changed in this revision

azure_c_shared_utility/macro_utils.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/refcount.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/sastoken.h Show annotated file Show diff for this revision Revisions of this file
httpapi_compact.c Show annotated file Show diff for this revision Revisions of this file
sastoken.c Show annotated file Show diff for this revision Revisions of this file
sha1.c Show annotated file Show diff for this revision Revisions of this file
sha224.c Show annotated file Show diff for this revision Revisions of this file
sha384-512.c Show annotated file Show diff for this revision Revisions of this file
tlsio_wolfssl.c Show annotated file Show diff for this revision Revisions of this file
--- a/azure_c_shared_utility/macro_utils.h	Fri Oct 21 22:11:02 2016 +0000
+++ b/azure_c_shared_utility/macro_utils.h	Wed Nov 16 21:38:39 2016 -0800
@@ -5356,6 +5356,256 @@
 FOR_EACH_2_122(X, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124)
 
 
+#define FOR_EACH_2_REVERSE_0(...)
+
+#define FOR_EACH_2_REVERSE_2(X, P1, P2) \
+X(P1, P2)
+
+#define FOR_EACH_2_REVERSE_4(X, P1, P2, P3, P4) \
+X(P3, P4) \
+FOR_EACH_2_REVERSE_2(X, P1, P2)
+
+#define FOR_EACH_2_REVERSE_6(X, P1, P2, P3, P4, P5, P6) \
+X(P5, P6) \
+FOR_EACH_2_REVERSE_4(X, P1, P2, P3, P4)
+
+#define FOR_EACH_2_REVERSE_8(X, P1, P2, P3, P4, P5, P6, P7, P8) \
+X(P7, P8) \
+FOR_EACH_2_REVERSE_6(X, P1, P2, P3, P4, P5, P6)
+
+#define FOR_EACH_2_REVERSE_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) \
+X(P9, P10) \
+FOR_EACH_2_REVERSE_8(X, P1, P2, P3, P4, P5, P6, P7, P8)
+
+#define FOR_EACH_2_REVERSE_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12) \
+X(P11, P12) \
+FOR_EACH_2_REVERSE_10(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)
+
+#define FOR_EACH_2_REVERSE_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14) \
+X(P13, P14) \
+FOR_EACH_2_REVERSE_12(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)
+
+#define FOR_EACH_2_REVERSE_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16) \
+X(P15, P16) \
+FOR_EACH_2_REVERSE_14(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)
+
+#define FOR_EACH_2_REVERSE_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18) \
+X(P17, P18) \
+FOR_EACH_2_REVERSE_16(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16)
+
+#define FOR_EACH_2_REVERSE_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20) \
+X(P19, P20) \
+FOR_EACH_2_REVERSE_18(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18)
+
+#define FOR_EACH_2_REVERSE_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22) \
+X(P21, P22) \
+FOR_EACH_2_REVERSE_20(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20)
+
+#define FOR_EACH_2_REVERSE_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24) \
+X(P23, P24) \
+FOR_EACH_2_REVERSE_22(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22)
+
+#define FOR_EACH_2_REVERSE_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26) \
+X(P25, P26) \
+FOR_EACH_2_REVERSE_24(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24)
+
+#define FOR_EACH_2_REVERSE_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28) \
+X(P27, P28) \
+FOR_EACH_2_REVERSE_26(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26)
+
+#define FOR_EACH_2_REVERSE_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30) \
+X(P29, P30) \
+FOR_EACH_2_REVERSE_28(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28)
+
+#define FOR_EACH_2_REVERSE_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32) \
+X(P31, P32) \
+FOR_EACH_2_REVERSE_30(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30)
+
+#define FOR_EACH_2_REVERSE_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34) \
+X(P33, P34) \
+FOR_EACH_2_REVERSE_32(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32)
+
+#define FOR_EACH_2_REVERSE_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36) \
+X(P35, P36) \
+FOR_EACH_2_REVERSE_34(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34)
+
+#define FOR_EACH_2_REVERSE_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38) \
+X(P37, P38) \
+FOR_EACH_2_REVERSE_36(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36)
+
+#define FOR_EACH_2_REVERSE_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40) \
+X(P39, P40) \
+FOR_EACH_2_REVERSE_38(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38)
+
+#define FOR_EACH_2_REVERSE_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42) \
+X(P41, P42) \
+FOR_EACH_2_REVERSE_40(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40)
+
+#define FOR_EACH_2_REVERSE_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44) \
+X(P43, P44) \
+FOR_EACH_2_REVERSE_42(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42)
+
+#define FOR_EACH_2_REVERSE_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46) \
+X(P45, P46) \
+FOR_EACH_2_REVERSE_44(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44)
+
+#define FOR_EACH_2_REVERSE_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48) \
+X(P47, P48) \
+FOR_EACH_2_REVERSE_46(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46)
+
+#define FOR_EACH_2_REVERSE_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50) \
+X(P49, P50) \
+FOR_EACH_2_REVERSE_48(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48)
+
+#define FOR_EACH_2_REVERSE_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52) \
+X(P51, P52) \
+FOR_EACH_2_REVERSE_50(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50)
+
+#define FOR_EACH_2_REVERSE_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54) \
+X(P53, P54) \
+FOR_EACH_2_REVERSE_52(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52)
+
+#define FOR_EACH_2_REVERSE_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56) \
+X(P55, P56) \
+FOR_EACH_2_REVERSE_54(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54)
+
+#define FOR_EACH_2_REVERSE_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58) \
+X(P57, P58) \
+FOR_EACH_2_REVERSE_56(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56)
+
+#define FOR_EACH_2_REVERSE_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60) \
+X(P59, P60) \
+FOR_EACH_2_REVERSE_58(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58)
+
+#define FOR_EACH_2_REVERSE_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62) \
+X(P61, P62) \
+FOR_EACH_2_REVERSE_60(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60)
+
+#define FOR_EACH_2_REVERSE_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64) \
+X(P63, P64) \
+FOR_EACH_2_REVERSE_62(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62)
+
+#define FOR_EACH_2_REVERSE_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66) \
+X(P65, P66) \
+FOR_EACH_2_REVERSE_64(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64)
+
+#define FOR_EACH_2_REVERSE_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68) \
+X(P67, P68) \
+FOR_EACH_2_REVERSE_66(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66)
+
+#define FOR_EACH_2_REVERSE_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70) \
+X(P69, P70) \
+FOR_EACH_2_REVERSE_68(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68)
+
+#define FOR_EACH_2_REVERSE_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72) \
+X(P71, P72) \
+FOR_EACH_2_REVERSE_70(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70)
+
+#define FOR_EACH_2_REVERSE_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74) \
+X(P73, P74) \
+FOR_EACH_2_REVERSE_72(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72)
+
+#define FOR_EACH_2_REVERSE_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76) \
+X(P75, P76) \
+FOR_EACH_2_REVERSE_74(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74)
+
+#define FOR_EACH_2_REVERSE_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78) \
+X(P77, P78) \
+FOR_EACH_2_REVERSE_76(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76)
+
+#define FOR_EACH_2_REVERSE_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80) \
+X(P79, P80) \
+FOR_EACH_2_REVERSE_78(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78)
+
+#define FOR_EACH_2_REVERSE_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82) \
+X(P81, P82) \
+FOR_EACH_2_REVERSE_80(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80)
+
+#define FOR_EACH_2_REVERSE_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84) \
+X(P83, P84) \
+FOR_EACH_2_REVERSE_82(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82)
+
+#define FOR_EACH_2_REVERSE_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86) \
+X(P85, P86) \
+FOR_EACH_2_REVERSE_84(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84)
+
+#define FOR_EACH_2_REVERSE_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88) \
+X(P87, P88) \
+FOR_EACH_2_REVERSE_86(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86)
+
+#define FOR_EACH_2_REVERSE_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90) \
+X(P89, P90) \
+FOR_EACH_2_REVERSE_88(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88)
+
+#define FOR_EACH_2_REVERSE_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92) \
+X(P91, P92) \
+FOR_EACH_2_REVERSE_90(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90)
+
+#define FOR_EACH_2_REVERSE_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94) \
+X(P93, P94) \
+FOR_EACH_2_REVERSE_92(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92)
+
+#define FOR_EACH_2_REVERSE_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96) \
+X(P95, P96) \
+FOR_EACH_2_REVERSE_94(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94)
+
+#define FOR_EACH_2_REVERSE_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98) \
+X(P97, P98) \
+FOR_EACH_2_REVERSE_96(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96)
+
+#define FOR_EACH_2_REVERSE_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100) \
+X(P99, P100) \
+FOR_EACH_2_REVERSE_98(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98)
+
+#define FOR_EACH_2_REVERSE_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102) \
+X(P101, P102) \
+FOR_EACH_2_REVERSE_100(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100)
+
+#define FOR_EACH_2_REVERSE_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104) \
+X(P103, P104) \
+FOR_EACH_2_REVERSE_102(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102)
+
+#define FOR_EACH_2_REVERSE_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106) \
+X(P105, P106) \
+FOR_EACH_2_REVERSE_104(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104)
+
+#define FOR_EACH_2_REVERSE_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108) \
+X(P107, P108) \
+FOR_EACH_2_REVERSE_106(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106)
+
+#define FOR_EACH_2_REVERSE_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110) \
+X(P109, P110) \
+FOR_EACH_2_REVERSE_108(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108)
+
+#define FOR_EACH_2_REVERSE_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112) \
+X(P111, P112) \
+FOR_EACH_2_REVERSE_110(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110)
+
+#define FOR_EACH_2_REVERSE_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114) \
+X(P113, P114) \
+FOR_EACH_2_REVERSE_112(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112)
+
+#define FOR_EACH_2_REVERSE_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116) \
+X(P115, P116) \
+FOR_EACH_2_REVERSE_114(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114)
+
+#define FOR_EACH_2_REVERSE_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118) \
+X(P117, P118) \
+FOR_EACH_2_REVERSE_116(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116)
+
+#define FOR_EACH_2_REVERSE_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120) \
+X(P119, P120) \
+FOR_EACH_2_REVERSE_118(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118)
+
+#define FOR_EACH_2_REVERSE_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122) \
+X(P121, P122) \
+FOR_EACH_2_REVERSE_120(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120)
+
+#define FOR_EACH_2_REVERSE_124(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122, P123, P124) \
+X(P123, P124) \
+FOR_EACH_2_REVERSE_122(X, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, P30, P31, P32, P33, P34, P35, P36, P37, P38, P39, P40, P41, P42, P43, P44, P45, P46, P47, P48, P49, P50, P51, P52, P53, P54, P55, P56, P57, P58, P59, P60, P61, P62, P63, P64, P65, P66, P67, P68, P69, P70, P71, P72, P73, P74, P75, P76, P77, P78, P79, P80, P81, P82, P83, P84, P85, P86, P87, P88, P89, P90, P91, P92, P93, P94, P95, P96, P97, P98, P99, P100, P101, P102, P103, P104, P105, P106, P107, P108, P109, P110, P111, P112, P113, P114, P115, P116, P117, P118, P119, P120, P121, P122)
+
+
 #define FOR_EACH_1_COUNTED_0(...)
 
 #define FOR_EACH_1_COUNTED_1(X, P1) \
@@ -6115,10 +6365,15 @@
 */
 #define FOR_EACH_2_COUNTED(MACRO_TO_INVOKE, ...) C2(FOR_EACH_2_COUNTED_, C1(COUNT_ARG(__VA_ARGS__))) LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
 #define FOR_EACH_1_COUNTED(MACRO_TO_INVOKE, ...) C2(FOR_EACH_1_COUNTED_, C1(COUNT_ARG(__VA_ARGS__))) LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
+
+/*FOR_EACH_2_REVERSE acts just like FOR_EACH_2, but in reverse order. Example:
+FOR_EACH_2_REVERSE(X,a,b,c,d,e,f) => X(e,f) X(c,d) X (a, b) in this order */
+#define FOR_EACH_2_REVERSE(MACRO_TO_INVOKE, ...) C2(FOR_EACH_2_REVERSE_, C1(COUNT_ARG(__VA_ARGS__))) LPAREN MACRO_TO_INVOKE, __VA_ARGS__)
 #else
 #define FOR_EACH_2(MACRO_TO_INVOKE, ...) C2(FOR_EACH_2_, C1(COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE, __VA_ARGS__)
 #define FOR_EACH_2_COUNTED(MACRO_TO_INVOKE, ...) C2(FOR_EACH_2_COUNTED_, C1(COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE,  __VA_ARGS__)
 #define FOR_EACH_1_COUNTED(MACRO_TO_INVOKE, ...) C2(FOR_EACH_1_COUNTED_, C1(COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE,  __VA_ARGS__)
+#define FOR_EACH_2_REVERSE(MACRO_TO_INVOKE, ...) C2(FOR_EACH_2_REVERSE_, C1(COUNT_ARG(__VA_ARGS__))) ( MACRO_TO_INVOKE, __VA_ARGS__)
 #endif
 
 #ifdef _MSC_VER
--- a/azure_c_shared_utility/refcount.h	Fri Oct 21 22:11:02 2016 +0000
+++ b/azure_c_shared_utility/refcount.h	Wed Nov 16 21:38:39 2016 -0800
@@ -31,6 +31,10 @@
 #define REFCOUNT_USE_STD_ATOMIC 1
 #endif
 
+#if defined(ARDUINO_ARCH_SAMD)
+#undef  REFCOUNT_USE_STD_ATOMIC
+#endif
+
 #define REFCOUNT_TYPE(type) \
 struct C2(C2(REFCOUNT_, type), _TAG)
 
--- a/azure_c_shared_utility/sastoken.h	Fri Oct 21 22:11:02 2016 +0000
+++ b/azure_c_shared_utility/sastoken.h	Wed Nov 16 21:38:39 2016 -0800
@@ -5,12 +5,13 @@
 #define SASTOKEN_H
 
 #include "azure_c_shared_utility/strings.h"
+#include <stdbool.h>
 #include "azure_c_shared_utility/umock_c_prod.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
-
+    MOCKABLE_FUNCTION(, bool, SASToken_Validate, STRING_HANDLE, sasToken);
     MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry);
 
 #ifdef __cplusplus
--- a/httpapi_compact.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/httpapi_compact.c	Wed Nov 16 21:38:39 2016 -0800
@@ -16,10 +16,11 @@
 #include "azure_c_shared_utility/platform.h"
 #include "azure_c_shared_utility/tlsio.h"
 #include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/shared_util_options.h"
 #include <string.h>
 #include <limits.h>
 
-/*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the `httpapi.h`. ]*/ 
+/*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the `httpapi.h`. ]*/
 /*Codes_SRS_HTTPAPI_COMPACT_21_002: [ The httpapi_compact shall support the http requests. ]*/
 /*Codes_SRS_HTTPAPI_COMPACT_21_003: [ The httpapi_compact shall return error codes defined by HTTPAPI_RESULT. ]*/
 #include "azure_c_shared_utility/httpapi.h"
@@ -27,41 +28,47 @@
 #define MAX_HOSTNAME     64
 #define TEMP_BUFFER_SIZE 1024
 
-/*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
-/*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-#define MAX_RECEIVE_RETRY   70
-/*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-#define RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS  100
-#define OPEN_RETRY_INTERVAL_IN_MICROSECONDS  100
-
+/*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+#define MAX_OPEN_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+#define MAX_CLOSE_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+#define MAX_SEND_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
+#define MAX_RECEIVE_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+#define RETRY_INTERVAL_IN_MICROSECONDS  100
 
 DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
 
 typedef struct HTTP_HANDLE_DATA_TAG
 {
     char*           certificate;
+    char*           x509ClientCertificate;
+    char*           x509ClientPrivateKey;
     XIO_HANDLE      xio_handle;
     size_t          received_bytes_count;
     unsigned char*  received_bytes;
     unsigned int    is_io_error : 1;
     unsigned int    is_connected : 1;
+    unsigned int    send_completed : 1;
 } HTTP_HANDLE_DATA;
 
 /*the following function does the same as sscanf(pos2, "%d", &sec)*/
 /*this function only exists because some of platforms do not have sscanf. */
 static int ParseStringToDecimal(const char *src, int* dst)
 {
-	int result;
+    int result;
     char* next;
     (*dst) = strtol(src, &next, 0);
     if ((src == next) || ((((*dst) == LONG_MAX) || ((*dst) == LONG_MIN)) && (errno != 0)))
     {
-		result = EOF;
+        result = EOF;
     }
-	else
-	{
-		result = 1;
-	}
+    else
+    {
+        result = 1;
+    }
     return result;
 }
 
@@ -70,27 +77,27 @@
 #define HEXA_DIGIT_VAL(c)         (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='f')) ? (c-'a'+10) : ((c>='A') && (c<='F')) ? (c-'A'+10) : -1)
 static int ParseStringToHexadecimal(const char *src, size_t* dst)
 {
-	int result;
+    int result;
     int digitVal;
     if (src == NULL)
-	{
-		result = EOF;
-	}
-	else if (HEXA_DIGIT_VAL(*src) == -1)
-	{
-		result = EOF;
-	}
-	else
-	{
-		(*dst) = 0;
-		while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
-		{
-			(*dst) *= 0x10;
-			(*dst) += (size_t)digitVal;
-			src++;
-		}
-		result = 1;
-	}
+    {
+        result = EOF;
+    }
+    else if (HEXA_DIGIT_VAL(*src) == -1)
+    {
+        result = EOF;
+    }
+    else
+    {
+        (*dst) = 0;
+        while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
+        {
+            (*dst) *= 0x10;
+            (*dst) += (size_t)digitVal;
+            src++;
+        }
+        result = 1;
+    }
     return result;
 }
 
@@ -98,88 +105,88 @@
 /*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */
 static int  ParseHttpResponse(const char* src, int* dst)
 {
-	int result;
-	static const char HTTPPrefix[] = "HTTP/";
+    int result;
+    static const char HTTPPrefix[] = "HTTP/";
     bool fail;
     const char* runPrefix;
 
-	if ((src == NULL) || (dst == NULL))
-	{
-		result = EOF;
-	}
-	else
-	{
-		fail = false;
-		runPrefix = HTTPPrefix;
+    if ((src == NULL) || (dst == NULL))
+    {
+        result = EOF;
+    }
+    else
+    {
+        fail = false;
+        runPrefix = HTTPPrefix;
 
-		while((*runPrefix) != '\0')
-		{
-			if ((*runPrefix) != (*src))
-			{
-				fail = true;
-				break;
-			}
-			src++;
-			runPrefix++;
-		}
+        while((*runPrefix) != '\0')
+        {
+            if ((*runPrefix) != (*src))
+            {
+                fail = true;
+                break;
+            }
+            src++;
+            runPrefix++;
+        }
 
-		if (!fail)
-		{
-			while ((*src) != '.')
-			{
-				if ((*src) == '\0')
-				{
-					fail = true;
+        if (!fail)
+        {
+            while ((*src) != '.')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
                     break;
-				}
-				src++;
-			}
-		}
+                }
+                src++;
+            }
+        }
 
-		if (!fail)
-		{
-			while ((*src) != ' ')
-			{
-				if ((*src) == '\0')
-				{
-					fail = true;
+        if (!fail)
+        {
+            while ((*src) != ' ')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
                     break;
-				}
-				src++;
-			}
-		}
+                }
+                src++;
+            }
+        }
 
-		if (fail)
-		{
-			result = EOF;
-		}
-		else
-		{
-			result = ParseStringToDecimal(src, dst);
-		}
-	}
+        if (fail)
+        {
+            result = EOF;
+        }
+        else
+        {
+            result = ParseStringToDecimal(src, dst);
+        }
+    }
 
     return result;
 }
 
 HTTPAPI_RESULT HTTPAPI_Init(void)
 {
-	/*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/
-	/**
-	 * No memory is necessary. 
-	 */
+/*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/
+/**
+ * No memory is necessary.
+ */
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/
-    return HTTPAPI_OK;
+ /*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/
+return HTTPAPI_OK;
 }
 
 void HTTPAPI_Deinit(void)
 {
-	/*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/
-	/**
-	* No memory was necessary.
-	*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/
+    /**
+    * No memory was necessary.
+    */
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_011: [ The HTTPAPI_CreateConnection shall create an http connection to the host specified by the hostName parameter. ]*/
@@ -188,75 +195,132 @@
     HTTP_HANDLE_DATA* http_instance;
     TLSIO_CONFIG tlsio_config;
 
-	if (hostName == NULL)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		LogError("Invalid host name. Null hostName parameter.");
-		http_instance = NULL;
-	}
-	else if (*hostName == '\0')
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		LogError("Invalid host name. Empty string.");
-		http_instance = NULL;
-	}
-	else
-	{
-		http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
-		/*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		if (http_instance == NULL)
-		{
-			LogError("There is no memory to control the http connection");
-		}
-		else
-		{
-			tlsio_config.hostname = hostName;
-			tlsio_config.port = 443;
+    if (hostName == NULL)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Null hostName parameter.");
+        http_instance = NULL;
+    }
+    else if (*hostName == '\0')
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Empty string.");
+        http_instance = NULL;
+    }
+    else
+    {
+        http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
+        /*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        if (http_instance == NULL)
+        {
+            LogError("There is no memory to control the http connection");
+        }
+        else
+        {
+            tlsio_config.hostname = hostName;
+            tlsio_config.port = 443;
+
+            http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
 
-			http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
+            /*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/
+            if (http_instance->xio_handle == NULL)
+            {
+                LogError("Create connection failed");
+                free(http_instance);
+                http_instance = NULL;
+            }
+            else
+            {
+                http_instance->is_connected = 0;
+                http_instance->is_io_error = 0;
+                http_instance->received_bytes_count = 0;
+                http_instance->received_bytes = NULL;
+                http_instance->certificate = NULL;
+                http_instance->x509ClientCertificate = NULL;
+                http_instance->x509ClientPrivateKey = NULL;
+            }
+        }
+    }
 
-			/*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/
-			if (http_instance->xio_handle == NULL)
-			{
-				LogError("Create connection failed");
-				free(http_instance);
-				http_instance = NULL;
-			}
-			else
-			{
-				http_instance->is_connected = 0;
-				http_instance->is_io_error = 0;
-				http_instance->received_bytes_count = 0;
-				http_instance->received_bytes = NULL;
-				http_instance->certificate = NULL;
-			}
-		}
-	}
+    /*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
+    return (HTTP_HANDLE)http_instance;
+}
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
-	return (HTTP_HANDLE)http_instance;
+static void on_io_close_complete(void* context)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        http_instance->is_connected = 0;
+    }
 }
 
 void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
 {
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
-	if (http_instance != NULL)
+    /*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
+    if (http_instance != NULL)
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
-		if (http_instance->xio_handle != NULL)
+        /*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
+        if (http_instance->xio_handle != NULL)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_CreateConnection. ]*/
+            http_instance->is_io_error = 0;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_ExecuteRequest. ]*/
+            if (xio_close(http_instance->xio_handle, on_io_close_complete, http_instance) != 0)
+            {
+                LogError("The SSL got error closing the connection");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_087: [ If the xio return anything different than 0, the HTTPAPI_CloseConnection shall destroy the connection anyway. ]*/
+                http_instance->is_connected = 0;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+                int countRetry = MAX_CLOSE_RETRY;
+                while (http_instance->is_connected == 1)
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_085: [ If the HTTPAPI_CloseConnection retries 10 seconds to close the connection without success, it shall destroy the connection anyway. ]*/
+                        LogError("Close timeout. The SSL didn't close the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_io_error == 1)
+                    {
+                        LogError("The SSL got error closing the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_connected == 1)
+                    {
+                        LogInfo("Waiting for TLS close connection");
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_086: [ The HTTPAPI_CloseConnection shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+            /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ After close the connection, The HTTPAPI_CloseConnection shall destroy the connection previously created in HTTPAPI_CreateConnection. ]*/
             xio_destroy(http_instance->xio_handle);
         }
 
-		/*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
-		if (http_instance->certificate)
+        /*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->certificate)
         {
             free(http_instance->certificate);
         }
 
+        /*Codes_SRS_HTTPAPI_COMPACT_06_001: [ If there is a x509 client certificate associated to this connection, the HTTAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        /*Codes_SRS_HTTPAPI_COMPACT_06_002: [ If there is a x509 client private key associated to this connection, then HTTP_CloseConnection shall free all the allocated memory for the private key. ]*/
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
         free(http_instance);
     }
 }
@@ -264,19 +328,37 @@
 static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
 {
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
-    
+
     if (http_instance != NULL)
-	{
-		if (open_result == IO_OPEN_OK)
-		{
-			http_instance->is_connected = 1;
-			http_instance->is_io_error = 0;
-		}
-		else
-		{
-			http_instance->is_io_error = 1;
-		}
-	}
+    {
+        if (open_result == IO_OPEN_OK)
+        {
+            http_instance->is_connected = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
+}
+
+static void on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        if (send_result == IO_SEND_OK)
+        {
+            http_instance->send_completed = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
 }
 
 #define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
@@ -284,26 +366,26 @@
 {
     int result;
 
-	if ((s1 == NULL) || (s2 == NULL))
-	{
-		result = -1;
-	}
-	else
-	{
-		result = 0;
-		while (((n--) >= 0) && ((*s1) != '\0') && ((*s2) != '\0') && (result == 0))
-		{
-			/* compute the difference between the chars */
-			result = TOLOWER(*s1) - TOLOWER(*s2);
-			s1++;
-			s2++;
-		}
+    if ((s1 == NULL) || (s2 == NULL))
+    {
+        result = -1;
+    }
+    else
+    {
+        result = 0;
+        while (((n--) >= 0) && ((*s1) != '\0') && ((*s2) != '\0') && (result == 0))
+        {
+            /* compute the difference between the chars */
+            result = TOLOWER(*s1) - TOLOWER(*s2);
+            s1++;
+            s2++;
+        }
 
         if ((*s2) != '\0')
         {
             result = -1;
         }
-	}
+    }
 
     return result;
 }
@@ -344,7 +426,7 @@
                 }
             }
         }
-	}
+    }
 }
 
 static void on_io_error(void* context)
@@ -361,47 +443,48 @@
 {
     int result;
 
-	if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
-	{
+    if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
+    {
         LogError("conn_receive: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
         result = -1;
-	}
-	else
-	{
-		result = 0;
-		while (result < count)
-		{
-			xio_dowork(http_instance->xio_handle);
+    }
+    else
+    {
+        result = 0;
+        while (result < count)
+        {
+            xio_dowork(http_instance->xio_handle);
 
-			/* if any error was detected while receiving then simply break and report it */
-			if (http_instance->is_io_error != 0)
-			{
+            /* if any error was detected while receiving then simply break and report it */
+            if (http_instance->is_io_error != 0)
+            {
                 LogError("xio reported error on dowork");
                 result = -1;
-				break;
-			}
+                break;
+            }
 
-			if (http_instance->received_bytes_count >= (size_t)count)
-			{
-				/* Consuming bytes from the receive buffer */
-				(void)memcpy(buffer, http_instance->received_bytes, count);
-				(void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
-				http_instance->received_bytes_count -= count;
+            if (http_instance->received_bytes_count >= (size_t)count)
+            {
+                /* Consuming bytes from the receive buffer */
+                (void)memcpy(buffer, http_instance->received_bytes, count);
+                (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
+                http_instance->received_bytes_count -= count;
 
-				/* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
-				if (http_instance->received_bytes_count == 0)
-				{
-					free(http_instance->received_bytes);
-					http_instance->received_bytes = NULL;
-				}
+                /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
+                if (http_instance->received_bytes_count == 0)
+                {
+                    free(http_instance->received_bytes);
+                    http_instance->received_bytes = NULL;
+                }
 
-				result = count;
-				break;
-			}
+                result = count;
+                break;
+            }
 
-			ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
-		}
-	}
+            /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+            ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+        }
+    }
 
     return result;
 }
@@ -431,7 +514,7 @@
     else
     {
         char* destByte = buf;
-        /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
         int countRetry = MAX_RECEIVE_RETRY;
         bool endOfSearch = false;
         resultLineSize = -1;
@@ -493,13 +576,13 @@
             {
                 if ((countRetry--) > 0)
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-                    ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                    ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
                 }
                 else
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-                    LogError("Timeout. The HTTP request is incomplete");
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    LogError("Receive timeout. The HTTP request is incomplete");
                     endOfSearch = true;
                 }
             }
@@ -522,10 +605,10 @@
         cur = conn_receive(http_instance, buf + offset, (int)size);
 
         // end of stream reached
-		if (cur == 0)
-		{
-			break;
-		}
+        if (cur == 0)
+        {
+            break;
+        }
 
         // read cur bytes (might be less than requested)
         size -= (size_t)cur;
@@ -549,7 +632,7 @@
     }
     else
     {
-        /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
         int countRetry = MAX_RECEIVE_RETRY;
         result = (int)n;
         while (n > 0)
@@ -581,13 +664,13 @@
                 {
                     if ((countRetry--) > 0)
                     {
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-                        ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
                     }
                     else
                     {
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-                        LogError("Timeout. The HTTP request is incomplete");
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        LogError("Receive timeout. The HTTP request is incomplete");
                         n = 0;
                         result = -1;
                     }
@@ -603,53 +686,127 @@
 /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
 static HTTPAPI_RESULT OpenXIOConnection(HTTP_HANDLE_DATA* http_instance)
 {
-	HTTPAPI_RESULT result;
+    HTTPAPI_RESULT result;
+
+    if (http_instance->is_connected != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    else
+    {
+        http_instance->is_io_error = 0;
+
+        /*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        if ((http_instance->certificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, "TrustedCerts", http_instance->certificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load certificate");
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_06_003: [ If the x509 client certificate is provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        else if ((http_instance->x509ClientCertificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_CERT, http_instance->x509ClientCertificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_06_005: [ If the transport failed setting the client certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate");
+        }
+        else if ((http_instance->x509ClientPrivateKey != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_instance->x509ClientPrivateKey) != 0))
+        {
 
-	if (http_instance->is_connected != 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
-		if ((http_instance->certificate != NULL) &&
-			(xio_setoption(http_instance->xio_handle, "TrustedCerts", http_instance->certificate) != 0))
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
-			result = HTTPAPI_SET_OPTION_FAILED;
-			LogInfo("Could not load certificate");
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
-			if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0)
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
-				result = HTTPAPI_OPEN_REQUEST_FAILED;
-			}
-			else
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-				result = HTTPAPI_OK;
-				while ((http_instance->is_connected == 0) &&
-					(http_instance->is_io_error == 0))
-				{
-					xio_dowork(http_instance->xio_handle);
-					LogInfo("Waiting for TLS connection");
-					ThreadAPI_Sleep(OPEN_RETRY_INTERVAL_IN_MICROSECONDS);
-				}
-			}
-		}
-	}
-	
-	if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
-		result = HTTPAPI_OPEN_REQUEST_FAILED;
-	}
+            /*Codes_SRS_HTTPAPI_COMPACT_06_006: [ If the transport failed setting the client certificate private key, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ] */
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate private key");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+            if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                result = HTTPAPI_OPEN_REQUEST_FAILED;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                result = HTTPAPI_OK;
+                /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+                int countRetry = MAX_OPEN_RETRY;
+                while ((http_instance->is_connected == 0) &&
+                    (http_instance->is_io_error == 0))
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    LogInfo("Waiting for TLS connection");
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ If the HTTPAPI_ExecuteRequest cannot open the connection in 10 seconds, it shall fail and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                        LogError("Open timeout. The HTTP request is incomplete");
+                        result = HTTPAPI_OPEN_REQUEST_FAILED;
+                        break;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+        }
+    }
 
-	return result;
+    if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+        result = HTTPAPI_OPEN_REQUEST_FAILED;
+    }
+
+    return result;
+}
+
+static HTTPAPI_RESULT conn_send_all(HTTP_HANDLE_DATA* http_instance, const unsigned char* buf, size_t bufLen)
+{
+    HTTPAPI_RESULT result;
+
+    http_instance->send_completed = 0;
+    http_instance->is_io_error = 0;
+    if (xio_send(http_instance->xio_handle, buf, bufLen, on_send_complete, http_instance) != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+        result = HTTPAPI_SEND_REQUEST_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+        int countRetry = MAX_SEND_RETRY;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while ((http_instance->send_completed == 0) && (result == HTTPAPI_OK))
+        {
+            xio_dowork(http_instance->xio_handle);
+            if (http_instance->is_io_error != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else if ((countRetry--) <= 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_080: [ If the HTTPAPI_ExecuteRequest retries to send the message for 20 seconds without success, it shall fail and return HTTPAPI_SEND_REQUEST_FAILED. ]*/
+                LogError("Send timeout. The HTTP request is incomplete");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+            }
+        }
+    }
+
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types `GET`, `POST`, `PUT`, `DELETE`, `PATCH`. ]*/
@@ -662,249 +819,234 @@
 /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
 static HTTPAPI_RESULT SendHeadsToXIO(HTTP_HANDLE_DATA* http_instance, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, size_t headersCount)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	int     ret;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
 
-	//Send request
-	/*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
-	if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
-		(ret >= sizeof(buf)))
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
-		result = HTTPAPI_STRING_PROCESSING_ERROR;
-	}
-    else if (xio_send(http_instance->xio_handle, (const unsigned char*)buf, strlen(buf), NULL, NULL) != 0)
+    //Send request
+    /*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
+    if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
+        (ret >= sizeof(buf)))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+        result = HTTPAPI_STRING_PROCESSING_ERROR;
+    }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+    else if ((result = conn_send_all(http_instance, (const unsigned char*)buf, strlen(buf))) == HTTPAPI_OK)
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-		result = HTTPAPI_SEND_REQUEST_FAILED;
-	}
-	else
-	{
-		//Send default headers
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-		for (size_t i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
-		{
-			char* header;
-			if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
-				result = HTTPAPI_STRING_PROCESSING_ERROR;
-			}
-			else
-			{
-                if (xio_send(http_instance->xio_handle, (const unsigned char*)header, strlen(header), NULL, NULL) != 0)
+        //Send default headers
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        for (size_t i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
+        {
+            char* header;
+            if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+                result = HTTPAPI_STRING_PROCESSING_ERROR;
+            }
+            else
+            {
+                if ((result = conn_send_all(http_instance, (const unsigned char*)header, strlen(header))) == HTTPAPI_OK)
                 {
-					/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-					result = HTTPAPI_SEND_REQUEST_FAILED;
-				}
-                if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0)
-                {
-					/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-					result = HTTPAPI_SEND_REQUEST_FAILED;
-				}
-				free(header);
-			}
-		}
+                    result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+                }
+                free(header);
+            }
+        }
 
-		//Close headers
-        if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0)
+        //Close headers
+        if (result == HTTPAPI_OK)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-			result = HTTPAPI_SEND_REQUEST_FAILED;
-		}
-	}
-	return result;
+            result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+        }
+    }
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
 static HTTPAPI_RESULT SendContentToXIO(HTTP_HANDLE_DATA* http_instance, const unsigned char* content, size_t contentLength)
 {
-	HTTPAPI_RESULT result;
+    HTTPAPI_RESULT result;
 
-	//Send data (if available)
-	/*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
-	if (content && contentLength > 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/
-        if (xio_send(http_instance->xio_handle, content, contentLength, NULL, NULL) != 0)
-        {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_029: [ If the HTTPAPI_ExecuteRequest cannot send the buffer with the request, it shall return HTTPAPI_SEND_REQUEST_FAILED. ]*/
-			result = HTTPAPI_SEND_REQUEST_FAILED;
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-			result = HTTPAPI_OK;
-		}
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
-	return result;
+    //Send data (if available)
+    /*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+    if (content && contentLength > 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/
+        result = conn_send_all(http_instance, content, contentLength);
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
 static HTTPAPI_RESULT RecieveHeaderFromXIO(HTTP_HANDLE_DATA* http_instance, unsigned int* statusCode)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	int     ret;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
+
+    http_instance->is_io_error = 0;
 
-	//Receive response
-	if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+    //Receive response
+    if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
         result = HTTPAPI_READ_DATA_FAILED;
-	}
-	//Parse HTTP response
-	else if (ParseHttpResponse(buf, &ret) != 1)
-	{
-		//Cannot match string, error
+    }
+    //Parse HTTP response
+    else if (ParseHttpResponse(buf, &ret) != 1)
+    {
+        //Cannot match string, error
         /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
         LogInfo("Not a correct HTTP answer");
-		result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
-		if (statusCode)
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
-			*statusCode = ret;
-		}
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
+        result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
+        if (statusCode)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
+            *statusCode = ret;
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
 
-	return result;
+    return result;
 }
 
 static HTTPAPI_RESULT RecieveContentInfoFromXIO(HTTP_HANDLE_DATA* http_instance, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
     const char* substr;
     char* whereIsColon;
     int lengthInMsg;
-	const char* ContentLength = "content-length:";
-	const int ContentLengthSize = 16;
-	const char* TransferEncoding = "transfer-encoding:";
-	const int TransferEncodingSize = 19;
-	const char* Chunked = "chunked";
-	const int ChunkedSize = 8;
+    const char* ContentLength = "content-length:";
+    const int ContentLengthSize = 16;
+    const char* TransferEncoding = "transfer-encoding:";
+    const int TransferEncodingSize = 19;
+    const char* Chunked = "chunked";
+    const int ChunkedSize = 8;
+
+    http_instance->is_io_error = 0;
 
-	//Read HTTP response headers
-	if (readLine(http_instance, buf, sizeof(buf)) < 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+    //Read HTTP response headers
+    if (readLine(http_instance, buf, sizeof(buf)) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
         result = HTTPAPI_READ_DATA_FAILED;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
 
-		while (*buf && (result == HTTPAPI_OK))
-		{
-			if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
-			{
-				substr = buf + ContentLengthSize - 1;
-				if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				else
-				{
-					(*bodyLength) = (size_t)lengthInMsg;
-				}
-			}
-			else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
-			{
-				substr = buf + TransferEncodingSize - 1;
+        while (*buf && (result == HTTPAPI_OK))
+        {
+            if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
+            {
+                substr = buf + ContentLengthSize - 1;
+                if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    (*bodyLength) = (size_t)lengthInMsg;
+                }
+            }
+            else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
+            {
+                substr = buf + TransferEncodingSize - 1;
+
+                while (isspace(*substr)) substr++;
 
-				while (isspace(*substr)) substr++;
-				
-				if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
-				{
-					(*chunked) = true;
-				}
-			}
+                if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
+                {
+                    (*chunked) = true;
+                }
+            }
 
-			if (result == HTTPAPI_OK)
-			{
-				whereIsColon = strchr((char*)buf, ':');
-				/*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/
-				if (whereIsColon && (responseHeadersHandle != NULL))
-				{
-					*whereIsColon = '\0';
-					HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
-				}
+            if (result == HTTPAPI_OK)
+            {
+                whereIsColon = strchr((char*)buf, ':');
+                /*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/
+                if (whereIsColon && (responseHeadersHandle != NULL))
+                {
+                    *whereIsColon = '\0';
+                    HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
+                }
 
-				if (readLine(http_instance, buf, sizeof(buf)) < 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                if (readLine(http_instance, buf, sizeof(buf)) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                     result = HTTPAPI_READ_DATA_FAILED;
-				}
-			}
-		}
-	}
+                }
+            }
+        }
+    }
 
-	return result;
+    return result;
 }
 
 static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	const unsigned char* receivedContent;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    const unsigned char* receivedContent;
+
+    http_instance->is_io_error = 0;
 
-	//Read HTTP response body
-	if (!chunked)
-	{
-		if (bodyLength)
-		{
-			if (responseContent != NULL)
-			{
-				if (BUFFER_pre_build(responseContent, bodyLength) != 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-					result = HTTPAPI_ALLOC_FAILED;
-				}
-				else if (BUFFER_content(responseContent, &receivedContent) != 0)
-				{
-					(void)BUFFER_unbuild(responseContent);
+    //Read HTTP response body
+    if (!chunked)
+    {
+        if (bodyLength)
+        {
+            if (responseContent != NULL)
+            {
+                if (BUFFER_pre_build(responseContent, bodyLength) != 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                {
+                    (void)BUFFER_unbuild(responseContent);
 
-					/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-					result = HTTPAPI_ALLOC_FAILED;
-				}
-				else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				else
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-					result = HTTPAPI_OK;
-				}
-			}
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                    result = HTTPAPI_OK;
+                }
+            }
             else
             {
                 /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
                 if (skipN(http_instance, bodyLength) < 0)
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                     result = HTTPAPI_READ_DATA_FAILED;
                 }
                 else
@@ -912,114 +1054,114 @@
                     result = HTTPAPI_OK;
                 }
             }
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-			result = HTTPAPI_OK;
-		}
-	}
-	else
-	{
-		size_t size = 0;
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-		while (result == HTTPAPI_OK)
-		{
-			size_t chunkSize;
-			if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-                /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+            result = HTTPAPI_OK;
+        }
+    }
+    else
+    {
+        size_t size = 0;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while (result == HTTPAPI_OK)
+        {
+            size_t chunkSize;
+            if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                 result = HTTPAPI_READ_DATA_FAILED;
-			}
-			else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
-			{
-				//Cannot match string, error
-				/*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
-				result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
-			}
-			else if (chunkSize == 0)
-			{
-				// 0 length means next line is just '\r\n' and end of chunks
-				if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
-					|| buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-				{
-					(void)BUFFER_unbuild(responseContent);
+            }
+            else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
+            {
+                //Cannot match string, error
+                /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
+                result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+            }
+            else if (chunkSize == 0)
+            {
+                // 0 length means next line is just '\r\n' and end of chunks
+                if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                {
+                    (void)BUFFER_unbuild(responseContent);
 
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				break;
-			}
-			else
-			{
-				if (responseContent != NULL)
-				{
-					if (BUFFER_enlarge(responseContent, chunkSize) != 0)
-					{
-						(void)BUFFER_unbuild(responseContent);
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                break;
+            }
+            else
+            {
+                if (responseContent != NULL)
+                {
+                    if (BUFFER_enlarge(responseContent, chunkSize) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
 
-						/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-						result = HTTPAPI_ALLOC_FAILED;
-					}
-					else if (BUFFER_content(responseContent, &receivedContent) != 0)
-					{
-						(void)BUFFER_unbuild(responseContent);
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
 
-						/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-						result = HTTPAPI_ALLOC_FAILED;
-					}
-					else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
-					{
-						result = HTTPAPI_READ_DATA_FAILED;
-					}
-				}
-				else
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
-					if (skipN(http_instance, chunkSize) < 0)
-					{
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
+                    if (skipN(http_instance, chunkSize) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                         result = HTTPAPI_READ_DATA_FAILED;
-					}
-				}
+                    }
+                }
 
-				if (result == HTTPAPI_OK)
-				{
-					if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
-						|| buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-					{
-						result = HTTPAPI_READ_DATA_FAILED;
-					}
-					size += chunkSize;
-				}
-			}
-		}
+                if (result == HTTPAPI_OK)
+                {
+                    if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                        || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                    size += chunkSize;
+                }
+            }
+        }
 
-	}
-	return result;
+    }
+    return result;
 }
 
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
 static bool validRequestType(HTTPAPI_REQUEST_TYPE requestType)
 {
-	bool result;
+    bool result;
 
-	if ((requestType == HTTPAPI_REQUEST_GET) ||
-		(requestType == HTTPAPI_REQUEST_POST) ||
-		(requestType == HTTPAPI_REQUEST_PUT) ||
-		(requestType == HTTPAPI_REQUEST_DELETE) ||
-		(requestType == HTTPAPI_REQUEST_PATCH))
-	{
-		result = true;
-	}
-	else
-	{
-		result = false;
-	}
+    if ((requestType == HTTPAPI_REQUEST_GET) ||
+        (requestType == HTTPAPI_REQUEST_POST) ||
+        (requestType == HTTPAPI_REQUEST_PUT) ||
+        (requestType == HTTPAPI_REQUEST_DELETE) ||
+        (requestType == HTTPAPI_REQUEST_PATCH))
+    {
+        result = true;
+    }
+    else
+    {
+        result = false;
+    }
 
-	return result;
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
@@ -1035,65 +1177,58 @@
     size_t  headersCount;
     size_t  bodyLength = 0;
     bool    chunked = false;
-	HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	if (http_instance == NULL ||
+    /*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    if (http_instance == NULL ||
         relativePath == NULL ||
         httpHeadersHandle == NULL ||
-		!validRequestType(requestType) ||
+        !validRequestType(requestType) ||
         HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
     {
         result = HTTPAPI_INVALID_ARG;
         LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
     }
-	/*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
-	else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
-	{
-		LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
-	else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
-	{
-		LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
-	else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
-	{
-		LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message recived by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
-	else if ((result = RecieveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
-	{
-		LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message recieved by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/
-	else if ((result = RecieveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
-	{
-		LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message recieved by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
-	else if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
-	{
-		LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
+    /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+    else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
+    {
+        LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
+    else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
+    {
+        LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
+    else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
+    {
+        LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message recived by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
+    else if ((result = RecieveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
+    {
+        LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message recieved by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/
+    else if ((result = RecieveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
+    {
+        LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message recieved by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
+    else if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
+    {
+        LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
 
     conn_receive_discard_buffer(http_instance);
 
-    /*Codes_SRS_HTTPAPI_COMPACT_21_031: [ After receive the response, the HTTPAPI_ExecuteRequest shall close the transport connection with the host. ]*/
-	if ((http_instance != NULL) &&
-        (http_instance->is_connected != 0))
-    {
-        xio_close(http_instance->xio_handle, NULL, NULL);
-        http_instance->is_connected = 0;
-    }
 
     return result;
 }
@@ -1106,16 +1241,16 @@
     HTTPAPI_RESULT result;
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	if (
+    if (
         (http_instance == NULL) ||
         (optionName == NULL) ||
         (value == NULL)
         )
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
     }
     else if (strcmp("TrustedCerts", optionName) == 0)
     {
@@ -1128,20 +1263,64 @@
         http_instance->certificate = (char*)malloc((len + 1) * sizeof(char));
         if (http_instance->certificate == NULL)
         {
-			/*SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
-			result = HTTPAPI_ALLOC_FAILED;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
             LogInfo("unable to allocate memory for the certificate in HTTPAPI_SetOption");
         }
         else
         {
-			/*SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
             (void)strcpy(http_instance->certificate, (const char*)value);
             result = HTTPAPI_OK;
         }
     }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        int len = (int)strlen((char*)value);
+        http_instance->x509ClientCertificate = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientCertificate == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client certificate in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientCertificate, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
+
+        int len = (int)strlen((char*)value);
+        http_instance->x509ClientPrivateKey = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientPrivateKey == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client private key in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientPrivateKey, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
     else
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
         result = HTTPAPI_INVALID_ARG;
         LogInfo("unknown option %s", optionName);
     }
@@ -1156,16 +1335,16 @@
     size_t certLen;
     char* tempCert;
 
-	if (
+    if (
         (optionName == NULL) ||
         (value == NULL) ||
         (savedValue == NULL)
         )
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
     }
     else if (strcmp("TrustedCerts", optionName) == 0)
     {
@@ -1173,21 +1352,55 @@
         tempCert = (char*)malloc((certLen + 1) * sizeof(char));
         if (tempCert == NULL)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
-			result = HTTPAPI_ALLOC_FAILED;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
         }
         else
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
-			(void)strcpy(tempCert, (const char*)value);
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
             *savedValue = tempCert;
             result = HTTPAPI_OK;
         }
     }
     else
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
         LogInfo("unknown option %s", optionName);
     }
     return result;
--- a/sastoken.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/sastoken.c	Wed Nov 16 21:38:39 2016 -0800
@@ -1,16 +1,11 @@
 // Copyright (c) Microsoft. All rights reserved.
 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
-#include <stdlib.h>
 #ifdef _CRTDBG_MAP_ALLOC
 #include <crtdbg.h>
 #endif
+
 #include "azure_c_shared_utility/gballoc.h"
-
-#include <time.h>
-#include <stddef.h>
-
-#include "azure_c_shared_utility/crt_abstractions.h"
 #include "azure_c_shared_utility/sastoken.h"
 #include "azure_c_shared_utility/urlencode.h"
 #include "azure_c_shared_utility/hmacsha256.h"
@@ -19,6 +14,190 @@
 #include "azure_c_shared_utility/strings.h"
 #include "azure_c_shared_utility/buffer_.h"
 #include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+
+static double getExpiryValue(const char* expiryASCII)
+{
+    double value = 0;
+    size_t i = 0;
+    for (i = 0; expiryASCII[i] != '\0'; i++)
+    {
+        if (expiryASCII[i] >= '0' && expiryASCII[i] <= '9')
+        {
+            value = value * 10 + (expiryASCII[i] - '0');
+        }
+        else
+        {
+            value = 0;
+            break;
+        }
+    }
+    return value;
+}
+
+bool SASToken_Validate(STRING_HANDLE sasToken)
+{
+    bool result;
+    /*Codes_SRS_SASTOKEN_25_025: [**SASToken_Validate shall get the SASToken value by invoking STRING_c_str on the handle.**]***/
+    const char* sasTokenArray = STRING_c_str(sasToken);
+
+    /***Codes_SRS_SASTOKEN_25_024: [**If handle is NULL then SASToken_Validate shall return false.**] ***/
+    /*Codes_SRS_SASTOKEN_25_026: [**If STRING_c_str on handle return NULL then SASToken_Validate shall return false.**]***/
+    if (sasToken == NULL || sasTokenArray == NULL)
+    {
+        result = false;
+    }
+    else
+    {
+        int seStart = -1, seStop = -1;
+        int srStart = -1, srStop = -1;
+        int sigStart = -1, sigStop = -1;
+        int tokenLength = (int) STRING_length(sasToken);
+        int i ;
+        for (i = 0; i < tokenLength; i++)
+        {
+            if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'e' && sasTokenArray[i + 2] == '=') // Look for se=
+            {
+                seStart = i + 3;
+                if (srStart > 0 && srStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ') // look for either & or space
+                        srStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        srStop = i - 2;
+                    else
+                        seStart = -1; // as the format is not either "&se=" or " se="
+                }
+                else if (sigStart > 0 && sigStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        sigStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        sigStop = i - 2;
+                    else
+                        seStart = -1;
+                }
+                continue;
+            }
+            if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'r' && sasTokenArray[i + 2] == '=') // Look for sr=
+            {
+                srStart = i + 3;
+                if (seStart > 0 && seStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        seStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        seStop = i - 2;
+                    else
+                        srStart = -1;
+                }
+                else if (sigStart > 0 && sigStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        sigStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        sigStop = i - 2;
+                    else
+                        srStart = -1;
+                }
+                continue;
+            }
+            if (sasTokenArray[i] == 's' && sasTokenArray[i + 1] == 'i' && sasTokenArray[i + 2] == 'g' && sasTokenArray[i + 3] == '=') // Look for sig=
+            {
+                sigStart = i + 4;
+                if (srStart > 0 && srStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        srStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        srStop = i - 2;
+                    else
+                        sigStart = -1;
+                }
+                else if (seStart > 0 && seStop < 0)
+                {
+                    if (sasTokenArray[i - 1] != '&' && sasTokenArray[i - 1] == ' ')
+                        seStop = i - 1;
+                    else if (sasTokenArray[i - 1] == '&')
+                        seStop = i - 2;
+                    else
+                        sigStart = -1;
+                }
+                continue;
+            }
+        }
+        /*Codes_SRS_SASTOKEN_25_027: [**If SASTOKEN does not obey the SASToken format then SASToken_Validate shall return false.**]***/
+        /*Codes_SRS_SASTOKEN_25_028: [**SASToken_validate shall check for the presence of sr, se and sig from the token and return false if not found**]***/
+        if (seStart < 0 || srStart < 0 || sigStart < 0)
+        {
+            result = false;
+        }
+        else
+        {
+            if (seStop < 0)
+            {
+                seStop = tokenLength;
+            }
+            else if (srStop < 0)
+            {
+                srStop = tokenLength;
+            }
+            else if (sigStop < 0)
+            {
+                sigStop = tokenLength;
+            }
+
+            if ((seStop <= seStart) ||
+                (srStop <= srStart) ||
+                (sigStop <= sigStart))
+            {
+                result = false;
+            }
+            else
+            {
+                char* expiryASCII = malloc(seStop - seStart + 1);
+                /*Codes_SRS_SASTOKEN_25_031: [**If malloc fails during validation then SASToken_Validate shall return false.**]***/
+                if (expiryASCII == NULL)
+                {
+                    result = false;
+                }
+                else
+                {
+                    double expiry;
+                    for (i = seStart; i < seStop; i++)
+                    {
+                        expiryASCII[i - seStart] = sasTokenArray[i];
+                    }
+                    expiryASCII[seStop - seStart] = '\0';
+
+                    expiry = getExpiryValue(expiryASCII);
+                    /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/
+                    if (expiry <= 0)
+                    {
+                        result = false;
+                    }
+                    else
+                    {
+                        double secSinceEpoch = get_difftime(get_time(NULL), (time_t)0);
+                        if (expiry < secSinceEpoch)
+                        {
+                            /*Codes_SRS_SASTOKEN_25_029: [**SASToken_validate shall check for expiry time from token and if token has expired then would return false **]***/
+                            result = false;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_SASTOKEN_25_030: [**SASToken_validate shall return true only if the format is obeyed and the token has not yet expired **]***/
+                            result = true;
+                        }
+                    }
+                    free(expiryASCII);
+                }
+            }
+        }
+    }
+
+    return result;
+}
 
 STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry)
 {
--- a/sha1.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/sha1.c	Wed Nov 16 21:38:39 2016 -0800
@@ -56,7 +56,6 @@
 /*
 * add "length" to the length
 */
-static uint32_t addTemp;
 #define SHA1AddLength(context, length)                     \
     (addTemp = (context)->Length_Low,                      \
      (context)->Corrupted =                                \
@@ -129,6 +128,7 @@
 int SHA1Input(SHA1Context *context,
     const uint8_t *message_array, unsigned length)
 {
+    uint32_t addTemp;
     if (!length)
         return shaSuccess;
 
@@ -179,6 +179,8 @@
 int SHA1FinalBits(SHA1Context *context, const uint8_t message_bits,
     unsigned int length)
 {
+    uint32_t addTemp;
+
     uint8_t masks[8] = {
         /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
         /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
--- a/sha224.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/sha224.c	Wed Nov 16 21:38:39 2016 -0800
@@ -67,7 +67,6 @@
 /*
 * add "length" to the length
 */
-static uint32_t addTemp;
 #define SHA224_256AddLength(context, length)               \
   (addTemp = (context)->Length_Low, (context)->Corrupted = \
     (((context)->Length_Low += (length)) < addTemp) &&     \
@@ -230,6 +229,7 @@
 int SHA256Input(SHA256Context *context, const uint8_t *message_array,
     unsigned int length)
 {
+    uint32_t addTemp;
     if (!length)
         return shaSuccess;
 
@@ -281,6 +281,7 @@
 int SHA256FinalBits(SHA256Context *context,
     const uint8_t message_bits, unsigned int length)
 {
+    uint32_t addTemp;
     uint8_t masks[8] = {
         /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
         /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
--- a/sha384-512.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/sha384-512.c	Wed Nov 16 21:38:39 2016 -0800
@@ -52,6 +52,7 @@
 #include "azure_c_shared_utility/sha-private.h"
 
 #ifdef USE_32BIT_ONLY
+#error IoTHubClient does not support USE_32BIT_ONLY flag
 /*
 * Define 64-bit arithmetic in terms of 32-bit arithmetic.
 * Each 64-bit number is represented in a 2-word array.
@@ -297,7 +298,6 @@
 /*
 * add "length" to the length
 */
-static uint64_t addTemp;
 #define SHA384_512AddLength(context, length)                   \
    (addTemp = context->Length_Low, context->Corrupted =        \
     ((context->Length_Low += length) < addTemp) &&             \
@@ -468,6 +468,7 @@
     const uint8_t *message_array,
     unsigned int length)
 {
+    uint64_t addTemp;
     if (!length)
         return shaSuccess;
 
@@ -519,6 +520,7 @@
 int SHA512FinalBits(SHA512Context *context,
     const uint8_t message_bits, unsigned int length)
 {
+    uint64_t addTemp;
     uint8_t masks[8] = {
         /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
         /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
--- a/tlsio_wolfssl.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/tlsio_wolfssl.c	Wed Nov 16 21:38:39 2016 -0800
@@ -16,6 +16,8 @@
 #include "azure_c_shared_utility/socketio.h"
 #include "azure_c_shared_utility/crt_abstractions.h"
 #include "azure_c_shared_utility/xlogging.h"
+#include "azure_c_shared_utility/shared_util_options.h"
+
 
 typedef enum TLSIO_STATE_ENUM_TAG
 {
@@ -46,6 +48,8 @@
     ON_SEND_COMPLETE on_send_complete;
     void* on_send_complete_callback_context;
     char* certificate;
+    char* x509certificate;
+    char* x509privatekey;
     char* hostname;
     int port;
 } TLS_IO_INSTANCE;
@@ -54,10 +58,9 @@
 static void* tlsio_wolfssl_CloneOption(const char* name, const void* value)
 {
     void* result;
-    if (
-        (name == NULL) || (value == NULL)
-        )
+    if ((name == NULL) || (value == NULL))
     {
+        LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
         result = NULL;
     }
     else
@@ -66,6 +69,31 @@
         {
             if (mallocAndStrcpy_s((char**)&result, value) != 0)
             {
+                LogError("unable to mallocAndStrcpy_s TrustedCerts value");
+                result = NULL;
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else if (strcmp(name, SU_OPTION_X509_CERT) == 0)
+        {
+            if (mallocAndStrcpy_s((char**)&result, value) != 0)
+            {
+                LogError("unable to mallocAndStrcpy_s x509certificate value");
+                result = NULL;
+            }
+            else
+            {
+                /*return as is*/
+            }
+        }
+        else if (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0)
+        {
+            if (mallocAndStrcpy_s((char**)&result, value) != 0)
+            {
+                LogError("unable to mallocAndStrcpy_s x509privatekey value");
                 result = NULL;
             }
             else
@@ -75,7 +103,7 @@
         }
         else
         {
-            /*option is not handled*/
+            LogError("not handled option : %s", name);
             result = NULL;
         }
     }
@@ -86,15 +114,21 @@
 static void tlsio_wolfssl_DestroyOption(const char* name, const void* value)
 {
     /*since all options for this layer are actually string copies., disposing of one is just calling free*/
-    if ((name != NULL) && (value != NULL))
+    if ((name == NULL) || (value == NULL))
     {
-        if (strcmp(name, "TrustedCerts") == 0)
+        LogError("invalid parameter detected: const char* name=%p, const void* value=%p", name, value);
+    }
+    else
+    {
+        if ((strcmp(name, "TrustedCerts") == 0) ||
+            (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
+            (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0))
         {
             free((void*)value);
         }
         else
         {
-            /*option is not handled*/
+            LogError("not handled option : %s", name);
         }
     }
 }
@@ -212,21 +246,21 @@
 
     switch (tls_io_instance->tlsio_state)
     {
-        default:
-        case TLSIO_STATE_NOT_OPEN:
-        case TLSIO_STATE_ERROR:
-            break;
+    default:
+    case TLSIO_STATE_NOT_OPEN:
+    case TLSIO_STATE_ERROR:
+        break;
 
-        case TLSIO_STATE_OPENING_UNDERLYING_IO:
-        case TLSIO_STATE_IN_HANDSHAKE:
-            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
-            indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
-            break;
+    case TLSIO_STATE_OPENING_UNDERLYING_IO:
+    case TLSIO_STATE_IN_HANDSHAKE:
+        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+        indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
+        break;
 
-        case TLSIO_STATE_OPEN:
-            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
-            indicate_error(tls_io_instance);
-            break;
+    case TLSIO_STATE_OPEN:
+        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
+        indicate_error(tls_io_instance);
+        break;
     }
 }
 
@@ -250,6 +284,7 @@
     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
     unsigned char* new_socket_io_read_bytes;
 
+    (void)ssl;
     while (tls_io_instance->socket_io_read_byte_count == 0)
     {
         xio_dowork(tls_io_instance->socket_io);
@@ -302,6 +337,7 @@
     int result;
     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
 
+    (void)ssl;
     if (xio_send(tls_io_instance->socket_io, buf, sz, tls_io_instance->on_send_complete, tls_io_instance->on_send_complete_callback_context) != 0)
     {
         tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
@@ -319,6 +355,7 @@
 static int on_handshake_done(WOLFSSL* ssl, void* context)
 {
     TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
+    (void)ssl;
     if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
     {
         tls_io_instance->tlsio_state = TLSIO_STATE_OPEN;
@@ -333,7 +370,7 @@
     int result;
     if (tls_io_instance->certificate != NULL)
     {
-        int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)tls_io_instance->certificate, strlen(tls_io_instance->certificate)+1, SSL_FILETYPE_PEM);
+        int res = wolfSSL_CTX_load_verify_buffer(tls_io_instance->ssl_context, (const unsigned char*)tls_io_instance->certificate, strlen(tls_io_instance->certificate) + 1, SSL_FILETYPE_PEM);
         if (res != SSL_SUCCESS)
         {
             result = __LINE__;
@@ -350,6 +387,38 @@
     return result;
 }
 
+static int x509_wolfssl_add_credentials(WOLFSSL* ssl, char* x509certificate, char* x509privatekey) {
+
+    int result;
+
+    if (wolfSSL_use_certificate_buffer(ssl, (unsigned char*)x509certificate, strlen(x509certificate) + 1, SSL_FILETYPE_PEM) != SSL_SUCCESS)
+    {
+        LogError("unable to load x509 client certificate");
+        result = __LINE__;
+    }
+    else if (wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)x509privatekey, strlen(x509privatekey) + 1, SSL_FILETYPE_PEM) != SSL_SUCCESS)
+    {
+        LogError("unable to load x509 client private key");
+        result = __LINE__;
+    }
+#ifdef HAVE_SECURE_RENEGOTIATION
+    else if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) {
+        LogError("unable to enable secure renegotiation");
+        result = __LINE__;
+    }
+#endif 
+    else
+    {
+        result = 0;
+    }
+    return result;
+}
+
+static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
+{
+    wolfSSL_free(tls_io_instance->ssl);
+}
+
 static int create_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
 {
     int result;
@@ -367,6 +436,19 @@
             wolfSSL_CTX_free(tls_io_instance->ssl_context);
             result = __LINE__;
         }
+        /*x509 authentication can only be build before underlying connection is realized*/
+        else if ((tls_io_instance->x509certificate != NULL) &&
+            (tls_io_instance->x509privatekey != NULL) &&
+            (x509_wolfssl_add_credentials(tls_io_instance->ssl, tls_io_instance->x509certificate, tls_io_instance->x509privatekey) != 0))
+        {
+            destroy_wolfssl_instance(tls_io_instance);
+            tls_io_instance->ssl = NULL;
+            wolfSSL_CTX_free(tls_io_instance->ssl_context);
+            tls_io_instance->ssl_context = NULL;
+            LogError("unable to use x509 authentication");
+            result = __LINE__;
+        }
+
         else
         {
             tls_io_instance->socket_io_read_bytes = NULL;
@@ -388,11 +470,6 @@
     return result;
 }
 
-static void destroy_wolfssl_instance(TLS_IO_INSTANCE* tls_io_instance)
-{
-    wolfSSL_free(tls_io_instance->ssl);
-}
-
 int tlsio_wolfssl_init(void)
 {
     (void)wolfSSL_library_init();
@@ -430,6 +507,8 @@
             result->ssl = NULL;
             result->ssl_context = NULL;
             result->certificate = NULL;
+            result->x509certificate = NULL;
+            result->x509privatekey = NULL;
 
             result->on_bytes_received = NULL;
             result->on_bytes_received_context = NULL;
@@ -500,6 +579,16 @@
             free(tls_io_instance->certificate);
             tls_io_instance->certificate = NULL;
         }
+        if (tls_io_instance->x509certificate != NULL)
+        {
+            free(tls_io_instance->x509certificate);
+            tls_io_instance->x509certificate = NULL;
+        }
+        if (tls_io_instance->x509privatekey != NULL)
+        {
+            free(tls_io_instance->x509privatekey);
+            tls_io_instance->x509privatekey = NULL;
+        }
         wolfSSL_CTX_free(tls_io_instance->ssl_context);
         xio_destroy(tls_io_instance->socket_io);
         free(tls_io);
@@ -549,26 +638,14 @@
             else
             {
                 // The state can get changed in the on_underlying_io_open_complete
-                if (tls_io_instance->tlsio_state == TLSIO_STATE_ERROR)
+                if (tls_io_instance->tlsio_state != TLSIO_STATE_OPEN)
                 {
                     LogError("Failed to connect to server.  The certificates may not be correct.");
                     result = __LINE__;
                 }
                 else
                 {
-                    int res;
-                    tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
-                    res = wolfSSL_connect(tls_io_instance->ssl);
-                    if (res != SSL_SUCCESS)
-                    {
-                        LogError("Failed to connect to server.");
-                        tls_io_instance->tlsio_state = TLSIO_STATE_NOT_OPEN;
-                        result = __LINE__;
-                    }
-                    else
-                    {
-                        result = 0;
-                    }
+                    result = 0;
                 }
             }
         }
@@ -637,7 +714,7 @@
             tls_io_instance->on_send_complete_callback_context = callback_context;
 
             int res = wolfSSL_write(tls_io_instance->ssl, buffer, size);
-            if (res != size)
+            if ((res < 0) || ((size_t)res != size)) // Best way I can think of to safely compare an int to a size_t
             {
                 result = __LINE__;
             }
@@ -671,6 +748,26 @@
     return &tlsio_wolfssl_interface_description;
 }
 
+static int process_option(char** destination, const char* name, const char* value)
+{
+    int result;
+    if (*destination != NULL)
+    {
+        free(*destination);
+        *destination = NULL;
+    }
+    if (mallocAndStrcpy_s(destination, value) != 0)
+    {
+        LogError("unable to process option %s",name);
+        result = __LINE__;
+    }
+    else
+    {
+        result = 0;
+    }
+    return result;
+
+}
 int tlsio_wolfssl_setoption(CONCRETE_IO_HANDLE tls_io, const char* optionName, const void* value)
 {
     int result;
@@ -685,34 +782,27 @@
 
         if (strcmp("TrustedCerts", optionName) == 0)
         {
-            const char* cert = (const char*)value;
-            if (tls_io_instance->certificate != NULL)
-            {
-                // Free the memory if it has been previously allocated
-                free(tls_io_instance->certificate);
-            }
-
-            // Store the certificate
-            size_t len = strlen(cert);
-            tls_io_instance->certificate = (const char*)malloc(len+1);
-            if (tls_io_instance->certificate == NULL)
+            result  = process_option(&tls_io_instance->certificate, optionName, value);
+        }
+        else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+        {
+            result = process_option(&tls_io_instance->x509certificate, optionName, value);
+        }
+        else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+        {
+            result = process_option(&tls_io_instance->x509privatekey, optionName, value);
+        }
+        else
+        {
+            if (tls_io_instance->socket_io == NULL)
             {
                 result = __LINE__;
             }
             else
             {
-                (void)strcpy(tls_io_instance->certificate, cert);
-                result = 0;
+                result = xio_setoption(tls_io_instance->socket_io, optionName, value);
             }
         }
-        else if (tls_io_instance->socket_io == NULL)
-        {
-            result = __LINE__;
-        }
-        else
-        {
-            result = xio_setoption(tls_io_instance->socket_io, optionName, value);
-        }
     }
 
     return result;