BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file ServerConnection.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdio.h>
31 #include <string.h>
32 #include <stddef.h>
33  
34 #include <misc/debug.h>
35 #include <misc/strdup.h>
36 #include <base/BLog.h>
37  
38 #include <server_connection/ServerConnection.h>
39  
40 #include <generated/blog_channel_ServerConnection.h>
41  
42 #define STATE_CONNECTING 1
43 #define STATE_WAITINIT 2
44 #define STATE_COMPLETE 3
45  
46 static void report_error (ServerConnection *o);
47 static void connector_handler (ServerConnection *o, int is_error);
48 static void pending_handler (ServerConnection *o);
49 static SECStatus client_auth_data_callback (ServerConnection *o, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey);
50 static void connection_handler (ServerConnection *o, int event);
51 static void sslcon_handler (ServerConnection *o, int event);
52 static void decoder_handler_error (ServerConnection *o);
53 static void input_handler_send (ServerConnection *o, uint8_t *data, int data_len);
54 static void packet_hello (ServerConnection *o, uint8_t *data, int data_len);
55 static void packet_newclient (ServerConnection *o, uint8_t *data, int data_len);
56 static void packet_endclient (ServerConnection *o, uint8_t *data, int data_len);
57 static void packet_inmsg (ServerConnection *o, uint8_t *data, int data_len);
58 static int start_packet (ServerConnection *o, void **data, int len);
59 static void end_packet (ServerConnection *o, uint8_t type);
60 static void newclient_job_handler (ServerConnection *o);
61  
62 void report_error (ServerConnection *o)
63 {
64 DEBUGERROR(&o->d_err, o->handler_error(o->user))
65 }
66  
67 void connector_handler (ServerConnection *o, int is_error)
68 {
69 DebugObject_Access(&o->d_obj);
70 ASSERT(o->state == STATE_CONNECTING)
71 ASSERT(!o->buffers_released)
72  
73 // check connection attempt result
74 if (is_error) {
75 BLog(BLOG_ERROR, "connection failed");
76 goto fail0;
77 }
78  
79 BLog(BLOG_NOTICE, "connected");
80  
81 // init connection
82 if (!BConnection_Init(&o->con, BConnection_source_connector(&o->connector), o->reactor, o, (BConnection_handler)connection_handler)) {
83 BLog(BLOG_ERROR, "BConnection_Init failed");
84 goto fail0;
85 }
86  
87 // init connection interfaces
88 BConnection_SendAsync_Init(&o->con);
89 BConnection_RecvAsync_Init(&o->con);
90  
91 StreamPassInterface *send_iface = BConnection_SendAsync_GetIf(&o->con);
92 StreamRecvInterface *recv_iface = BConnection_RecvAsync_GetIf(&o->con);
93  
94 if (o->have_ssl) {
95 // create bottom NSPR file descriptor
96 if (!BSSLConnection_MakeBackend(&o->bottom_prfd, send_iface, recv_iface, o->twd, o->ssl_flags)) {
97 BLog(BLOG_ERROR, "BSSLConnection_MakeBackend failed");
98 goto fail0a;
99 }
100  
101 // create SSL file descriptor from the bottom NSPR file descriptor
102 if (!(o->ssl_prfd = SSL_ImportFD(NULL, &o->bottom_prfd))) {
103 BLog(BLOG_ERROR, "SSL_ImportFD failed");
104 ASSERT_FORCE(PR_Close(&o->bottom_prfd) == PR_SUCCESS)
105 goto fail0a;
106 }
107  
108 // set client mode
109 if (SSL_ResetHandshake(o->ssl_prfd, PR_FALSE) != SECSuccess) {
110 BLog(BLOG_ERROR, "SSL_ResetHandshake failed");
111 goto fail1;
112 }
113  
114 // set server name
115 if (SSL_SetURL(o->ssl_prfd, o->server_name) != SECSuccess) {
116 BLog(BLOG_ERROR, "SSL_SetURL failed");
117 goto fail1;
118 }
119  
120 // set client certificate callback
121 if (SSL_GetClientAuthDataHook(o->ssl_prfd, (SSLGetClientAuthData)client_auth_data_callback, o) != SECSuccess) {
122 BLog(BLOG_ERROR, "SSL_GetClientAuthDataHook failed");
123 goto fail1;
124 }
125  
126 // init BSSLConnection
127 BSSLConnection_Init(&o->sslcon, o->ssl_prfd, 0, BReactor_PendingGroup(o->reactor), o, (BSSLConnection_handler)sslcon_handler);
128  
129 send_iface = BSSLConnection_GetSendIf(&o->sslcon);
130 recv_iface = BSSLConnection_GetRecvIf(&o->sslcon);
131 }
132  
133 // init input chain
134 PacketPassInterface_Init(&o->input_interface, SC_MAX_ENC, (PacketPassInterface_handler_send)input_handler_send, o, BReactor_PendingGroup(o->reactor));
135 if (!PacketProtoDecoder_Init(&o->input_decoder, recv_iface, &o->input_interface, BReactor_PendingGroup(o->reactor), o, (PacketProtoDecoder_handler_error)decoder_handler_error)) {
136 BLog(BLOG_ERROR, "PacketProtoDecoder_Init failed");
137 goto fail2;
138 }
139  
140 // set job to send hello
141 // this needs to be in here because hello sending must be done after sending started (so we can write into the send buffer),
142 // but before receiving started (so we don't get into conflict with the user sending packets)
143 BPending_Init(&o->start_job, BReactor_PendingGroup(o->reactor), (BPending_handler)pending_handler, o);
144 BPending_Set(&o->start_job);
145  
146 // init keepalive output branch
147 SCKeepaliveSource_Init(&o->output_ka_zero, BReactor_PendingGroup(o->reactor));
148 PacketProtoEncoder_Init(&o->output_ka_encoder, SCKeepaliveSource_GetOutput(&o->output_ka_zero), BReactor_PendingGroup(o->reactor));
149  
150 // init output common
151  
152 // init sender
153 PacketStreamSender_Init(&o->output_sender, send_iface, PACKETPROTO_ENCLEN(SC_MAX_ENC), BReactor_PendingGroup(o->reactor));
154  
155 // init keepalives
156 if (!KeepaliveIO_Init(&o->output_keepaliveio, o->reactor, PacketStreamSender_GetInput(&o->output_sender), PacketProtoEncoder_GetOutput(&o->output_ka_encoder), o->keepalive_interval)) {
157 BLog(BLOG_ERROR, "KeepaliveIO_Init failed");
158 goto fail3;
159 }
160  
161 // init queue
162 PacketPassPriorityQueue_Init(&o->output_queue, KeepaliveIO_GetInput(&o->output_keepaliveio), BReactor_PendingGroup(o->reactor), 0);
163  
164 // init output local flow
165  
166 // init queue flow
167 PacketPassPriorityQueueFlow_Init(&o->output_local_qflow, &o->output_queue, 0);
168  
169 // init PacketProtoFlow
170 if (!PacketProtoFlow_Init(&o->output_local_oflow, SC_MAX_ENC, o->buffer_size, PacketPassPriorityQueueFlow_GetInput(&o->output_local_qflow), BReactor_PendingGroup(o->reactor))) {
171 BLog(BLOG_ERROR, "PacketProtoFlow_Init failed");
172 goto fail4;
173 }
174 o->output_local_if = PacketProtoFlow_GetInput(&o->output_local_oflow);
175  
176 // have no output packet
177 o->output_local_packet_len = -1;
178  
179 // init output user flow
180 PacketPassPriorityQueueFlow_Init(&o->output_user_qflow, &o->output_queue, 1);
181  
182 // update state
183 o->state = STATE_WAITINIT;
184  
185 return;
186  
187 fail4:
188 PacketPassPriorityQueueFlow_Free(&o->output_local_qflow);
189 PacketPassPriorityQueue_Free(&o->output_queue);
190 KeepaliveIO_Free(&o->output_keepaliveio);
191 fail3:
192 PacketStreamSender_Free(&o->output_sender);
193 PacketProtoEncoder_Free(&o->output_ka_encoder);
194 SCKeepaliveSource_Free(&o->output_ka_zero);
195 BPending_Free(&o->start_job);
196 PacketProtoDecoder_Free(&o->input_decoder);
197 fail2:
198 PacketPassInterface_Free(&o->input_interface);
199 if (o->have_ssl) {
200 BSSLConnection_Free(&o->sslcon);
201 fail1:
202 ASSERT_FORCE(PR_Close(o->ssl_prfd) == PR_SUCCESS)
203 }
204 fail0a:
205 BConnection_RecvAsync_Free(&o->con);
206 BConnection_SendAsync_Free(&o->con);
207 BConnection_Free(&o->con);
208 fail0:
209 // report error
210 report_error(o);
211 }
212  
213 void pending_handler (ServerConnection *o)
214 {
215 ASSERT(o->state == STATE_WAITINIT)
216 ASSERT(!o->buffers_released)
217 DebugObject_Access(&o->d_obj);
218  
219 // send hello
220 struct sc_client_hello omsg;
221 void *packet;
222 if (!start_packet(o, &packet, sizeof(omsg))) {
223 BLog(BLOG_ERROR, "no buffer for hello");
224 report_error(o);
225 return;
226 }
227 omsg.version = htol16(SC_VERSION);
228 memcpy(packet, &omsg, sizeof(omsg));
229 end_packet(o, SCID_CLIENTHELLO);
230 }
231  
232 SECStatus client_auth_data_callback (ServerConnection *o, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
233 {
234 ASSERT(o->have_ssl)
235 DebugObject_Access(&o->d_obj);
236  
237 CERTCertificate *newcert;
238 if (!(newcert = CERT_DupCertificate(o->client_cert))) {
239 return SECFailure;
240 }
241  
242 SECKEYPrivateKey *newkey;
243 if (!(newkey = SECKEY_CopyPrivateKey(o->client_key))) {
244 CERT_DestroyCertificate(newcert);
245 return SECFailure;
246 }
247  
248 *pRetCert = newcert;
249 *pRetKey = newkey;
250 return SECSuccess;
251 }
252  
253 void connection_handler (ServerConnection *o, int event)
254 {
255 DebugObject_Access(&o->d_obj);
256 ASSERT(o->state >= STATE_WAITINIT)
257 ASSERT(!o->buffers_released)
258  
259 if (event == BCONNECTION_EVENT_RECVCLOSED) {
260 BLog(BLOG_INFO, "connection closed");
261 } else {
262 BLog(BLOG_INFO, "connection error");
263 }
264  
265 report_error(o);
266 return;
267 }
268  
269 void sslcon_handler (ServerConnection *o, int event)
270 {
271 DebugObject_Access(&o->d_obj);
272 ASSERT(o->have_ssl)
273 ASSERT(o->state >= STATE_WAITINIT)
274 ASSERT(!o->buffers_released)
275 ASSERT(event == BSSLCONNECTION_EVENT_ERROR)
276  
277 BLog(BLOG_ERROR, "SSL error");
278  
279 report_error(o);
280 return;
281 }
282  
283 void decoder_handler_error (ServerConnection *o)
284 {
285 DebugObject_Access(&o->d_obj);
286 ASSERT(o->state >= STATE_WAITINIT)
287 ASSERT(!o->buffers_released)
288  
289 BLog(BLOG_ERROR, "decoder error");
290  
291 report_error(o);
292 return;
293 }
294  
295 void input_handler_send (ServerConnection *o, uint8_t *data, int data_len)
296 {
297 ASSERT(o->state >= STATE_WAITINIT)
298 ASSERT(!o->buffers_released)
299 ASSERT(data_len >= 0)
300 ASSERT(data_len <= SC_MAX_ENC)
301 DebugObject_Access(&o->d_obj);
302  
303 // accept packet
304 PacketPassInterface_Done(&o->input_interface);
305  
306 // parse header
307 if (data_len < sizeof(struct sc_header)) {
308 BLog(BLOG_ERROR, "packet too short (no sc header)");
309 report_error(o);
310 return;
311 }
312 struct sc_header header;
313 memcpy(&header, data, sizeof(header));
314 data += sizeof(header);
315 data_len -= sizeof(header);
316 uint8_t type = ltoh8(header.type);
317  
318 // call appropriate handler based on packet type
319 switch (type) {
320 case SCID_SERVERHELLO:
321 packet_hello(o, data, data_len);
322 return;
323 case SCID_NEWCLIENT:
324 packet_newclient(o, data, data_len);
325 return;
326 case SCID_ENDCLIENT:
327 packet_endclient(o, data, data_len);
328 return;
329 case SCID_INMSG:
330 packet_inmsg(o, data, data_len);
331 return;
332 default:
333 BLog(BLOG_ERROR, "unknown packet type %d", (int)type);
334 report_error(o);
335 return;
336 }
337 }
338  
339 void packet_hello (ServerConnection *o, uint8_t *data, int data_len)
340 {
341 if (o->state != STATE_WAITINIT) {
342 BLog(BLOG_ERROR, "hello: not expected");
343 report_error(o);
344 return;
345 }
346  
347 if (data_len != sizeof(struct sc_server_hello)) {
348 BLog(BLOG_ERROR, "hello: invalid length");
349 report_error(o);
350 return;
351 }
352 struct sc_server_hello msg;
353 memcpy(&msg, data, sizeof(msg));
354 peerid_t id = ltoh16(msg.id);
355  
356 // change state
357 o->state = STATE_COMPLETE;
358  
359 // report
360 o->handler_ready(o->user, id, msg.clientAddr);
361 return;
362 }
363  
364 void packet_newclient (ServerConnection *o, uint8_t *data, int data_len)
365 {
366 if (o->state != STATE_COMPLETE) {
367 BLog(BLOG_ERROR, "newclient: not expected");
368 report_error(o);
369 return;
370 }
371  
372 if (data_len < sizeof(struct sc_server_newclient) || data_len > sizeof(struct sc_server_newclient) + SCID_NEWCLIENT_MAX_CERT_LEN) {
373 BLog(BLOG_ERROR, "newclient: invalid length");
374 report_error(o);
375 return;
376 }
377  
378 struct sc_server_newclient msg;
379 memcpy(&msg, data, sizeof(msg));
380 peerid_t id = ltoh16(msg.id);
381  
382 // schedule reporting new client
383 o->newclient_data = data;
384 o->newclient_data_len = data_len;
385 BPending_Set(&o->newclient_job);
386  
387 // send acceptpeer
388 struct sc_client_acceptpeer omsg;
389 void *packet;
390 if (!start_packet(o, &packet, sizeof(omsg))) {
391 BLog(BLOG_ERROR, "newclient: out of buffer for acceptpeer");
392 report_error(o);
393 return;
394 }
395 omsg.clientid = htol16(id);
396 memcpy(packet, &omsg, sizeof(omsg));
397 end_packet(o, SCID_ACCEPTPEER);
398 }
399  
400 void packet_endclient (ServerConnection *o, uint8_t *data, int data_len)
401 {
402 if (o->state != STATE_COMPLETE) {
403 BLog(BLOG_ERROR, "endclient: not expected");
404 report_error(o);
405 return;
406 }
407  
408 if (data_len != sizeof(struct sc_server_endclient)) {
409 BLog(BLOG_ERROR, "endclient: invalid length");
410 report_error(o);
411 return;
412 }
413  
414 struct sc_server_endclient msg;
415 memcpy(&msg, data, sizeof(msg));
416 peerid_t id = ltoh16(msg.id);
417  
418 // report
419 o->handler_endclient(o->user, id);
420 return;
421 }
422  
423 void packet_inmsg (ServerConnection *o, uint8_t *data, int data_len)
424 {
425 if (o->state != STATE_COMPLETE) {
426 BLog(BLOG_ERROR, "inmsg: not expected");
427 report_error(o);
428 return;
429 }
430  
431 if (data_len < sizeof(struct sc_server_inmsg)) {
432 BLog(BLOG_ERROR, "inmsg: missing header");
433 report_error(o);
434 return;
435 }
436  
437 if (data_len > sizeof(struct sc_server_inmsg) + SC_MAX_MSGLEN) {
438 BLog(BLOG_ERROR, "inmsg: too long");
439 report_error(o);
440 return;
441 }
442  
443 struct sc_server_inmsg msg;
444 memcpy(&msg, data, sizeof(msg));
445 peerid_t peer_id = ltoh16(msg.clientid);
446 uint8_t *payload = data + sizeof(struct sc_server_inmsg);
447 int payload_len = data_len - sizeof(struct sc_server_inmsg);
448  
449 // report
450 o->handler_message(o->user, peer_id, payload, payload_len);
451 return;
452 }
453  
454 int start_packet (ServerConnection *o, void **data, int len)
455 {
456 ASSERT(o->state >= STATE_WAITINIT)
457 ASSERT(o->output_local_packet_len == -1)
458 ASSERT(len >= 0)
459 ASSERT(len <= SC_MAX_PAYLOAD)
460 ASSERT(data || len == 0)
461  
462 // obtain memory location
463 if (!BufferWriter_StartPacket(o->output_local_if, &o->output_local_packet)) {
464 BLog(BLOG_ERROR, "out of buffer");
465 return 0;
466 }
467  
468 o->output_local_packet_len = len;
469  
470 if (data) {
471 *data = o->output_local_packet + sizeof(struct sc_header);
472 }
473  
474 return 1;
475 }
476  
477 void end_packet (ServerConnection *o, uint8_t type)
478 {
479 ASSERT(o->state >= STATE_WAITINIT)
480 ASSERT(o->output_local_packet_len >= 0)
481 ASSERT(o->output_local_packet_len <= SC_MAX_PAYLOAD)
482  
483 // write header
484 struct sc_header header;
485 header.type = htol8(type);
486 memcpy(o->output_local_packet, &header, sizeof(header));
487  
488 // finish writing packet
489 BufferWriter_EndPacket(o->output_local_if, sizeof(struct sc_header) + o->output_local_packet_len);
490  
491 o->output_local_packet_len = -1;
492 }
493  
494 int ServerConnection_Init (
495 ServerConnection *o,
496 BReactor *reactor,
497 BThreadWorkDispatcher *twd,
498 BAddr addr,
499 int keepalive_interval,
500 int buffer_size,
501 int have_ssl,
502 int ssl_flags,
503 CERTCertificate *client_cert,
504 SECKEYPrivateKey *client_key,
505 const char *server_name,
506 void *user,
507 ServerConnection_handler_error handler_error,
508 ServerConnection_handler_ready handler_ready,
509 ServerConnection_handler_newclient handler_newclient,
510 ServerConnection_handler_endclient handler_endclient,
511 ServerConnection_handler_message handler_message
512 )
513 {
514 ASSERT(keepalive_interval > 0)
515 ASSERT(buffer_size > 0)
516 ASSERT(have_ssl == 0 || have_ssl == 1)
517 ASSERT(!have_ssl || server_name)
518  
519 // init arguments
520 o->reactor = reactor;
521 o->twd = twd;
522 o->keepalive_interval = keepalive_interval;
523 o->buffer_size = buffer_size;
524 o->have_ssl = have_ssl;
525 if (have_ssl) {
526 o->ssl_flags = ssl_flags;
527 o->client_cert = client_cert;
528 o->client_key = client_key;
529 }
530 o->user = user;
531 o->handler_error = handler_error;
532 o->handler_ready = handler_ready;
533 o->handler_newclient = handler_newclient;
534 o->handler_endclient = handler_endclient;
535 o->handler_message = handler_message;
536  
537 o->server_name = NULL;
538 if (have_ssl && !(o->server_name = b_strdup(server_name))) {
539 BLog(BLOG_ERROR, "malloc failed");
540 goto fail0;
541 }
542  
543 if (!BConnection_AddressSupported(addr)) {
544 BLog(BLOG_ERROR, "BConnection_AddressSupported failed");
545 goto fail1;
546 }
547  
548 // init connector
549 if (!BConnector_Init(&o->connector, addr, o->reactor, o, (BConnector_handler)connector_handler)) {
550 BLog(BLOG_ERROR, "BConnector_Init failed");
551 goto fail1;
552 }
553  
554 // init newclient job
555 BPending_Init(&o->newclient_job, BReactor_PendingGroup(o->reactor), (BPending_handler)newclient_job_handler, o);
556  
557 // set state
558 o->state = STATE_CONNECTING;
559 o->buffers_released = 0;
560  
561 DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
562 DebugObject_Init(&o->d_obj);
563 return 1;
564  
565 fail1:
566 free(o->server_name);
567 fail0:
568 return 0;
569 }
570  
571 void ServerConnection_Free (ServerConnection *o)
572 {
573 DebugObject_Free(&o->d_obj);
574 DebugError_Free(&o->d_err);
575  
576 if (o->state > STATE_CONNECTING) {
577 // allow freeing queue flows
578 PacketPassPriorityQueue_PrepareFree(&o->output_queue);
579  
580 // stop using any buffers before they get freed
581 if (o->have_ssl && !o->buffers_released) {
582 BSSLConnection_ReleaseBuffers(&o->sslcon);
583 }
584  
585 // free output user flow
586 PacketPassPriorityQueueFlow_Free(&o->output_user_qflow);
587  
588 // free output local flow
589 PacketProtoFlow_Free(&o->output_local_oflow);
590 PacketPassPriorityQueueFlow_Free(&o->output_local_qflow);
591  
592 // free output common
593 PacketPassPriorityQueue_Free(&o->output_queue);
594 KeepaliveIO_Free(&o->output_keepaliveio);
595 PacketStreamSender_Free(&o->output_sender);
596  
597 // free output keep-alive branch
598 PacketProtoEncoder_Free(&o->output_ka_encoder);
599 SCKeepaliveSource_Free(&o->output_ka_zero);
600  
601 // free job
602 BPending_Free(&o->start_job);
603  
604 // free input chain
605 PacketProtoDecoder_Free(&o->input_decoder);
606 PacketPassInterface_Free(&o->input_interface);
607  
608 // free SSL
609 if (o->have_ssl) {
610 BSSLConnection_Free(&o->sslcon);
611 ASSERT_FORCE(PR_Close(o->ssl_prfd) == PR_SUCCESS)
612 }
613  
614 // free connection interfaces
615 BConnection_RecvAsync_Free(&o->con);
616 BConnection_SendAsync_Free(&o->con);
617  
618 // free connection
619 BConnection_Free(&o->con);
620 }
621  
622 // free newclient job
623 BPending_Free(&o->newclient_job);
624  
625 // free connector
626 BConnector_Free(&o->connector);
627  
628 // free server name
629 free(o->server_name);
630 }
631  
632 void ServerConnection_ReleaseBuffers (ServerConnection *o)
633 {
634 DebugObject_Access(&o->d_obj);
635 ASSERT(!o->buffers_released)
636  
637 if (o->state > STATE_CONNECTING && o->have_ssl) {
638 BSSLConnection_ReleaseBuffers(&o->sslcon);
639 }
640  
641 o->buffers_released = 1;
642 }
643  
644 PacketPassInterface * ServerConnection_GetSendInterface (ServerConnection *o)
645 {
646 ASSERT(o->state == STATE_COMPLETE)
647 DebugError_AssertNoError(&o->d_err);
648 DebugObject_Access(&o->d_obj);
649  
650 return PacketPassPriorityQueueFlow_GetInput(&o->output_user_qflow);
651 }
652  
653 void newclient_job_handler (ServerConnection *o)
654 {
655 DebugObject_Access(&o->d_obj);
656 ASSERT(o->state == STATE_COMPLETE)
657  
658 struct sc_server_newclient msg;
659 memcpy(&msg, o->newclient_data, sizeof(msg));
660 peerid_t id = ltoh16(msg.id);
661 int flags = ltoh16(msg.flags);
662  
663 uint8_t *cert_data = o->newclient_data + sizeof(msg);
664 int cert_len = o->newclient_data_len - sizeof(msg);
665  
666 // report new client
667 o->handler_newclient(o->user, id, flags, cert_data, cert_len);
668 return;
669 }