PageRenderTime 104ms CodeModel.GetById 2ms app.highlight 93ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/Footagehead-1.3.2/libwired/libwired/net/wi-socket.c

https://bitbucket.org/balrog/zanka-full
C | 1696 lines | 1093 code | 577 blank | 26 comment | 215 complexity | 116f45e6588c23e69ca7ac7b90b31f5c MD5 | raw file
   1/* $Id$ */
   2
   3/*
   4 *  Copyright (c) 2003-2009 Axel Andersson
   5 *  All rights reserved.
   6 *
   7 *  Redistribution and use in source and binary forms, with or without
   8 *  modification, are permitted provided that the following conditions
   9 *  are met:
  10 *  1. Redistributions of source code must retain the above copyright
  11 *     notice, this list of conditions and the following disclaimer.
  12 *  2. Redistributions in binary form must reproduce the above copyright
  13 *     notice, this list of conditions and the following disclaimer in the
  14 *     documentation and/or other materials provided with the distribution.
  15 *
  16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26 * POSSIBILITY OF SUCH DAMAGE.
  27 */
  28
  29#include "config.h"
  30
  31#include <sys/param.h>
  32#include <sys/types.h>
  33#include <sys/time.h>
  34#include <sys/socket.h>
  35#include <netinet/in.h>
  36
  37#ifdef HAVE_NETINET_IN_SYSTM_H
  38#include <netinet/in_systm.h>
  39#endif
  40
  41#ifdef HAVE_NETINET_IP_H
  42#include <netinet/ip.h>
  43#endif
  44
  45#include <netinet/tcp.h>
  46#include <netdb.h>
  47#include <net/if.h>
  48#include <fcntl.h>
  49#include <unistd.h>
  50#include <stdio.h>
  51#include <string.h>
  52#include <errno.h>
  53
  54#ifdef HAVE_OPENSSL_SSL_H
  55#include <openssl/err.h>
  56#include <openssl/ssl.h>
  57#endif
  58
  59#ifdef HAVE_IFADDRS_H
  60#include <ifaddrs.h>
  61#endif
  62
  63#include <wired/wi-array.h>
  64#include <wired/wi-assert.h>
  65#include <wired/wi-address.h>
  66#include <wired/wi-date.h>
  67#include <wired/wi-macros.h>
  68#include <wired/wi-lock.h>
  69#include <wired/wi-private.h>
  70#include <wired/wi-rsa.h>
  71#include <wired/wi-socket.h>
  72#include <wired/wi-string.h>
  73#include <wired/wi-system.h>
  74#include <wired/wi-thread.h>
  75#include <wired/wi-x509.h>
  76
  77#define _WI_SOCKET_BUFFER_MAX_SIZE		131072
  78
  79
  80struct _wi_socket_tls {
  81	wi_runtime_base_t					base;
  82	
  83#ifdef HAVE_OPENSSL_SSL_H
  84	SSL_CTX								*ssl_ctx;
  85	DH									*dh;
  86	wi_boolean_t						private_key;
  87#endif
  88};
  89
  90
  91struct _wi_socket {
  92	wi_runtime_base_t					base;
  93	
  94	wi_address_t						*address;
  95	wi_socket_type_t					type;
  96	wi_uinteger_t						direction;
  97	int									sd;
  98
  99#ifdef HAVE_OPENSSL_SSL_H
 100	SSL									*ssl;
 101#endif
 102	
 103	void								*data;
 104	
 105	wi_string_t							*buffer;
 106	
 107	wi_boolean_t						interactive;
 108	wi_boolean_t						close;
 109	wi_boolean_t						broken;
 110};
 111
 112
 113#if defined(HAVE_OPENSSL_SSL_H) && defined(WI_PTHREADS)
 114static unsigned long					_wi_socket_ssl_id_function(void);
 115static void								_wi_socket_ssl_locking_function(int, int, const char *, int);
 116#endif
 117
 118#ifdef HAVE_OPENSSL_SSL_H
 119static void								_wi_socket_tls_dealloc(wi_runtime_instance_t *);
 120#endif
 121
 122static void								_wi_socket_dealloc(wi_runtime_instance_t *);
 123static wi_string_t *					_wi_socket_description(wi_runtime_instance_t *);
 124
 125static wi_boolean_t						_wi_socket_set_option_int(wi_socket_t *, int, int, int);
 126static wi_boolean_t						_wi_socket_get_option_int(wi_socket_t *, int, int, int *);
 127
 128
 129#if defined(HAVE_OPENSSL_SSL_H) && defined(WI_PTHREADS)
 130static wi_array_t						*_wi_socket_ssl_locks;
 131#endif
 132
 133#ifdef HAVE_OPENSSL_SSL_H
 134
 135static wi_runtime_id_t					_wi_socket_tls_runtime_id = WI_RUNTIME_ID_NULL;
 136static wi_runtime_class_t				_wi_socket_tls_runtime_class = {
 137	"wi_socket_tls_t",
 138	_wi_socket_tls_dealloc,
 139	NULL,
 140	NULL,
 141	NULL,
 142	NULL
 143};
 144
 145#endif
 146
 147static wi_runtime_id_t					_wi_socket_runtime_id = WI_RUNTIME_ID_NULL;
 148static wi_runtime_class_t				_wi_socket_runtime_class = {
 149	"wi_socket_t",
 150	_wi_socket_dealloc,
 151	NULL,
 152	NULL,
 153	_wi_socket_description,
 154	NULL
 155};
 156
 157
 158
 159void wi_socket_register(void) {
 160#ifdef HAVE_OPENSSL_SSL_H
 161	_wi_socket_tls_runtime_id = wi_runtime_register_class(&_wi_socket_tls_runtime_class);
 162#endif
 163	
 164	_wi_socket_runtime_id = wi_runtime_register_class(&_wi_socket_runtime_class);
 165}
 166
 167
 168
 169void wi_socket_initialize(void) {
 170#ifdef HAVE_OPENSSL_SSL_H
 171#ifdef WI_PTHREADS
 172	wi_lock_t		*lock;
 173	wi_uinteger_t	i, count;
 174#endif
 175
 176	SSL_library_init();
 177
 178#ifdef WI_PTHREADS
 179	count = CRYPTO_num_locks();
 180	_wi_socket_ssl_locks = wi_array_init_with_capacity(wi_array_alloc(), count);
 181	
 182	for(i = 0; i < count; i++) {
 183		lock = wi_lock_init(wi_lock_alloc());
 184		wi_array_add_data(_wi_socket_ssl_locks, lock);
 185		wi_release(lock);
 186	}
 187
 188	CRYPTO_set_id_callback(_wi_socket_ssl_id_function);
 189	CRYPTO_set_locking_callback(_wi_socket_ssl_locking_function);
 190#endif
 191#endif
 192}
 193
 194
 195
 196#pragma mark -
 197
 198#if defined(HAVE_OPENSSL_SSL_H) && defined(WI_PTHREADS)
 199
 200static unsigned long _wi_socket_ssl_id_function(void) {
 201	return ((unsigned long) wi_thread_current_thread());
 202}
 203
 204
 205
 206static void _wi_socket_ssl_locking_function(int mode, int n, const char *file, int line) {
 207	wi_lock_t		*lock;
 208	
 209	lock = WI_ARRAY(_wi_socket_ssl_locks, n);
 210	
 211	if(mode & CRYPTO_LOCK)
 212		wi_lock_lock(lock);
 213	else
 214		wi_lock_unlock(lock);
 215}
 216
 217#endif
 218
 219
 220
 221#pragma mark -
 222
 223void wi_socket_exit_thread(void) {
 224#ifdef HAVE_OPENSSL_SSL_H
 225	ERR_remove_state(0);
 226#endif
 227}
 228
 229
 230
 231#pragma mark -
 232
 233#ifdef HAVE_OPENSSL_SSL_H
 234
 235wi_runtime_id_t wi_socket_tls_runtime_id(void) {
 236	return _wi_socket_tls_runtime_id;
 237}
 238
 239
 240
 241#pragma mark -
 242
 243wi_socket_tls_t * wi_socket_tls_alloc(void) {
 244	return wi_runtime_create_instance(_wi_socket_tls_runtime_id, sizeof(wi_socket_tls_t));
 245}
 246
 247
 248
 249wi_socket_tls_t * wi_socket_tls_init_with_type(wi_socket_tls_t *tls, wi_socket_tls_type_t type) {
 250	SSL_METHOD		*method;
 251	
 252	switch(type) {
 253		default:
 254		case WI_SOCKET_TLS_CLIENT:
 255			method = TLSv1_client_method();
 256			break;
 257
 258		case WI_SOCKET_TLS_SERVER:
 259			method = TLSv1_server_method();
 260			break;
 261	}
 262	
 263	tls->ssl_ctx = SSL_CTX_new(method);
 264	
 265	if(!tls->ssl_ctx) {
 266		wi_error_set_openssl_error();
 267		
 268		wi_release(NULL);
 269		
 270		return NULL;
 271	}
 272	
 273	SSL_CTX_set_mode(tls->ssl_ctx, SSL_MODE_AUTO_RETRY);
 274	SSL_CTX_set_quiet_shutdown(tls->ssl_ctx, 1);
 275	
 276	return tls;
 277}
 278
 279
 280
 281static void _wi_socket_tls_dealloc(wi_runtime_instance_t *instance) {
 282	wi_socket_tls_t		*tls = instance;
 283	
 284	if(tls->ssl_ctx)
 285		SSL_CTX_free(tls->ssl_ctx);
 286	
 287	if(tls->dh)
 288		DH_free(tls->dh);
 289}
 290
 291
 292
 293#pragma mark -
 294
 295wi_boolean_t wi_socket_tls_set_certificate(wi_socket_tls_t *tls, wi_x509_t *x509) {
 296	if(SSL_CTX_use_certificate(tls->ssl_ctx, wi_x509_x509(x509)) != 1) {
 297		wi_error_set_openssl_error();
 298
 299		return false;
 300	}
 301	
 302	return true;
 303}
 304
 305
 306
 307wi_boolean_t wi_socket_tls_set_private_key(wi_socket_tls_t *tls, wi_rsa_t *rsa) {
 308	tls->private_key = false;
 309	
 310	if(SSL_CTX_use_RSAPrivateKey(tls->ssl_ctx, wi_rsa_rsa(rsa)) != 1) {
 311		wi_error_set_openssl_error();
 312
 313		return false;
 314	}
 315	
 316	tls->private_key = true;
 317	
 318	return true;
 319}
 320
 321
 322
 323wi_boolean_t wi_socket_tls_set_ciphers(wi_socket_tls_t *tls, wi_string_t *ciphers) {
 324	if(SSL_CTX_set_cipher_list(tls->ssl_ctx, wi_string_cstring(ciphers)) != 1) {
 325		wi_error_set_libwired_error(WI_ERROR_SOCKET_NOVALIDCIPHER);
 326
 327		return false;
 328	}
 329	
 330	return true;
 331}
 332
 333
 334
 335wi_boolean_t wi_socket_tls_set_dh(wi_socket_tls_t *tls, const unsigned char *p, size_t p_size, const unsigned char *g, size_t g_size) {
 336	tls->dh = DH_new();
 337	
 338	if(!tls->dh) {
 339		wi_error_set_openssl_error();
 340
 341		return false;
 342	}
 343
 344	tls->dh->p = BN_bin2bn(p, p_size, NULL);
 345	tls->dh->g = BN_bin2bn(g, g_size, NULL);
 346
 347	if(!tls->dh->p || !tls->dh->g) {
 348		wi_error_set_openssl_error();
 349
 350		DH_free(tls->dh);
 351		tls->dh = NULL;
 352		
 353		return false;
 354	}
 355	
 356	return true;
 357}
 358
 359#endif
 360
 361
 362
 363#pragma mark -
 364
 365wi_runtime_id_t wi_socket_runtime_id(void) {
 366	return _wi_socket_runtime_id;
 367}
 368
 369
 370
 371#pragma mark -
 372
 373wi_socket_t * wi_socket_with_address(wi_address_t *address, wi_socket_type_t type) {
 374	return wi_autorelease(wi_socket_init_with_address(wi_socket_alloc(), address, type));
 375}
 376
 377
 378
 379#pragma mark -
 380
 381wi_socket_t * wi_socket_alloc(void) {
 382	return wi_runtime_create_instance(_wi_socket_runtime_id, sizeof(wi_socket_t));
 383}
 384
 385
 386
 387wi_socket_t * wi_socket_init_with_address(wi_socket_t *_socket, wi_address_t *address, wi_socket_type_t type) {
 388	_socket->address	= wi_copy(address);
 389	_socket->close		= true;
 390	_socket->buffer		= wi_string_init_with_capacity(wi_string_alloc(), WI_SOCKET_BUFFER_SIZE);
 391	_socket->type		= type;
 392
 393	_socket->sd			= socket(wi_address_family(_socket->address), _socket->type, 0);
 394	
 395	if(_socket->sd < 0) {
 396		wi_error_set_errno(errno);
 397		
 398		wi_release(_socket);
 399		
 400		return NULL;
 401	}
 402	
 403	if(!_wi_socket_set_option_int(_socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
 404		wi_release(_socket);
 405		
 406		return NULL;
 407	}
 408	
 409#ifdef SO_REUSEPORT
 410	if(!_wi_socket_set_option_int(_socket, SOL_SOCKET, SO_REUSEPORT, 1)) {
 411		wi_release(_socket);
 412		
 413		return NULL;
 414	}
 415#endif
 416
 417	return _socket;
 418}
 419
 420
 421
 422wi_socket_t * wi_socket_init_with_descriptor(wi_socket_t *socket, int sd) {
 423	socket->sd			= sd;
 424	socket->buffer		= wi_string_init_with_capacity(wi_string_alloc(), WI_SOCKET_BUFFER_SIZE);
 425	
 426	return socket;
 427}
 428
 429
 430
 431static void _wi_socket_dealloc(wi_runtime_instance_t *instance) {
 432	wi_socket_t		*socket = instance;
 433	
 434	wi_socket_close(socket);
 435	
 436	wi_release(socket->address);
 437	wi_release(socket->buffer);
 438}
 439
 440
 441
 442static wi_string_t * _wi_socket_description(wi_runtime_instance_t *instance) {
 443	wi_socket_t		*socket = instance;
 444
 445	return wi_string_with_format(WI_STR("<%@ %p>{sd = %d, address = %@}"),
 446		wi_runtime_class_name(socket),
 447		socket,
 448		socket->sd,
 449		socket->address);
 450}
 451
 452
 453
 454#pragma mark -
 455
 456static wi_boolean_t _wi_socket_set_option_int(wi_socket_t *socket, int level, int name, int option) {
 457	if(setsockopt(socket->sd, level, name, &option, sizeof(option)) < 0) {
 458		wi_error_set_errno(errno);
 459		
 460		return false;
 461	}
 462	
 463	return true;
 464}
 465
 466
 467
 468static wi_boolean_t _wi_socket_get_option_int(wi_socket_t *socket, int level, int name, int *option) {
 469	socklen_t		length;
 470	
 471	length = sizeof(*option);
 472	
 473	if(getsockopt(socket->sd, level, name, option, &length) < 0) {
 474		wi_error_set_errno(errno);
 475		
 476		*option = 0;
 477		
 478		return false;
 479	}
 480	
 481	return true;
 482}
 483
 484
 485
 486#pragma mark -
 487
 488wi_address_t * wi_socket_address(wi_socket_t *socket) {
 489	return socket->address;
 490}
 491
 492
 493
 494int wi_socket_descriptor(wi_socket_t *socket) {
 495	return socket->sd;
 496}
 497
 498
 499
 500void * wi_socket_ssl(wi_socket_t *socket) {
 501#ifdef HAVE_OPENSSL_SSL_H
 502	return socket->ssl;
 503#else
 504	return NULL;
 505#endif
 506}
 507
 508
 509
 510wi_rsa_t * wi_socket_ssl_public_key(wi_socket_t *socket) {
 511#ifdef HAVE_OPENSSL_SSL_H
 512	RSA			*rsa = NULL;
 513	X509		*x509 = NULL;
 514	EVP_PKEY	*pkey = NULL;
 515
 516	x509 = SSL_get_peer_certificate(socket->ssl);
 517
 518	if(!x509) {
 519		wi_error_set_openssl_error();
 520		
 521		goto end;
 522	}
 523	
 524	pkey = X509_get_pubkey(x509);
 525	
 526	if(!pkey) {
 527		wi_error_set_openssl_error();
 528
 529		goto end;
 530	}
 531	
 532	rsa = EVP_PKEY_get1_RSA(pkey);
 533	
 534	if(!rsa)
 535		wi_error_set_openssl_error();
 536
 537end:
 538	if(x509)
 539		X509_free(x509);
 540	
 541	if(pkey)
 542		EVP_PKEY_free(pkey);
 543	
 544	return wi_autorelease(wi_rsa_init_with_rsa(wi_rsa_alloc(), rsa));
 545#else
 546	return NULL;
 547#endif
 548}
 549
 550
 551
 552wi_string_t * wi_socket_cipher_version(wi_socket_t *socket) {
 553#ifdef HAVE_OPENSSL_SSL_H
 554	return wi_string_with_cstring(SSL_get_cipher_version(socket->ssl));
 555#else
 556	return NULL;
 557#endif
 558}
 559
 560
 561
 562wi_string_t * wi_socket_cipher_name(wi_socket_t *socket) {
 563#ifdef HAVE_OPENSSL_SSL_H
 564	return wi_string_with_cstring(SSL_get_cipher_name(socket->ssl));
 565#else
 566	return NULL;
 567#endif
 568}
 569
 570
 571
 572wi_uinteger_t wi_socket_cipher_bits(wi_socket_t *socket) {
 573#ifdef HAVE_OPENSSL_SSL_H
 574	return SSL_get_cipher_bits(socket->ssl, NULL);
 575#else
 576	return 0;
 577#endif
 578}
 579
 580
 581
 582wi_string_t * wi_socket_certificate_name(wi_socket_t *socket) {
 583#ifdef HAVE_OPENSSL_SSL_H
 584	X509			*x509 = NULL;
 585	EVP_PKEY		*pkey = NULL;
 586	wi_string_t		*string = NULL;
 587
 588	x509 = SSL_get_peer_certificate(socket->ssl);
 589
 590	if(!x509)
 591		goto end;
 592
 593	pkey = X509_get_pubkey(x509);
 594
 595	if(!pkey)
 596		goto end;
 597	
 598	switch(EVP_PKEY_type(pkey->type)) {
 599		case EVP_PKEY_RSA:
 600			string = wi_string_init_with_cstring(wi_string_alloc(), "RSA");
 601			break;
 602
 603		case EVP_PKEY_DSA:
 604			string = wi_string_init_with_cstring(wi_string_alloc(), "DSA");
 605			break;
 606
 607		case EVP_PKEY_DH:
 608			string = wi_string_init_with_cstring(wi_string_alloc(), "DH");
 609			break;
 610
 611		default:
 612			break;
 613	}
 614	
 615end:
 616	if(x509)
 617		X509_free(x509);
 618
 619	if(pkey)
 620		EVP_PKEY_free(pkey);
 621
 622	return wi_autorelease(string);
 623#else
 624	return NULL;
 625#endif
 626}
 627
 628
 629
 630wi_uinteger_t wi_socket_certificate_bits(wi_socket_t *socket) {
 631#ifdef HAVE_OPENSSL_SSL_H
 632	X509			*x509 = NULL;
 633	EVP_PKEY		*pkey = NULL;
 634	wi_uinteger_t	bits = 0;
 635
 636	x509 = SSL_get_peer_certificate(socket->ssl);
 637
 638	if(!x509)
 639		goto end;
 640
 641	pkey = X509_get_pubkey(x509);
 642
 643	if(!pkey)
 644		goto end;
 645	
 646	bits = 8 * EVP_PKEY_size(pkey);
 647	
 648end:
 649	if(x509)
 650		X509_free(x509);
 651
 652	if(pkey)
 653		EVP_PKEY_free(pkey);
 654
 655	return bits;
 656#else
 657	return 0;
 658#endif
 659}
 660
 661
 662
 663wi_string_t * wi_socket_certificate_hostname(wi_socket_t *socket) {
 664#ifdef HAVE_OPENSSL_SSL_H
 665	X509			*x509;
 666	wi_string_t		*string;
 667	char			hostname[MAXHOSTNAMELEN];
 668
 669	x509 = SSL_get_peer_certificate(socket->ssl);
 670
 671	if(!x509)
 672		return NULL;
 673
 674	X509_NAME_get_text_by_NID(X509_get_subject_name(x509),
 675							  NID_commonName,
 676							  hostname,
 677							  sizeof(hostname));
 678	
 679	string = wi_string_init_with_cstring(wi_string_alloc(), hostname);
 680	
 681	X509_free(x509);
 682	
 683	return wi_autorelease(string);
 684#else
 685	return NULL;
 686#endif
 687}
 688
 689
 690
 691#pragma mark -
 692
 693void wi_socket_set_port(wi_socket_t *socket, wi_uinteger_t port) {
 694	wi_address_set_port(socket->address, port);
 695}
 696
 697
 698
 699wi_uinteger_t wi_socket_port(wi_socket_t *socket) {
 700	return wi_address_port(socket->address);
 701}
 702
 703
 704
 705void wi_socket_set_direction(wi_socket_t *socket, wi_uinteger_t direction) {
 706	socket->direction = direction;
 707}
 708
 709
 710
 711wi_uinteger_t wi_socket_direction(wi_socket_t *socket) {
 712	return socket->direction;
 713}
 714
 715
 716
 717void wi_socket_set_data(wi_socket_t *socket, void *data) {
 718	socket->data = data;
 719}
 720
 721
 722
 723void * wi_socket_data(wi_socket_t *socket) {
 724	return socket->data;
 725}
 726
 727
 728
 729
 730wi_boolean_t wi_socket_set_blocking(wi_socket_t *socket, wi_boolean_t blocking) {
 731	int		flags;
 732
 733	flags = fcntl(socket->sd, F_GETFL);
 734
 735	if(flags < 0) {
 736		wi_error_set_errno(errno);
 737
 738		return false;
 739	}
 740
 741	if(blocking)
 742		flags &= ~O_NONBLOCK;
 743	else
 744		flags |= O_NONBLOCK;
 745
 746	if(fcntl(socket->sd, F_SETFL, flags) < 0) {
 747		wi_error_set_errno(errno);
 748
 749		return false;
 750	}
 751	
 752	return true;
 753}
 754
 755
 756
 757wi_boolean_t wi_socket_blocking(wi_socket_t *socket) {
 758	int		flags;
 759	
 760	flags = fcntl(socket->sd, F_GETFL);
 761		
 762	if(flags < 0) {
 763		wi_error_set_errno(errno);
 764
 765		return false;
 766	}
 767	
 768	return !(flags & O_NONBLOCK);
 769}
 770
 771
 772
 773wi_boolean_t wi_socket_set_timeout(wi_socket_t *socket, wi_time_interval_t interval) {
 774	struct timeval		tv;
 775	
 776	tv = wi_dtotv(interval);
 777	
 778	if(setsockopt(socket->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
 779		wi_error_set_errno(errno);
 780		
 781		return false;
 782	}
 783
 784	if(setsockopt(socket->sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
 785		wi_error_set_errno(errno);
 786		
 787		return false;
 788	}
 789	
 790	return true;
 791}
 792
 793
 794
 795wi_time_interval_t wi_socket_timeout(wi_socket_t *socket) {
 796	struct timeval		tv;
 797	socklen_t			length;
 798	
 799	length = sizeof(tv);
 800	
 801	if(getsockopt(socket->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, &length) < 0) {
 802		wi_error_set_errno(errno);
 803		
 804		return 0.0;
 805	}
 806	
 807	return wi_tvtod(tv);
 808}
 809
 810
 811
 812void wi_socket_set_interactive(wi_socket_t *socket, wi_boolean_t interactive) {
 813	_wi_socket_set_option_int(socket, IPPROTO_TCP, TCP_NODELAY, interactive ? 1 : 0);
 814	
 815#if defined(IPTOS_LOWDELAY) && defined(IPTOS_THROUGHPUT)
 816	if(wi_address_family(socket->address) == WI_ADDRESS_IPV4)
 817		_wi_socket_set_option_int(socket, IPPROTO_IP, IP_TOS, interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT);
 818#endif
 819	
 820	socket->interactive = interactive;
 821}
 822
 823
 824
 825wi_boolean_t wi_socket_interactive(wi_socket_t *socket) {
 826	return socket->interactive;
 827}
 828
 829
 830
 831int wi_socket_error(wi_socket_t *socket) {
 832	int		error;
 833	
 834	WI_ASSERT(socket->type == WI_SOCKET_TCP, "%@ is not a TCP socket", socket);
 835	
 836	if(!_wi_socket_get_option_int(socket, SOL_SOCKET, SO_ERROR, &error))
 837		return errno;
 838	
 839	return error;
 840}
 841
 842
 843
 844#pragma mark -
 845
 846wi_socket_t * wi_socket_wait_multiple(wi_array_t *array, wi_time_interval_t timeout) {
 847	wi_enumerator_t		*enumerator;
 848	wi_socket_t			*socket, *waiting_socket = NULL;
 849	struct timeval		tv;
 850	fd_set				rfds, wfds;
 851	int					state, max_sd;
 852
 853	tv = wi_dtotv(timeout);
 854	max_sd = -1;
 855
 856	FD_ZERO(&rfds);
 857	FD_ZERO(&wfds);
 858
 859	wi_array_rdlock(array);
 860	
 861	enumerator = wi_array_data_enumerator(array);
 862	
 863	while((socket = wi_enumerator_next_data(enumerator))) {
 864		if(wi_string_length(socket->buffer) > 0) {
 865			waiting_socket = socket;
 866			
 867			break;
 868		}
 869		
 870		if(socket->direction & WI_SOCKET_READ)
 871			FD_SET(socket->sd, &rfds);
 872
 873		if(socket->direction & WI_SOCKET_WRITE)
 874			FD_SET(socket->sd, &wfds);
 875
 876		if(socket->sd > max_sd)
 877			max_sd = socket->sd;
 878	}
 879
 880	wi_array_unlock(array);
 881	
 882	if(waiting_socket)
 883		return waiting_socket;
 884	
 885	state = select(max_sd + 1, &rfds, &wfds, NULL, (timeout > 0.0) ? &tv : NULL);
 886	
 887	if(state < 0) {
 888		wi_error_set_errno(errno);
 889
 890		return NULL;
 891	}
 892	
 893	wi_array_rdlock(array);
 894
 895	enumerator = wi_array_data_enumerator(array);
 896	
 897	while((socket = wi_enumerator_next_data(enumerator))) {
 898		if(FD_ISSET(socket->sd, &rfds) || FD_ISSET(socket->sd, &wfds)) {
 899			waiting_socket = socket;
 900
 901			break;
 902		}
 903	}
 904	
 905	wi_array_unlock(array);
 906	
 907	return waiting_socket;
 908}
 909
 910
 911
 912wi_socket_state_t wi_socket_wait(wi_socket_t *socket, wi_time_interval_t timeout) {
 913	if(wi_string_length(socket->buffer) > 0)
 914		return WI_SOCKET_READY;
 915
 916	return wi_socket_wait_descriptor(socket->sd,
 917									 timeout,
 918									 (socket->direction & WI_SOCKET_READ),
 919									 (socket->direction & WI_SOCKET_WRITE));
 920}
 921
 922
 923
 924wi_socket_state_t wi_socket_wait_descriptor(int sd, wi_time_interval_t timeout, wi_boolean_t read, wi_boolean_t write) {
 925	struct timeval	tv;
 926	fd_set			rfds, wfds;
 927	int				state;
 928	
 929	tv = wi_dtotv(timeout);
 930	
 931	FD_ZERO(&rfds);
 932	FD_ZERO(&wfds);
 933	
 934	if(read)
 935		FD_SET(sd, &rfds);
 936	
 937	if(write)
 938		FD_SET(sd, &wfds);
 939	
 940	state = select(sd + 1, &rfds, &wfds, NULL, (timeout > 0.0) ? &tv : NULL);
 941	
 942	if(state < 0) {
 943		wi_error_set_errno(errno);
 944		
 945		return WI_SOCKET_ERROR;
 946	}
 947	
 948	if(state == 0)
 949		return WI_SOCKET_TIMEOUT;
 950	
 951	return WI_SOCKET_READY;
 952}
 953
 954
 955
 956#pragma mark -
 957
 958wi_boolean_t wi_socket_listen(wi_socket_t *socket, wi_uinteger_t backlog) {
 959	struct sockaddr				*sa;
 960	struct sockaddr_storage		ss;
 961	wi_uinteger_t				port;
 962	socklen_t					length;
 963	
 964	port	= wi_address_port(socket->address);
 965	sa		= wi_address_sa(socket->address);
 966	length	= wi_address_sa_length(socket->address);
 967	
 968	if(bind(socket->sd, sa, length) < 0) {
 969		wi_error_set_errno(errno);
 970		
 971		return false;
 972	}
 973
 974	if(socket->type == WI_SOCKET_TCP) {
 975		if(listen(socket->sd, backlog) < 0) {
 976			wi_error_set_errno(errno);
 977
 978			return false;
 979		}
 980	}
 981	
 982	if(port == 0) {
 983		length = sizeof(ss);
 984		
 985		if(getsockname(socket->sd, (struct sockaddr *) &ss, &length) == 0) {
 986			wi_release(socket->address);
 987			socket->address = wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss);
 988		}
 989	}
 990	
 991	socket->direction = WI_SOCKET_READ;
 992	
 993	return true;
 994}
 995
 996
 997
 998wi_boolean_t wi_socket_connect(wi_socket_t *socket, wi_time_interval_t timeout) {
 999	struct sockaddr		*sa;
1000	wi_socket_state_t	state;
1001	wi_uinteger_t		length;
1002	int					err;
1003	wi_boolean_t		blocking;
1004	
1005	sa		= wi_address_sa(socket->address);
1006	length	= wi_address_sa_length(socket->address);
1007
1008	if(timeout > 0.0) {
1009		blocking = wi_socket_blocking(socket);
1010
1011		if(blocking)
1012			wi_socket_set_blocking(socket, false);
1013		
1014		err = connect(socket->sd, sa, length);
1015		
1016		if(err < 0) {
1017			if(errno != EINPROGRESS) {
1018				wi_error_set_errno(errno);
1019				
1020				return false;
1021			}
1022			
1023			do {
1024				state = wi_socket_wait_descriptor(socket->sd, 1.0, true, true);
1025				timeout -= 1.0;
1026			} while(state == WI_SOCKET_TIMEOUT && timeout >= 0.0);
1027			
1028			if(state == WI_SOCKET_ERROR)
1029				return false;
1030			
1031			if(timeout <= 0.0) {
1032				wi_error_set_errno(ETIMEDOUT);
1033				
1034				return false;
1035			}
1036			
1037			err = wi_socket_error(socket);
1038			
1039			if(err != 0) {
1040				wi_error_set_errno(err);
1041				
1042				return false;
1043			}
1044		}
1045
1046		if(blocking)
1047			wi_socket_set_blocking(socket, true);
1048	} else {
1049		if(connect(socket->sd, sa, length) < 0) {
1050			wi_error_set_errno(errno);
1051				
1052			return false;
1053		}
1054	}
1055
1056	socket->direction = WI_SOCKET_READ;
1057	
1058	return true;
1059}
1060
1061
1062
1063#ifdef HAVE_OPENSSL_SSL_H
1064
1065wi_boolean_t wi_socket_connect_tls(wi_socket_t *socket, wi_socket_tls_t *tls, wi_time_interval_t timeout) {
1066	wi_socket_state_t	state;
1067	int					err, result;
1068	wi_boolean_t		blocking;
1069	
1070	socket->ssl = SSL_new(tls->ssl_ctx);
1071	
1072	if(!socket->ssl) {
1073		wi_error_set_openssl_error();
1074		
1075		return false;
1076	}
1077	
1078	if(SSL_set_fd(socket->ssl, socket->sd) != 1) {
1079		wi_error_set_openssl_error();
1080		
1081		return false;
1082	}
1083	
1084	if(timeout > 0.0) {
1085		blocking = wi_socket_blocking(socket);
1086
1087		if(blocking)
1088			wi_socket_set_blocking(socket, false);
1089
1090		result = SSL_connect(socket->ssl);
1091		
1092		if(result != 1) {
1093			do {
1094				err = SSL_get_error(socket->ssl, result);
1095
1096				if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
1097					wi_error_set_openssl_ssl_error_with_result(socket->ssl, result);
1098					
1099					return false;
1100				}
1101				
1102				state = wi_socket_wait_descriptor(socket->sd, 1.0, (err == SSL_ERROR_WANT_READ), (err == SSL_ERROR_WANT_WRITE));
1103				
1104				if(state == WI_SOCKET_ERROR)
1105					break;
1106				else if(state == WI_SOCKET_READY) {
1107					result = SSL_connect(socket->ssl);
1108					
1109					if(result == 1)
1110						break;
1111				}
1112				
1113				timeout -= 1.0;
1114			} while(timeout >= 0.0);
1115			
1116			if(state == WI_SOCKET_ERROR)
1117				return false;
1118			
1119			if(timeout <= 0.0) {
1120				wi_error_set_errno(ETIMEDOUT);
1121				
1122				return false;
1123			}
1124		}
1125
1126		if(blocking)
1127			wi_socket_set_blocking(socket, true);
1128	} else {
1129		result = SSL_connect(socket->ssl);
1130		
1131		if(result != 1) {
1132			wi_error_set_openssl_ssl_error_with_result(socket->ssl, result);
1133
1134			return false;
1135		}
1136	}
1137	
1138	return true;
1139}
1140
1141#endif
1142
1143
1144
1145wi_socket_t * wi_socket_accept_multiple(wi_array_t *array, wi_time_interval_t timeout, wi_address_t **address) {
1146	wi_socket_t		*socket;
1147	
1148	*address = NULL;
1149	socket = wi_socket_wait_multiple(array, 0.0);
1150	
1151	if(!socket)
1152		return NULL;
1153	
1154	return wi_socket_accept(socket, timeout, address);
1155}
1156
1157
1158
1159wi_socket_t * wi_socket_accept(wi_socket_t *accept_socket, wi_time_interval_t timeout, wi_address_t **address) {
1160	wi_socket_t					*socket;
1161	struct sockaddr_storage		ss;
1162	socklen_t					length;
1163	int							sd, err = 0;
1164	
1165	length = sizeof(ss);
1166	sd = accept(accept_socket->sd, (struct sockaddr *) &ss, &length);
1167	
1168	if(sd < 0)
1169		err = errno;
1170
1171	*address = (length > 0) ? wi_autorelease(wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss)) : NULL;
1172
1173	if(sd < 0) {
1174		wi_error_set_errno(err);
1175		
1176		return NULL;
1177	}
1178
1179	socket = wi_socket_init_with_descriptor(wi_socket_alloc(), sd);
1180
1181	socket->close		= true;
1182	socket->address		= wi_retain(*address);
1183	socket->type		= accept_socket->type;
1184	socket->direction	= WI_SOCKET_READ;
1185	socket->interactive	= accept_socket->interactive;
1186	
1187	return wi_autorelease(socket);
1188}
1189
1190
1191
1192#ifdef HAVE_OPENSSL_SSL_H
1193
1194wi_boolean_t wi_socket_accept_tls(wi_socket_t *socket, wi_socket_tls_t *tls, wi_time_interval_t timeout) {
1195	wi_socket_state_t	state;
1196	int					err, result;
1197	wi_boolean_t		blocking;
1198	
1199	socket->ssl = SSL_new(tls->ssl_ctx);
1200	
1201	if(!socket->ssl) {
1202		wi_error_set_openssl_error();
1203		
1204		return false;
1205	}
1206	
1207	if(SSL_set_fd(socket->ssl, socket->sd) != 1) {
1208		wi_error_set_openssl_error();
1209		
1210		return false;
1211	}
1212	
1213	if(!tls->private_key && tls->dh) {
1214		if(SSL_set_tmp_dh(socket->ssl, tls->dh) != 1) {
1215			wi_error_set_openssl_error();
1216			
1217			return false;
1218		}
1219	}
1220	
1221	if(timeout > 0.0) {
1222		blocking = wi_socket_blocking(socket);
1223		
1224		if(blocking)
1225			wi_socket_set_blocking(socket, false);
1226		
1227		result = SSL_accept(socket->ssl);
1228		
1229		if(result != 1) {
1230			do {
1231				err = SSL_get_error(socket->ssl, result);
1232				
1233				if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) {
1234					wi_error_set_openssl_ssl_error_with_result(socket->ssl, result);
1235					
1236					return false;
1237				}
1238
1239				state = wi_socket_wait_descriptor(socket->sd, 1.0, (err == SSL_ERROR_WANT_READ), (err == SSL_ERROR_WANT_WRITE));
1240
1241				if(state == WI_SOCKET_ERROR)
1242					break;
1243				else if(state == WI_SOCKET_READY) {
1244					result = SSL_accept(socket->ssl);
1245					
1246					if(result == 1)
1247						break;
1248				}
1249				
1250				timeout -= 1.0;
1251			} while(timeout >= 0.0);
1252
1253			if(state == WI_SOCKET_ERROR)
1254				return false;
1255			
1256			if(timeout <= 0.0) {
1257				wi_error_set_errno(ETIMEDOUT);
1258				
1259				return false;
1260			}
1261		}
1262		
1263		if(blocking)
1264			wi_socket_set_blocking(socket, true);
1265	} else {
1266		result = SSL_accept(socket->ssl);
1267		
1268		if(result != 1) {
1269			wi_error_set_openssl_ssl_error_with_result(socket->ssl, result);
1270			
1271			return false;
1272		}
1273	}
1274	
1275	return true;
1276}
1277
1278#endif
1279
1280
1281
1282void wi_socket_close(wi_socket_t *socket) {
1283#ifdef HAVE_OPENSSL_SSL_H
1284	if(socket->ssl) {
1285		if(!socket->broken) {
1286			if(SSL_shutdown(socket->ssl) == 0)
1287				SSL_shutdown(socket->ssl);
1288		}
1289
1290		SSL_free(socket->ssl);
1291		
1292		socket->ssl = NULL;
1293	}
1294#endif
1295
1296	if(socket->close && socket->sd >= 0) {
1297		close(socket->sd);
1298		
1299		socket->sd = -1;
1300	}
1301}
1302
1303
1304
1305#pragma mark -
1306
1307wi_integer_t wi_socket_sendto_format(wi_socket_t *socket, wi_string_t *fmt, ...) {
1308	wi_string_t		*string;
1309	int				bytes;
1310	va_list			ap;
1311
1312	va_start(ap, fmt);
1313	string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap);
1314	va_end(ap);
1315
1316	bytes = wi_socket_sendto_buffer(socket, wi_string_cstring(string), wi_string_length(string));
1317	
1318	wi_release(string);
1319
1320	return bytes;
1321}
1322
1323
1324
1325wi_integer_t wi_socket_sendto_data(wi_socket_t *socket, wi_data_t *data) {
1326	return wi_socket_sendto_buffer(socket, wi_data_bytes(data), wi_data_length(data));
1327}
1328
1329
1330
1331wi_integer_t wi_socket_sendto_buffer(wi_socket_t *socket, const char *buffer, size_t length) {
1332	wi_address_t	*address;
1333	char			*outbuffer = NULL;
1334	wi_integer_t	bytes;
1335	
1336	address = wi_socket_address(socket);
1337	bytes = sendto(socket->sd, buffer, length, 0,
1338		wi_address_sa(address), wi_address_sa_length(address));
1339	
1340	if(bytes < 0) {
1341		wi_error_set_errno(errno);
1342		
1343		goto end;
1344	}
1345
1346end:
1347	if(outbuffer)
1348		wi_free(outbuffer);
1349	
1350	return bytes;
1351}
1352
1353
1354
1355wi_integer_t wi_socket_recvfrom_multiple(wi_array_t *array, char *buffer, size_t length, wi_address_t **address) {
1356	wi_socket_t		*socket;
1357	
1358	*address = NULL;
1359	socket = wi_socket_wait_multiple(array, 0.0);
1360	
1361	if(!socket)
1362		return -1;
1363	
1364	return wi_socket_recvfrom(socket, buffer, length, address);
1365}
1366
1367
1368
1369wi_integer_t wi_socket_recvfrom(wi_socket_t *socket, char *buffer, size_t length, wi_address_t **address) {
1370	struct sockaddr_storage		ss;
1371	char						*inbuffer = NULL;
1372	socklen_t					sslength;
1373	wi_integer_t				bytes;
1374	
1375	sslength = sizeof(ss);
1376	bytes = recvfrom(socket->sd, buffer, length, 0, (struct sockaddr *) &ss, &sslength);
1377
1378	if(bytes < 0) {
1379		wi_error_set_errno(errno);
1380		
1381		goto end;
1382	}
1383
1384end:
1385	*address = (sslength > 0) ? wi_autorelease(wi_address_init_with_sa(wi_address_alloc(), (struct sockaddr *) &ss)) : NULL;
1386
1387	if(inbuffer)
1388		wi_free(inbuffer);
1389
1390	return bytes;
1391}
1392
1393
1394
1395#pragma mark -
1396
1397wi_integer_t wi_socket_write_format(wi_socket_t *socket, wi_time_interval_t timeout, wi_string_t *fmt, ...) {
1398	wi_string_t		*string;
1399	wi_integer_t	bytes;
1400	va_list			ap;
1401
1402	va_start(ap, fmt);
1403	string = wi_string_init_with_format_and_arguments(wi_string_alloc(), fmt, ap);
1404	va_end(ap);
1405	
1406	bytes = wi_socket_write_buffer(socket, timeout, wi_string_cstring(string), wi_string_length(string));
1407	
1408	wi_release(string);
1409
1410	return bytes;
1411}
1412
1413
1414
1415wi_integer_t wi_socket_write_buffer(wi_socket_t *socket, wi_time_interval_t timeout, const void *buffer, size_t length) {
1416	wi_time_interval_t	interval;
1417	wi_socket_state_t	state;
1418	wi_uinteger_t		offset;
1419	wi_integer_t		bytes;
1420	
1421	WI_ASSERT(buffer != NULL, "buffer of length %u should not be NULL", length);
1422	
1423	if(timeout > 0.0) {
1424		state = wi_socket_wait_descriptor(socket->sd, timeout, false, true);
1425
1426		if(state != WI_SOCKET_READY) {
1427			if(state == WI_SOCKET_TIMEOUT)
1428				wi_error_set_errno(ETIMEDOUT);
1429			
1430			return -1;
1431		}
1432	}
1433
1434	interval = 0.0;
1435		
1436#ifdef HAVE_OPENSSL_SSL_H
1437	if(socket->ssl) {
1438		do {
1439			bytes = SSL_write(socket->ssl, buffer, length);
1440
1441			if(bytes <= 0) {
1442				if(bytes < 0 && SSL_get_error(socket->ssl, bytes) == SSL_ERROR_WANT_WRITE) {
1443					wi_thread_sleep(0.1);
1444					
1445					if(timeout > 0.0) {
1446						interval += 0.1;
1447
1448						if(interval >= timeout) {
1449							wi_error_set_errno(ETIMEDOUT);
1450							
1451							break;
1452						}
1453					}
1454				} else {
1455					wi_error_set_openssl_ssl_error_with_result(socket->ssl, bytes);
1456
1457					socket->broken = true;
1458
1459					break;
1460				}
1461			}
1462		} while(bytes <= 0);
1463		
1464		return bytes;
1465	} else {
1466#endif
1467		offset = 0;
1468		
1469		do {
1470			bytes = write(socket->sd, buffer + offset, length - offset);
1471			
1472			if(bytes <= 0) {
1473				if(bytes < 0)
1474					wi_error_set_errno(errno);
1475				else
1476					wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
1477				
1478				return bytes;
1479			}
1480			
1481			offset += bytes;
1482			
1483			if(offset < length) {
1484				wi_thread_sleep(0.1);
1485				
1486				if(timeout > 0.0) {
1487					interval += 0.1;
1488					
1489					if(interval >= timeout) {
1490						wi_error_set_errno(ETIMEDOUT);
1491						
1492						return -1;
1493					}
1494				}
1495			}
1496		} while(offset < length);
1497		
1498		return offset;
1499#ifdef HAVE_OPENSSL_SSL_H
1500	}
1501#endif
1502	
1503	return 0;
1504}
1505
1506
1507
1508wi_string_t * wi_socket_read(wi_socket_t *socket, wi_time_interval_t timeout, size_t length) {
1509	wi_string_t		*string;
1510	char			buffer[WI_SOCKET_BUFFER_SIZE];
1511	int				bytes = -1;
1512	
1513	string = wi_string_init_with_capacity(wi_string_alloc(), length);
1514	
1515	while(length > sizeof(buffer)) {
1516		bytes = wi_socket_read_buffer(socket, timeout, buffer, sizeof(buffer));
1517		
1518		if(bytes <= 0)
1519			goto end;
1520		
1521		wi_string_append_bytes(string, buffer, bytes);
1522		
1523		length -= bytes;
1524	}
1525
1526	if(length > 0) {
1527		bytes = wi_socket_read_buffer(socket, timeout, buffer, length);
1528		
1529		if(bytes <= 0)
1530			goto end;
1531		
1532		wi_string_append_bytes(string, buffer, bytes);
1533	}
1534
1535end:
1536	if(wi_string_length(string) == 0) {
1537		if(bytes < 0) {
1538			wi_release(string);
1539			
1540			string = NULL;
1541		}
1542	}
1543
1544	return wi_autorelease(string);
1545}
1546
1547
1548
1549wi_string_t * wi_socket_read_to_string(wi_socket_t *socket, wi_time_interval_t timeout, wi_string_t *separator) {
1550	wi_string_t		*string, *substring;
1551	wi_uinteger_t	index;
1552	
1553	index = wi_string_index_of_string(socket->buffer, separator, 0);
1554	
1555	if(index != WI_NOT_FOUND) {
1556		substring = wi_string_substring_to_index(socket->buffer, index + wi_string_length(separator));
1557		
1558		wi_string_delete_characters_in_range(socket->buffer, wi_make_range(0, wi_string_length(substring)));
1559
1560		return substring;
1561	}
1562	
1563	while((string = wi_socket_read(socket, timeout, WI_SOCKET_BUFFER_SIZE))) {
1564		if(wi_string_length(string) == 0)
1565			return string;
1566
1567		wi_string_append_string(socket->buffer, string);
1568
1569		index = wi_string_index_of_string(socket->buffer, separator, 0);
1570		
1571		if(index == WI_NOT_FOUND) {
1572			if(wi_string_length(socket->buffer) > _WI_SOCKET_BUFFER_MAX_SIZE) {
1573				substring = wi_string_substring_to_index(socket->buffer, _WI_SOCKET_BUFFER_MAX_SIZE);
1574
1575				wi_string_delete_characters_in_range(socket->buffer, wi_make_range(0, wi_string_length(substring)));
1576				
1577				return substring;
1578			}
1579		} else {
1580			substring = wi_string_substring_to_index(socket->buffer, index + wi_string_length(separator));
1581			
1582			wi_string_delete_characters_in_range(socket->buffer, wi_make_range(0, wi_string_length(substring)));
1583			
1584			return substring;
1585		}
1586	}
1587	
1588	return NULL;
1589}
1590
1591
1592
1593wi_integer_t wi_socket_read_buffer(wi_socket_t *socket, wi_time_interval_t timeout, void *buffer, size_t length) {
1594	wi_time_interval_t	interval;
1595	wi_socket_state_t	state;
1596	wi_uinteger_t		offset;
1597	wi_integer_t		bytes;
1598	
1599	WI_ASSERT(buffer != NULL, "buffer of length %u should not be NULL", length);
1600
1601	if(timeout > 0.0) {
1602#ifdef HAVE_OPENSSL_SSL_H
1603		if(!socket->ssl || (socket->ssl && SSL_pending(socket->ssl) == 0)) {
1604#endif
1605			state = wi_socket_wait_descriptor(socket->sd, timeout, true, false);
1606
1607			if(state != WI_SOCKET_READY) {
1608				if(state == WI_SOCKET_TIMEOUT)
1609					wi_error_set_errno(ETIMEDOUT);
1610				
1611				return -1;
1612			}
1613#ifdef HAVE_OPENSSL_SSL_H
1614		}
1615#endif
1616	}
1617	
1618	interval = 0.0;
1619		
1620#ifdef HAVE_OPENSSL_SSL_H
1621	if(socket->ssl) {
1622		do {
1623			bytes = SSL_read(socket->ssl, buffer, length);
1624			
1625			if(bytes <= 0) {
1626				if(bytes < 0 && SSL_get_error(socket->ssl, bytes) == SSL_ERROR_WANT_READ) {
1627					wi_thread_sleep(0.1);
1628					
1629					if(timeout > 0.0) {
1630						interval += 0.1;
1631						
1632						if(interval >= timeout) {
1633							wi_error_set_errno(ETIMEDOUT);
1634							
1635							break;
1636						}
1637					}
1638				} else {
1639					wi_error_set_openssl_ssl_error_with_result(socket->ssl, bytes);
1640
1641					socket->broken = true;
1642					
1643					break;
1644				}
1645			}
1646		} while(bytes <= 0);
1647		
1648		return bytes;
1649	} else {
1650#endif
1651		offset = 0;
1652		
1653		do {
1654			bytes = read(socket->sd, buffer + offset, length - offset);
1655			
1656			if(bytes <= 0) {
1657				if(bytes < 0)
1658					wi_error_set_errno(errno);
1659				else
1660					wi_error_set_libwired_error(WI_ERROR_SOCKET_EOF);
1661				
1662				return bytes;
1663			}
1664			
1665			offset += bytes;
1666			
1667			if(offset < length) {
1668				wi_thread_sleep(0.1);
1669				
1670				if(timeout > 0.0) {
1671					interval += 0.1;
1672					
1673					if(interval >= timeout) {
1674						wi_error_set_errno(ETIMEDOUT);
1675						
1676						return -1;
1677					}
1678				}
1679			}
1680		} while(offset < length);
1681		
1682		return offset;
1683#ifdef HAVE_OPENSSL_SSL_H
1684	}
1685#endif
1686
1687	return 0;
1688}
1689
1690
1691
1692#pragma mark -
1693
1694wi_string_t * wi_socket_buffered_string(wi_socket_t *socket) {
1695	return socket->buffer;
1696}