Branch data Line data Source code
1 : : /**
2 : : * \file
3 : : *
4 : : * \author Georg Hopp
5 : : *
6 : : * \copyright
7 : : * Copyright © 2012 Georg Hopp
8 : : *
9 : : * This program is free software: you can redistribute it and/or modify
10 : : * it under the terms of the GNU General Public License as published by
11 : : * the Free Software Foundation, either version 3 of the License, or
12 : : * (at your option) any later version.
13 : : *
14 : : * This program is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : : * GNU General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU General Public License
20 : : * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : : */
22 : :
23 : : #include <openssl/err.h>
24 : : #include <openssl/ssl.h>
25 : : #include <unistd.h>
26 : : #include <errno.h>
27 : :
28 : : #include "stream.h"
29 : : #include "logger.h"
30 : :
31 : : extern Logger logger;
32 : :
33 : :
34 : : ssize_t
35 : 0 : streamWrite(Stream this, void * buf, size_t count)
36 : : {
37 : : ssize_t done;
38 : :
39 : 0 : switch(this->type) {
40 : : ssize_t written;
41 : :
42 : : case STREAM_FD:
43 : 0 : written = write((this->handle).fd, buf, count);
44 : :
45 : 0 : if (written < 0) {
46 : 0 : switch (errno) {
47 : : case EINTR:
48 : : case ENOBUFS:
49 : : case ENOMEM:
50 : 0 : done = 0;
51 : 0 : break;
52 : : case (EAGAIN|EWOULDBLOCK):
53 : 0 : done = -1;
54 : 0 : break;
55 : : default:
56 : 0 : done = -2;
57 : 0 : break;
58 : : }
59 : : } else {
60 : 0 : done = written;
61 : : }
62 : :
63 : 0 : break;
64 : :
65 : : case STREAM_SSL:
66 : : /**
67 : : * \todo I got a segfault in this call under unclear
68 : : * circumstances. Most likely it has to do with a
69 : : * write on a closed connection.
70 : : */
71 : 0 : done = SSL_write((this->handle).ssl, buf, count);
72 : :
73 : 0 : if (0 == done) {
74 : 0 : done = -2;
75 : 0 : } else if (0 > done) {
76 : 0 : switch (SSL_get_error((this->handle).ssl, done)) {
77 : : case SSL_ERROR_SYSCALL:
78 : : {
79 : 0 : switch (errno) {
80 : : case EINTR:
81 : : case ENOBUFS:
82 : : case ENOMEM:
83 : 0 : done = 0;
84 : 0 : break;
85 : : case (EAGAIN|EWOULDBLOCK):
86 : 0 : done = -1;
87 : 0 : break;
88 : : default:
89 : 0 : done = -2;
90 : 0 : break;
91 : : }
92 : : }
93 : 0 : break;
94 : :
95 : : case SSL_ERROR_SSL:
96 : : {
97 : : unsigned long err;
98 : :
99 : 0 : while (0 != (err = ERR_get_error())) {
100 : 0 : loggerLog(
101 : : logger,
102 : : LOGGER_DEBUG,
103 : 0 : ERR_error_string(err, NULL));
104 : : }
105 : : }
106 : : // DROP THROUGH
107 : :
108 : : case SSL_ERROR_ZERO_RETURN:
109 : 0 : done = -2;
110 : 0 : break;
111 : : }
112 : : }
113 : :
114 : 0 : break;
115 : :
116 : : default:
117 : 0 : done = -2;
118 : 0 : break;
119 : : }
120 : :
121 : 0 : return done;
122 : : }
123 : :
124 : : // vim: set ts=4 sw=4:
|