dynwatch
diff socklib.c @ 0:ce3c5e4c75bf
dynwatch DynDNS updater for windows
author | John Tsiombikas <nuclear@siggraph.org> |
---|---|
date | Wed, 18 May 2011 05:53:29 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/socklib.c Wed May 18 05:53:29 2011 +0300 1.3 @@ -0,0 +1,246 @@ 1.4 +/* 1.5 +This file is part of socklib, a cross-platform socket library. 1.6 + 1.7 +Copyright (c) 2004 John Tsiombikas <nuclear@siggraph.org> 1.8 + 1.9 +This library is free software; you can redistribute it and/or modify 1.10 +it under the terms of the GNU General Public License as published by 1.11 +the Free Software Foundation; either version 2 of the License, or 1.12 +(at your option) any later version. 1.13 + 1.14 +This library is distributed in the hope that it will be useful, 1.15 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.16 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.17 +GNU General Public License for more details. 1.18 + 1.19 +You should have received a copy of the GNU General Public License 1.20 +along with this library; if not, write to the Free Software 1.21 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.22 +*/ 1.23 + 1.24 +#include <stdio.h> 1.25 +#include <stdlib.h> 1.26 +#include <string.h> 1.27 +#include <errno.h> 1.28 + 1.29 +#ifdef __unix__ 1.30 +#define __USE_BSD 1.31 +#include <unistd.h> 1.32 +#include <fcntl.h> 1.33 +#include <sys/types.h> 1.34 +#include <sys/socket.h> 1.35 +#include <sys/ioctl.h> 1.36 +#include <sys/param.h> 1.37 +#include <sys/select.h> 1.38 +#include <netdb.h> 1.39 +#include <netinet/in.h> 1.40 +#include <arpa/inet.h> 1.41 + 1.42 +#else /* assume win32 if not unix */ 1.43 + 1.44 +#include <winsock2.h> 1.45 + 1.46 +#define MAXHOSTNAMELEN 255 1.47 +#define close(s) closesocket(s) 1.48 + 1.49 +static int winsock_initialized; 1.50 +#endif /* __unix__ */ 1.51 + 1.52 +#include "socklib.h" 1.53 + 1.54 +#ifdef _MSC_VER 1.55 +#define __func__ __FUNCTION__ 1.56 +#endif /* _MSC_VER */ 1.57 + 1.58 +static int verbose = 1; 1.59 + 1.60 +int sl_listen(int port) { 1.61 + int s; 1.62 + struct sockaddr_in addr; 1.63 + struct hostent *host; 1.64 + char host_name[MAXHOSTNAMELEN+1]; 1.65 + 1.66 +#ifndef __unix__ 1.67 + if(!winsock_initialized) { 1.68 + WSADATA wsa_data; 1.69 + WSAStartup(MAKEWORD(1, 1), &wsa_data); 1.70 + winsock_initialized = 1; 1.71 + } 1.72 +#endif /* __unix__ */ 1.73 + 1.74 + if(gethostname(host_name, MAXHOSTNAMELEN+1) == -1) { 1.75 + if(verbose) perror("socklib error @ gethostname"); 1.76 + return -1; 1.77 + } 1.78 + 1.79 + if(!(host = gethostbyname(host_name))) { 1.80 + if(verbose) perror("socklib error @ gethostbyname"); 1.81 + return -1; 1.82 + } 1.83 + 1.84 + memset(&addr, 0, sizeof(struct sockaddr_in)); 1.85 + addr.sin_family = host->h_addrtype; 1.86 + addr.sin_port = htons(port); 1.87 + addr.sin_addr.s_addr = INADDR_ANY; 1.88 + 1.89 + if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1.90 + if(verbose) perror("socklib error @ socket"); 1.91 + return -1; 1.92 + } 1.93 + 1.94 + if(bind(s, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) { 1.95 + if(verbose) perror("socklib error @ bind"); 1.96 + close(s); 1.97 + return -1; 1.98 + } 1.99 + 1.100 + if(listen(s, 5) == -1) { 1.101 + if(verbose) perror("socklib error @ listen"); 1.102 + close(s); 1.103 + return -1; 1.104 + } 1.105 + 1.106 + return s; 1.107 +} 1.108 + 1.109 + 1.110 +int sl_accept(int listening_socket) { 1.111 + return accept(listening_socket, 0, 0); 1.112 +} 1.113 + 1.114 +int sl_connect_tcp(char *ipaddr, const char *hostname, int port) { 1.115 + int s, must_free_ipaddr = 0; 1.116 + struct sockaddr_in addr; 1.117 + struct hostent *host; 1.118 + 1.119 +#ifndef __unix__ 1.120 + if(!winsock_initialized) { 1.121 + WSADATA wsa_data; 1.122 + WSAStartup(MAKEWORD(1, 1), &wsa_data); 1.123 + winsock_initialized = 1; 1.124 + } 1.125 +#endif /* __unix__ */ 1.126 + 1.127 + if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1.128 + if(verbose) perror("socklib error @ socket"); 1.129 + return -1; 1.130 + } 1.131 + 1.132 + if(!ipaddr) { 1.133 + if(!hostname) return -1; 1.134 + 1.135 + ipaddr = malloc(20); 1.136 + must_free_ipaddr = 1; 1.137 + host = gethostbyname(hostname); 1.138 + 1.139 + if(!host) { 1.140 + if(verbose) perror("socklib error @ gethostbyname"); 1.141 + free(ipaddr); 1.142 + return -1; 1.143 + } 1.144 + 1.145 + strcpy(ipaddr, inet_ntoa(*((struct in_addr*)host->h_addr))); 1.146 + } 1.147 + 1.148 + memset(&addr, 0, sizeof(struct sockaddr_in)); 1.149 + addr.sin_family = AF_INET; 1.150 + addr.sin_port = htons(port); 1.151 + addr.sin_addr.s_addr = inet_addr(ipaddr); 1.152 + 1.153 + if((connect(s, (struct sockaddr*)&addr, sizeof(struct sockaddr))) == -1) { 1.154 + if(verbose) perror("socklib error @ connect"); 1.155 + if(must_free_ipaddr) free(ipaddr); 1.156 + return -1; 1.157 + } 1.158 + 1.159 + if(must_free_ipaddr) free(ipaddr); 1.160 + return s; 1.161 +} 1.162 + 1.163 + 1.164 +void sl_close_socket(int s) { 1.165 + char buffer[128]; 1.166 + 1.167 + shutdown(s, 1); 1.168 + while(recv(s, buffer, 128, 0)); 1.169 + close(s); 1.170 +} 1.171 + 1.172 +int sl_send_data(int s, const char *buffer, int size) { 1.173 + const char *ptr = buffer; 1.174 + const char *end = buffer + size; 1.175 + 1.176 + while(ptr < end) { 1.177 + int bytes = send(s, ptr, end - ptr, 0); 1.178 + if(bytes == -1) { 1.179 + if(verbose) { 1.180 + char errstr[80]; 1.181 + sprintf(errstr, "socklib error @ %s", __func__); 1.182 + perror(errstr); 1.183 + } 1.184 + return -1; 1.185 + } 1.186 + ptr += bytes; 1.187 + } 1.188 + 1.189 + return size; 1.190 +} 1.191 + 1.192 +int sl_recv_data(int s, char *buffer, int size) { 1.193 + int bytes = recv(s, buffer, size, 0); 1.194 + if(bytes == -1) { 1.195 + if(verbose) { 1.196 + char errstr[80]; 1.197 + sprintf(errstr, "socklib error @ %s", __func__); 1.198 + perror(errstr); 1.199 + } 1.200 + return -1; 1.201 + } 1.202 + return bytes; 1.203 +} 1.204 + 1.205 + 1.206 +/* if SL_CHK_IMMED is NOT specified then: 1.207 + * if timeout is 0: block forever, else block for so many milliseconds. 1.208 + */ 1.209 +int sl_check_socket(int s, int flags, unsigned int timeout) { 1.210 + int res; 1.211 + fd_set rfds, wfds; 1.212 + struct timeval tv, *tvptr; 1.213 + tv.tv_sec = tv.tv_usec = 0; 1.214 + 1.215 + tvptr = (flags & SL_CHK_IMMED) ? &tv : 0; 1.216 + 1.217 + if(flags & SL_CHK_IMMED) { 1.218 + tvptr = &tv; 1.219 + } else { 1.220 + tvptr = timeout > 0 ? &tv : 0; 1.221 + 1.222 + tv.tv_sec = timeout / 1000; 1.223 + tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000; 1.224 + } 1.225 + 1.226 + 1.227 + FD_ZERO(&rfds); 1.228 + FD_ZERO(&wfds); 1.229 + 1.230 + if(flags & SL_CHK_READ) { 1.231 + FD_SET(s, &rfds); 1.232 + if((res = select(s+1, &rfds, 0, 0, tvptr)) == -1) { 1.233 + return -1; 1.234 + } 1.235 + return FD_ISSET(s, &rfds) ? 1 : 0; 1.236 + } else if(flags & SL_CHK_WRITE) { 1.237 + FD_SET(s, &wfds); 1.238 + if((res = select(s+1, 0, &wfds, 0, tvptr)) == -1) { 1.239 + return -1; 1.240 + } 1.241 + return FD_ISSET(s, &wfds) ? 1 : 0; 1.242 + } 1.243 + 1.244 + return -1; 1.245 +} 1.246 + 1.247 +void sl_set_verbosity(int vlevel) { 1.248 + verbose = vlevel; 1.249 +}