sock.c (2179B)
1 /* dmc - dynamic mail client 2 * See LICENSE file for copyright and license details. 3 */ 4 5 #include <stdio.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <poll.h> 9 #include <stdarg.h> 10 #include <netdb.h> 11 #include <arpa/inet.h> 12 #include <sys/socket.h> 13 #include <netinet/in.h> 14 15 #if HAVE_SSL 16 #include <openssl/ssl.h> 17 static SSL_CTX *ctx; 18 static SSL *sfd; 19 #endif 20 static int ssl = 0; 21 static int fd = -1; 22 23 int sock_ssl (int fd) { 24 #if HAVE_SSL 25 // TODO Check certificate 26 SSL_library_init (); 27 SSL_load_error_strings (); 28 OpenSSL_add_all_algorithms (); 29 ctx = SSL_CTX_new (SSLv23_method ()); 30 sfd = SSL_new (ctx); 31 SSL_set_fd (sfd, fd); 32 if (SSL_connect (sfd) < 1) 33 return -1; 34 #endif 35 return fd; 36 } 37 38 int sock_connect(const char *host, int port, int ssl_enable) { 39 struct sockaddr_in sa; 40 struct hostent *he; 41 int s = socket (AF_INET, SOCK_STREAM, 0); 42 ssl = ssl_enable, fd = -1; 43 if (s != -1) { 44 memset (&sa, 0, sizeof (sa)); 45 sa.sin_family = AF_INET; 46 he = (struct hostent *)gethostbyname (host); 47 if (he != (struct hostent*)0) { 48 sa.sin_addr = *((struct in_addr *)he->h_addr); 49 sa.sin_port = htons (port); 50 if (!connect (s, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) 51 fd = ssl ? sock_ssl (s) : s; 52 } 53 if (fd == -1) 54 close (s); 55 } 56 return fd; 57 } 58 59 int sock_ready() { 60 #if HAVE_SSL 61 if (ssl && SSL_pending (sfd)) 62 return 1; 63 #endif 64 struct pollfd fds[1]; 65 fds[0].fd = fd; 66 fds[0].events = POLLIN|POLLPRI; 67 fds[0].revents = POLLNVAL|POLLHUP|POLLERR; 68 return poll (fds, 1, 1000); 69 } 70 71 void sock_close() { 72 #if HAVE_SSL 73 SSL_CTX_free (ctx); 74 SSL_free (sfd); 75 #endif 76 close (fd); 77 } 78 79 int sock_write(const char *str) { 80 #if HAVE_SSL 81 if (ssl) 82 return SSL_write (sfd, str, strlen(str)); 83 #endif 84 return write (fd, str, strlen(str)); 85 } 86 87 int sock_printf(const char *fmt, ...) { 88 va_list ap; 89 int ret = -1; 90 char buf[1024]; 91 va_start (ap, fmt); 92 vsnprintf (buf, sizeof (buf), fmt, ap); 93 // XXX check len 94 ret = sock_write (buf); 95 va_end (ap); 96 return ret; 97 } 98 99 int sock_read (char *buf, int len) { 100 int ret; 101 memset (buf, 0, len+1); 102 #if HAVE_SSL 103 if (ssl) ret = SSL_read (sfd, buf, len); 104 else 105 #endif 106 ret = read (fd, buf, len); 107 if (ret>0) 108 buf[ret] = '\0'; 109 return ret; 110 }