/* Asynchronous SSL stream reader */ int ssl_read_thread(thread_t * thread) { SOCK *sock_obj = THREAD_ARG(thread); int r = 0; int error; /* Handle read timeout */ if (thread->type == THREAD_READ_TIMEOUT) return epilog(thread); /* * The design implemented here is a workaround for use * with OpenSSL. This goto loop is a 'read until not * end of stream'. But this break a little our global * I/O multiplexer thread framework because it enter * a synchronous read process for each GET reply. * Sound a little nasty !. * * Why OpenSSL doesn t handle underlying fd. This * break the I/O (select()) approach !... * If you read this and know the answer, please reply * I am probably missing something... :) * My test show that sometime it return from select, * and sometime not... */ read_stream: /* read the SSL stream */ memset(sock_obj->buffer, 0, MAX_BUFFER_LENGTH); r = SSL_read(sock_obj->ssl, sock_obj->buffer, MAX_BUFFER_LENGTH); error = SSL_get_error(sock_obj->ssl, r); DBG(" [l:%d,fd:%d]\n", r, sock_obj->fd); if (error) { /* All the SSL streal has been parsed */ /* Handle response stream */ if (error != SSL_ERROR_NONE) return finalize(thread); } else if (r > 0 && error == 0) { /* Handle the response stream */ http_process_stream(sock_obj, r); /* * Register next ssl stream reader. * Register itself to not perturbe global I/O multiplexer. */ goto read_stream; } return 0; }
/* Asynchronous HTTP stream reader */ int http_read_thread(thread_t * thread) { SOCK *sock_obj = THREAD_ARG(thread); int r = 0; /* Handle read timeout */ if (thread->type == THREAD_READ_TIMEOUT) return epilog(thread); /* read the HTTP stream */ r = MAX_BUFFER_LENGTH - sock_obj->size; if (r <= 0) { /* defensive check, should not occur */ fprintf(stderr, "HTTP socket buffer overflow (not consumed)\n"); r = MAX_BUFFER_LENGTH; } memset(sock_obj->buffer + sock_obj->size, 0, r); r = read(thread->u.fd, sock_obj->buffer + sock_obj->size, r); DBG(" [l:%d,fd:%d]\n", r, sock_obj->fd); if (r == -1 || r == 0) { /* -1:error , 0:EOF */ if (r == -1) { /* We have encourred a real read error */ DBG("Read error with server [%s]:%d: %s\n", req->ipaddress, ntohs(req->addr_port), strerror(errno)); return epilog(thread); } /* All the HTTP stream has been parsed */ finalize(thread); } else { /* Handle the response stream */ http_process_stream(sock_obj, r); /* * Register next http stream reader. * Register itself to not perturbe global I/O multiplexer. */ thread_add_read(thread->master, http_read_thread, sock_obj, thread->u.fd, HTTP_CNX_TIMEOUT); } return 0; }