diff options
Diffstat (limited to 'vchat-connection.c')
-rw-r--r-- | vchat-connection.c | 133 |
1 files changed, 65 insertions, 68 deletions
diff --git a/vchat-connection.c b/vchat-connection.c index 5ab4dd4..01cf2c2 100644 --- a/vchat-connection.c +++ b/vchat-connection.c | |||
@@ -10,27 +10,27 @@ | |||
10 | * without even the implied warranty of merchantability or fitness for a | 10 | * without even the implied warranty of merchantability or fitness for a |
11 | * particular purpose. In no event shall the copyright holder be liable for | 11 | * particular purpose. In no event shall the copyright holder be liable for |
12 | * any direct, indirect, incidental or special damages arising in any way out | 12 | * any direct, indirect, incidental or special damages arising in any way out |
13 | * of the use of this software. | 13 | * of the use of this software. |
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <stdlib.h> | 17 | #include <errno.h> |
18 | #include <netdb.h> | ||
19 | #include <netinet/in.h> | ||
18 | #include <stddef.h> | 20 | #include <stddef.h> |
19 | #include <string.h> | ||
20 | #include <stdio.h> | 21 | #include <stdio.h> |
21 | #include <unistd.h> | 22 | #include <stdlib.h> |
22 | #include <netdb.h> | 23 | #include <string.h> |
23 | #include <errno.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/socket.h> | 24 | #include <sys/socket.h> |
26 | #include <netinet/in.h> | 25 | #include <sys/types.h> |
26 | #include <unistd.h> | ||
27 | 27 | ||
28 | /* For tilde_expand */ | 28 | /* For tilde_expand */ |
29 | #include <readline/readline.h> | 29 | #include <readline/readline.h> |
30 | 30 | ||
31 | #include "vchat.h" | ||
32 | #include "vchat-connection.h" | 31 | #include "vchat-connection.h" |
33 | #include "vchat-tls.h" | 32 | #include "vchat-tls.h" |
33 | #include "vchat.h" | ||
34 | 34 | ||
35 | static int serverfd = -1; | 35 | static int serverfd = -1; |
36 | unsigned int want_tcp_keepalive = 0; | 36 | unsigned int want_tcp_keepalive = 0; |
@@ -40,49 +40,49 @@ unsigned int want_tcp_keepalive = 0; | |||
40 | extern int status; | 40 | extern int status; |
41 | 41 | ||
42 | /* Generic tcp connector, blocking */ | 42 | /* Generic tcp connector, blocking */ |
43 | static int connect_tcp_socket( const char *server, const char *port ) { | 43 | static int connect_tcp_socket(const char *server, const char *port) { |
44 | struct addrinfo hints, *res, *res0; | 44 | struct addrinfo hints, *res, *res0; |
45 | int s, error; | 45 | int s, error; |
46 | 46 | ||
47 | memset(&hints, 0, sizeof(hints)); | 47 | memset(&hints, 0, sizeof(hints)); |
48 | hints.ai_family = PF_UNSPEC; | 48 | hints.ai_family = PF_UNSPEC; |
49 | hints.ai_socktype = SOCK_STREAM; | 49 | hints.ai_socktype = SOCK_STREAM; |
50 | error = getaddrinfo( server, port, &hints, &res0 ); | 50 | error = getaddrinfo(server, port, &hints, &res0); |
51 | if (error) return -1; | 51 | if (error) |
52 | return -1; | ||
52 | s = -1; | 53 | s = -1; |
53 | for (res = res0; res; res = res->ai_next) { | 54 | for (res = res0; res; res = res->ai_next) { |
54 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | 55 | s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); |
55 | if (s < 0) continue; | 56 | if (s < 0) |
57 | continue; | ||
56 | if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { | 58 | if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { |
57 | close(s); | 59 | close(s); |
58 | s = -1; | 60 | s = -1; |
59 | continue; | 61 | continue; |
60 | } | 62 | } |
61 | break; /* okay we got one */ | 63 | break; /* okay we got one */ |
62 | } | 64 | } |
63 | freeaddrinfo(res0); | 65 | freeaddrinfo(res0); |
64 | 66 | ||
65 | if (want_tcp_keepalive) { | 67 | if (want_tcp_keepalive) { |
66 | int one=1; | 68 | int one = 1; |
67 | setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one)); | 69 | setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)); |
68 | } | 70 | } |
69 | return s; | 71 | return s; |
70 | } | 72 | } |
71 | 73 | ||
72 | /* Return a tilde expanded path in a malloced buffer or NULL */ | 74 | /* Return a tilde expanded path in a malloced buffer or NULL */ |
73 | static char *get_tilde_expanded(confopt opt) { | 75 | static char *get_tilde_expanded(confopt opt) { |
74 | char *str = getstroption (opt); | 76 | char *str = getstroption(opt); |
75 | if (!str) | 77 | if (!str) |
76 | return str; | 78 | return str; |
77 | if (str[0] == '~') | 79 | if (str[0] == '~') |
78 | return tilde_expand (str); | 80 | return tilde_expand(str); |
79 | return strdup(str); | 81 | return strdup(str); |
80 | } | 82 | } |
81 | 83 | ||
82 | /* connects to server */ | 84 | /* connects to server */ |
83 | int | 85 | int vc_connect(const char *server, const char *port) { |
84 | vc_connect (const char *server, const char *port) | ||
85 | { | ||
86 | /* vchat connection x509 store */ | 86 | /* vchat connection x509 store */ |
87 | vc_x509store_t vc_store; | 87 | vc_x509store_t vc_store; |
88 | 88 | ||
@@ -90,11 +90,11 @@ vc_connect (const char *server, const char *port) | |||
90 | char *certfile, *cafile; | 90 | char *certfile, *cafile; |
91 | 91 | ||
92 | /* Connect to the server */ | 92 | /* Connect to the server */ |
93 | serverfd = connect_tcp_socket( server, port ); | 93 | serverfd = connect_tcp_socket(server, port); |
94 | if( serverfd < 0 ) { | 94 | if (serverfd < 0) { |
95 | /* inform user */ | 95 | /* inform user */ |
96 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | 96 | snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port); |
97 | writechan (tmpstr); | 97 | writechan(tmpstr); |
98 | return -1; | 98 | return -1; |
99 | } | 99 | } |
100 | 100 | ||
@@ -105,11 +105,11 @@ vc_connect (const char *server, const char *port) | |||
105 | vc_init_x509store(&vc_store); | 105 | vc_init_x509store(&vc_store); |
106 | 106 | ||
107 | /* get name of certificate file */ | 107 | /* get name of certificate file */ |
108 | certfile = get_tilde_expanded (CF_CERTFILE); | 108 | certfile = get_tilde_expanded(CF_CERTFILE); |
109 | /* do we have a certificate file? */ | 109 | /* do we have a certificate file? */ |
110 | if (certfile) { | 110 | if (certfile) { |
111 | /* get name of key file */ | 111 | /* get name of key file */ |
112 | char *keyfile = get_tilde_expanded (CF_KEYFILE); | 112 | char *keyfile = get_tilde_expanded(CF_KEYFILE); |
113 | 113 | ||
114 | vc_x509store_setcertfile(&vc_store, certfile); | 114 | vc_x509store_setcertfile(&vc_store, certfile); |
115 | vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); | 115 | vc_x509store_set_pkeycb(&vc_store, (vc_askpass_cb_t)passprompt); |
@@ -122,13 +122,13 @@ vc_connect (const char *server, const char *port) | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /* get name of ca file */ | 124 | /* get name of ca file */ |
125 | cafile = get_tilde_expanded (CF_CAFILE); | 125 | cafile = get_tilde_expanded(CF_CAFILE); |
126 | if (cafile && !access(cafile, F_OK)) | 126 | if (cafile && !access(cafile, F_OK)) |
127 | vc_x509store_setcafile(&vc_store, cafile); | 127 | vc_x509store_setcafile(&vc_store, cafile); |
128 | free(cafile); | 128 | free(cafile); |
129 | 129 | ||
130 | /* upgrade our plain BIO to ssl */ | 130 | /* upgrade our plain BIO to ssl */ |
131 | int result = vc_tls_connect( serverfd, &vc_store ); | 131 | int result = vc_tls_connect(serverfd, &vc_store); |
132 | vc_cleanup_x509store(&vc_store); | 132 | vc_cleanup_x509store(&vc_store); |
133 | 133 | ||
134 | if (result) { | 134 | if (result) { |
@@ -136,17 +136,17 @@ vc_connect (const char *server, const char *port) | |||
136 | serverfd = -1; | 136 | serverfd = -1; |
137 | errno = EIO; | 137 | errno = EIO; |
138 | vc_tls_cleanup(); | 138 | vc_tls_cleanup(); |
139 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port ); | 139 | snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port); |
140 | writechan (tmpstr); | 140 | writechan(tmpstr); |
141 | return -1; | 141 | return -1; |
142 | } | 142 | } |
143 | 143 | ||
144 | /* inform user */ | 144 | /* inform user */ |
145 | snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); | 145 | snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port); |
146 | writechan (tmpstr); | 146 | writechan(tmpstr); |
147 | 147 | ||
148 | #ifdef DEBUG | 148 | #ifdef DEBUG |
149 | dumpfile = fopen( "dumpfile", "a"); | 149 | dumpfile = fopen("dumpfile", "a"); |
150 | #endif | 150 | #endif |
151 | 151 | ||
152 | /* if we didn't fail until now, we've got a connection. */ | 152 | /* if we didn't fail until now, we've got a connection. */ |
@@ -154,25 +154,24 @@ vc_connect (const char *server, const char *port) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* Poll for activity on the socket or stdin */ | 156 | /* Poll for activity on the socket or stdin */ |
157 | int vc_poll (int timeout_seconds) { | 157 | int vc_poll(int timeout_seconds) { |
158 | fd_set readfds; | 158 | fd_set readfds; |
159 | FD_ZERO (&readfds); | 159 | FD_ZERO(&readfds); |
160 | FD_SET (0, &readfds); | 160 | FD_SET(0, &readfds); |
161 | if (serverfd != -1) | 161 | if (serverfd != -1) |
162 | FD_SET (serverfd, &readfds); | 162 | FD_SET(serverfd, &readfds); |
163 | struct timeval tv = { timeout_seconds, 0}; | 163 | struct timeval tv = {timeout_seconds, 0}; |
164 | int result = select (serverfd + 2, &readfds, NULL, NULL, &tv); | 164 | int result = select(serverfd + 2, &readfds, NULL, NULL, &tv); |
165 | if (result <= 0) | 165 | if (result <= 0) |
166 | return result; | 166 | return result; |
167 | result = FD_ISSET (0, &readfds) ? 1 : 0; | 167 | result = FD_ISSET(0, &readfds) ? 1 : 0; |
168 | if (serverfd != -1) | 168 | if (serverfd != -1) |
169 | result += FD_ISSET (serverfd, &readfds) ? 2 : 0; | 169 | result += FD_ISSET(serverfd, &readfds) ? 2 : 0; |
170 | return result; | 170 | return result; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* disconnect from server */ | 173 | /* disconnect from server */ |
174 | void | 174 | void vc_disconnect() { |
175 | vc_disconnect () { | ||
176 | if (serverfd > 0) { | 175 | if (serverfd > 0) { |
177 | close(serverfd); | 176 | close(serverfd); |
178 | serverfd = -1; | 177 | serverfd = -1; |
@@ -183,21 +182,19 @@ vc_disconnect () { | |||
183 | 182 | ||
184 | #define STAGINGSIZE 16384 | 183 | #define STAGINGSIZE 16384 |
185 | static char _staging[STAGINGSIZE]; | 184 | static char _staging[STAGINGSIZE]; |
186 | void | 185 | void vc_sendmessage(const char *msg) { |
187 | vc_sendmessage (const char *msg) | ||
188 | { | ||
189 | size_t sent, len = snprintf(_staging, sizeof(_staging), "%s\r\n", msg); | 186 | size_t sent, len = snprintf(_staging, sizeof(_staging), "%s\r\n", msg); |
190 | #ifdef DEBUG | 187 | #ifdef DEBUG |
191 | /* debugging? log network output! */ | 188 | /* debugging? log network output! */ |
192 | fprintf (dumpfile, ">| (%zd) %s\n", len - 2, msg); | 189 | fprintf(dumpfile, ">| (%zd) %s\n", len - 2, msg); |
193 | #endif | 190 | #endif |
194 | 191 | ||
195 | if (getintoption(CF_USESSL)) | 192 | if (getintoption(CF_USESSL)) |
196 | sent = vc_tls_sendmessage (_staging, len); | 193 | sent = vc_tls_sendmessage(_staging, len); |
197 | else | 194 | else |
198 | sent = write (serverfd, _staging, len); | 195 | sent = write(serverfd, _staging, len); |
199 | if (sent != len) | 196 | if (sent != len) |
200 | writecf (FS_ERR,"Message sending fuzzy."); | 197 | writecf(FS_ERR, "Message sending fuzzy."); |
201 | } | 198 | } |
202 | 199 | ||
203 | /* offset in buffer (for linebreaks at packet borders) */ | 200 | /* offset in buffer (for linebreaks at packet borders) */ |
@@ -206,9 +203,7 @@ static char _buf[BUFSIZE]; | |||
206 | static size_t _buf_fill; | 203 | static size_t _buf_fill; |
207 | 204 | ||
208 | /* get data from servers connection */ | 205 | /* get data from servers connection */ |
209 | void | 206 | void vc_receive(void) { |
210 | vc_receive (void) | ||
211 | { | ||
212 | char *endmsg; | 207 | char *endmsg; |
213 | size_t freebytes = BUFSIZE - _buf_fill; | 208 | size_t freebytes = BUFSIZE - _buf_fill; |
214 | ssize_t bytes; | 209 | ssize_t bytes; |
@@ -218,26 +213,27 @@ vc_receive (void) | |||
218 | else | 213 | else |
219 | bytes = vc_tls_receivemessage(_buf + _buf_fill, freebytes); | 214 | bytes = vc_tls_receivemessage(_buf + _buf_fill, freebytes); |
220 | 215 | ||
221 | /* Our tls functions may require retries with handshakes etc, this is signalled by -2 */ | 216 | /* Our tls functions may require retries with handshakes etc, this is |
217 | * signalled by -2 */ | ||
222 | if (bytes == -2) | 218 | if (bytes == -2) |
223 | return; | 219 | return; |
224 | 220 | ||
225 | /* Error on the socket read? raise error message, bail out */ | 221 | /* Error on the socket read? raise error message, bail out */ |
226 | if (bytes == -1) { | 222 | if (bytes == -1) { |
227 | snprintf (tmpstr, TMPSTRSIZE, "Receive fails, %s.", strerror(errno)); | 223 | snprintf(tmpstr, TMPSTRSIZE, "Receive fails, %s.", strerror(errno)); |
228 | snprintf (errstr, ERRSTRSIZE, "Receive fails, %s.\n", strerror(errno)); | 224 | snprintf(errstr, ERRSTRSIZE, "Receive fails, %s.\n", strerror(errno)); |
229 | writecf (FS_ERR,tmpstr); | 225 | writecf(FS_ERR, tmpstr); |
230 | status = 0; | 226 | status = 0; |
231 | return; | 227 | return; |
232 | } | 228 | } |
233 | 229 | ||
234 | /* end of file from server? */ | 230 | /* end of file from server? */ |
235 | if (bytes == 0) { | 231 | if (bytes == 0) { |
236 | /* inform user, bail out */ | 232 | /* inform user, bail out */ |
237 | writecf (FS_SERV, "* EOF from server."); | 233 | writecf(FS_SERV, "* EOF from server."); |
238 | snprintf (errstr, ERRSTRSIZE, "* EOF from server.\n"); | 234 | snprintf(errstr, ERRSTRSIZE, "* EOF from server.\n"); |
239 | status = 0; | 235 | status = 0; |
240 | return; | 236 | return; |
241 | } | 237 | } |
242 | 238 | ||
243 | _buf_fill += bytes; | 239 | _buf_fill += bytes; |
@@ -249,13 +245,14 @@ vc_receive (void) | |||
249 | endmsg[0] = 0; | 245 | endmsg[0] = 0; |
250 | if (endmsg[-1] == '\r') | 246 | if (endmsg[-1] == '\r') |
251 | endmsg[-1] = 0; | 247 | endmsg[-1] = 0; |
252 | /* If terminating and chomping left us with a message, give it to line handler */ | 248 | /* If terminating and chomping left us with a message, give it to line |
249 | * handler */ | ||
253 | if (_buf[0]) { | 250 | if (_buf[0]) { |
254 | #ifdef DEBUG | 251 | #ifdef DEBUG |
255 | /* debugging? log network input! */ | 252 | /* debugging? log network input! */ |
256 | fprintf (stderr, "<| %s\n", _buf); | 253 | fprintf(stderr, "<| %s\n", _buf); |
257 | #endif | 254 | #endif |
258 | protocol_parsemsg (_buf); | 255 | protocol_parsemsg(_buf); |
259 | } | 256 | } |
260 | } | 257 | } |
261 | _buf_fill -= 1 + endmsg - _buf; | 258 | _buf_fill -= 1 + endmsg - _buf; |