5 void state_machine_init(state_machine_t
*machine
)
8 machine
->bio_intossl
= machine
->bio_fromssl
= NULL
;
9 buffer_init(&machine
->clean_in
);
10 buffer_init(&machine
->clean_out
);
11 buffer_init(&machine
->dirty_in
);
12 buffer_init(&machine
->dirty_out
);
15 void state_machine_close(state_machine_t
*machine
)
18 SSL_free(machine
->ssl
);
19 /* SSL_free seems to decrement the reference counts already so doing this goes
22 if(machine
->bio_intossl
)
23 BIO_free(machine
->bio_intossl
);
24 if(machine
->bio_fromssl
)
25 BIO_free(machine
->bio_fromssl
);
27 buffer_close(&machine
->clean_in
);
28 buffer_close(&machine
->clean_out
);
29 buffer_close(&machine
->dirty_in
);
30 buffer_close(&machine
->dirty_out
);
31 state_machine_init(machine
);
34 buffer_t
*state_machine_get_buffer(state_machine_t
*machine
, sm_buffer_t type
)
38 return &machine
->clean_in
;
40 return &machine
->clean_out
;
42 return &machine
->dirty_in
;
44 return &machine
->dirty_out
;
48 /* Should never get here */
53 SSL
*state_machine_get_SSL(state_machine_t
*machine
)
58 int state_machine_set_SSL(state_machine_t
*machine
, SSL
*ssl
, int is_server
)
61 /* Shouldn't ever be set twice */
64 /* Create the BIOs to handle the dirty side of the SSL */
65 if((machine
->bio_intossl
= BIO_new(BIO_s_mem())) == NULL
)
67 if((machine
->bio_fromssl
= BIO_new(BIO_s_mem())) == NULL
)
69 /* Hook up the BIOs on the dirty side of the SSL */
70 SSL_set_bio(machine
->ssl
, machine
->bio_intossl
, machine
->bio_fromssl
);
72 SSL_set_accept_state(machine
->ssl
);
74 SSL_set_connect_state(machine
->ssl
);
75 /* If we're the first one to generate traffic - do it now otherwise we
76 * go into the next select empty-handed and our peer will not send data
77 * but will similarly wait for us. */
78 return state_machine_churn(machine
);
81 /* Performs the data-IO loop and returns zero if the machine should close */
82 int state_machine_churn(state_machine_t
*machine
)
85 if(machine
->ssl
== NULL
) {
86 if(buffer_empty(&machine
->clean_out
))
87 /* Time to close this state-machine altogether */
90 /* Still buffered data on the clean side to go out */
93 /* Do this loop twice to cover any dependencies about which precise
94 * order of reads and writes is required. */
95 for(loop
= 0; loop
< 2; loop
++) {
96 buffer_to_SSL(&machine
->clean_in
, machine
->ssl
);
97 buffer_to_BIO(&machine
->dirty_in
, machine
->bio_intossl
);
98 buffer_from_SSL(&machine
->clean_out
, machine
->ssl
);
99 buffer_from_BIO(&machine
->dirty_out
, machine
->bio_fromssl
);
101 /* We close on the SSL side if the info callback noticed some problems
102 * or an SSL shutdown was underway and shutdown traffic had all been
104 if(SSL_get_app_data(machine
->ssl
) || (SSL_get_shutdown(machine
->ssl
) &&
105 buffer_empty(&machine
->dirty_out
))) {
106 /* Great, we can seal off the dirty side completely */
107 if(!state_machine_close_dirty(machine
))
110 /* Either the SSL is alive and well, or the closing process still has
111 * outgoing data waiting to be sent */
115 /* Called when the clean side of the SSL has lost its connection */
116 int state_machine_close_clean(state_machine_t
*machine
)
118 /* Well, first thing to do is null out the clean-side buffers - they're
119 * no use any more. */
120 buffer_close(&machine
->clean_in
);
121 buffer_close(&machine
->clean_out
);
122 /* And start an SSL shutdown */
124 SSL_shutdown(machine
->ssl
);
125 /* This is an "event", so flush the SSL of any generated traffic */
126 state_machine_churn(machine
);
127 if(buffer_empty(&machine
->dirty_in
) &&
128 buffer_empty(&machine
->dirty_out
))
133 /* Called when the dirty side of the SSL has lost its connection. This is pretty
134 * terminal as all that can be left to do is send any buffered output on the
135 * clean side - after that, we're done. */
136 int state_machine_close_dirty(state_machine_t
*machine
)
138 buffer_close(&machine
->dirty_in
);
139 buffer_close(&machine
->dirty_out
);
140 buffer_close(&machine
->clean_in
);
142 SSL_free(machine
->ssl
);
144 machine
->bio_intossl
= machine
->bio_fromssl
= NULL
;
145 if(buffer_empty(&machine
->clean_out
))
150 #endif /* !defined(NO_TUNALA) */