summaryrefslogtreecommitdiff
path: root/vchat-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-connection.c')
-rw-r--r--vchat-connection.c133
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
35static int serverfd = -1; 35static int serverfd = -1;
36unsigned int want_tcp_keepalive = 0; 36unsigned int want_tcp_keepalive = 0;
@@ -40,49 +40,49 @@ unsigned int want_tcp_keepalive = 0;
40extern int status; 40extern int status;
41 41
42/* Generic tcp connector, blocking */ 42/* Generic tcp connector, blocking */
43static int connect_tcp_socket( const char *server, const char *port ) { 43static 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 */
73static char *get_tilde_expanded(confopt opt) { 75static 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 */
83int 85int vc_connect(const char *server, const char *port) {
84vc_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 */
157int vc_poll (int timeout_seconds) { 157int 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 */
174void 174void vc_disconnect() {
175vc_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
185static char _staging[STAGINGSIZE]; 184static char _staging[STAGINGSIZE];
186void 185void vc_sendmessage(const char *msg) {
187vc_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];
206static size_t _buf_fill; 203static size_t _buf_fill;
207 204
208/* get data from servers connection */ 205/* get data from servers connection */
209void 206void vc_receive(void) {
210vc_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;