dynwatch

annotate 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
rev   line source
nuclear@0 1 /*
nuclear@0 2 This file is part of socklib, a cross-platform socket library.
nuclear@0 3
nuclear@0 4 Copyright (c) 2004 John Tsiombikas <nuclear@siggraph.org>
nuclear@0 5
nuclear@0 6 This library is free software; you can redistribute it and/or modify
nuclear@0 7 it under the terms of the GNU General Public License as published by
nuclear@0 8 the Free Software Foundation; either version 2 of the License, or
nuclear@0 9 (at your option) any later version.
nuclear@0 10
nuclear@0 11 This library is distributed in the hope that it will be useful,
nuclear@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@0 14 GNU General Public License for more details.
nuclear@0 15
nuclear@0 16 You should have received a copy of the GNU General Public License
nuclear@0 17 along with this library; if not, write to the Free Software
nuclear@0 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
nuclear@0 19 */
nuclear@0 20
nuclear@0 21 #include <stdio.h>
nuclear@0 22 #include <stdlib.h>
nuclear@0 23 #include <string.h>
nuclear@0 24 #include <errno.h>
nuclear@0 25
nuclear@0 26 #ifdef __unix__
nuclear@0 27 #define __USE_BSD
nuclear@0 28 #include <unistd.h>
nuclear@0 29 #include <fcntl.h>
nuclear@0 30 #include <sys/types.h>
nuclear@0 31 #include <sys/socket.h>
nuclear@0 32 #include <sys/ioctl.h>
nuclear@0 33 #include <sys/param.h>
nuclear@0 34 #include <sys/select.h>
nuclear@0 35 #include <netdb.h>
nuclear@0 36 #include <netinet/in.h>
nuclear@0 37 #include <arpa/inet.h>
nuclear@0 38
nuclear@0 39 #else /* assume win32 if not unix */
nuclear@0 40
nuclear@0 41 #include <winsock2.h>
nuclear@0 42
nuclear@0 43 #define MAXHOSTNAMELEN 255
nuclear@0 44 #define close(s) closesocket(s)
nuclear@0 45
nuclear@0 46 static int winsock_initialized;
nuclear@0 47 #endif /* __unix__ */
nuclear@0 48
nuclear@0 49 #include "socklib.h"
nuclear@0 50
nuclear@0 51 #ifdef _MSC_VER
nuclear@0 52 #define __func__ __FUNCTION__
nuclear@0 53 #endif /* _MSC_VER */
nuclear@0 54
nuclear@0 55 static int verbose = 1;
nuclear@0 56
nuclear@0 57 int sl_listen(int port) {
nuclear@0 58 int s;
nuclear@0 59 struct sockaddr_in addr;
nuclear@0 60 struct hostent *host;
nuclear@0 61 char host_name[MAXHOSTNAMELEN+1];
nuclear@0 62
nuclear@0 63 #ifndef __unix__
nuclear@0 64 if(!winsock_initialized) {
nuclear@0 65 WSADATA wsa_data;
nuclear@0 66 WSAStartup(MAKEWORD(1, 1), &wsa_data);
nuclear@0 67 winsock_initialized = 1;
nuclear@0 68 }
nuclear@0 69 #endif /* __unix__ */
nuclear@0 70
nuclear@0 71 if(gethostname(host_name, MAXHOSTNAMELEN+1) == -1) {
nuclear@0 72 if(verbose) perror("socklib error @ gethostname");
nuclear@0 73 return -1;
nuclear@0 74 }
nuclear@0 75
nuclear@0 76 if(!(host = gethostbyname(host_name))) {
nuclear@0 77 if(verbose) perror("socklib error @ gethostbyname");
nuclear@0 78 return -1;
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 memset(&addr, 0, sizeof(struct sockaddr_in));
nuclear@0 82 addr.sin_family = host->h_addrtype;
nuclear@0 83 addr.sin_port = htons(port);
nuclear@0 84 addr.sin_addr.s_addr = INADDR_ANY;
nuclear@0 85
nuclear@0 86 if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
nuclear@0 87 if(verbose) perror("socklib error @ socket");
nuclear@0 88 return -1;
nuclear@0 89 }
nuclear@0 90
nuclear@0 91 if(bind(s, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1) {
nuclear@0 92 if(verbose) perror("socklib error @ bind");
nuclear@0 93 close(s);
nuclear@0 94 return -1;
nuclear@0 95 }
nuclear@0 96
nuclear@0 97 if(listen(s, 5) == -1) {
nuclear@0 98 if(verbose) perror("socklib error @ listen");
nuclear@0 99 close(s);
nuclear@0 100 return -1;
nuclear@0 101 }
nuclear@0 102
nuclear@0 103 return s;
nuclear@0 104 }
nuclear@0 105
nuclear@0 106
nuclear@0 107 int sl_accept(int listening_socket) {
nuclear@0 108 return accept(listening_socket, 0, 0);
nuclear@0 109 }
nuclear@0 110
nuclear@0 111 int sl_connect_tcp(char *ipaddr, const char *hostname, int port) {
nuclear@0 112 int s, must_free_ipaddr = 0;
nuclear@0 113 struct sockaddr_in addr;
nuclear@0 114 struct hostent *host;
nuclear@0 115
nuclear@0 116 #ifndef __unix__
nuclear@0 117 if(!winsock_initialized) {
nuclear@0 118 WSADATA wsa_data;
nuclear@0 119 WSAStartup(MAKEWORD(1, 1), &wsa_data);
nuclear@0 120 winsock_initialized = 1;
nuclear@0 121 }
nuclear@0 122 #endif /* __unix__ */
nuclear@0 123
nuclear@0 124 if((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
nuclear@0 125 if(verbose) perror("socklib error @ socket");
nuclear@0 126 return -1;
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 if(!ipaddr) {
nuclear@0 130 if(!hostname) return -1;
nuclear@0 131
nuclear@0 132 ipaddr = malloc(20);
nuclear@0 133 must_free_ipaddr = 1;
nuclear@0 134 host = gethostbyname(hostname);
nuclear@0 135
nuclear@0 136 if(!host) {
nuclear@0 137 if(verbose) perror("socklib error @ gethostbyname");
nuclear@0 138 free(ipaddr);
nuclear@0 139 return -1;
nuclear@0 140 }
nuclear@0 141
nuclear@0 142 strcpy(ipaddr, inet_ntoa(*((struct in_addr*)host->h_addr)));
nuclear@0 143 }
nuclear@0 144
nuclear@0 145 memset(&addr, 0, sizeof(struct sockaddr_in));
nuclear@0 146 addr.sin_family = AF_INET;
nuclear@0 147 addr.sin_port = htons(port);
nuclear@0 148 addr.sin_addr.s_addr = inet_addr(ipaddr);
nuclear@0 149
nuclear@0 150 if((connect(s, (struct sockaddr*)&addr, sizeof(struct sockaddr))) == -1) {
nuclear@0 151 if(verbose) perror("socklib error @ connect");
nuclear@0 152 if(must_free_ipaddr) free(ipaddr);
nuclear@0 153 return -1;
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 if(must_free_ipaddr) free(ipaddr);
nuclear@0 157 return s;
nuclear@0 158 }
nuclear@0 159
nuclear@0 160
nuclear@0 161 void sl_close_socket(int s) {
nuclear@0 162 char buffer[128];
nuclear@0 163
nuclear@0 164 shutdown(s, 1);
nuclear@0 165 while(recv(s, buffer, 128, 0));
nuclear@0 166 close(s);
nuclear@0 167 }
nuclear@0 168
nuclear@0 169 int sl_send_data(int s, const char *buffer, int size) {
nuclear@0 170 const char *ptr = buffer;
nuclear@0 171 const char *end = buffer + size;
nuclear@0 172
nuclear@0 173 while(ptr < end) {
nuclear@0 174 int bytes = send(s, ptr, end - ptr, 0);
nuclear@0 175 if(bytes == -1) {
nuclear@0 176 if(verbose) {
nuclear@0 177 char errstr[80];
nuclear@0 178 sprintf(errstr, "socklib error @ %s", __func__);
nuclear@0 179 perror(errstr);
nuclear@0 180 }
nuclear@0 181 return -1;
nuclear@0 182 }
nuclear@0 183 ptr += bytes;
nuclear@0 184 }
nuclear@0 185
nuclear@0 186 return size;
nuclear@0 187 }
nuclear@0 188
nuclear@0 189 int sl_recv_data(int s, char *buffer, int size) {
nuclear@0 190 int bytes = recv(s, buffer, size, 0);
nuclear@0 191 if(bytes == -1) {
nuclear@0 192 if(verbose) {
nuclear@0 193 char errstr[80];
nuclear@0 194 sprintf(errstr, "socklib error @ %s", __func__);
nuclear@0 195 perror(errstr);
nuclear@0 196 }
nuclear@0 197 return -1;
nuclear@0 198 }
nuclear@0 199 return bytes;
nuclear@0 200 }
nuclear@0 201
nuclear@0 202
nuclear@0 203 /* if SL_CHK_IMMED is NOT specified then:
nuclear@0 204 * if timeout is 0: block forever, else block for so many milliseconds.
nuclear@0 205 */
nuclear@0 206 int sl_check_socket(int s, int flags, unsigned int timeout) {
nuclear@0 207 int res;
nuclear@0 208 fd_set rfds, wfds;
nuclear@0 209 struct timeval tv, *tvptr;
nuclear@0 210 tv.tv_sec = tv.tv_usec = 0;
nuclear@0 211
nuclear@0 212 tvptr = (flags & SL_CHK_IMMED) ? &tv : 0;
nuclear@0 213
nuclear@0 214 if(flags & SL_CHK_IMMED) {
nuclear@0 215 tvptr = &tv;
nuclear@0 216 } else {
nuclear@0 217 tvptr = timeout > 0 ? &tv : 0;
nuclear@0 218
nuclear@0 219 tv.tv_sec = timeout / 1000;
nuclear@0 220 tv.tv_usec = (timeout - tv.tv_sec * 1000) * 1000;
nuclear@0 221 }
nuclear@0 222
nuclear@0 223
nuclear@0 224 FD_ZERO(&rfds);
nuclear@0 225 FD_ZERO(&wfds);
nuclear@0 226
nuclear@0 227 if(flags & SL_CHK_READ) {
nuclear@0 228 FD_SET(s, &rfds);
nuclear@0 229 if((res = select(s+1, &rfds, 0, 0, tvptr)) == -1) {
nuclear@0 230 return -1;
nuclear@0 231 }
nuclear@0 232 return FD_ISSET(s, &rfds) ? 1 : 0;
nuclear@0 233 } else if(flags & SL_CHK_WRITE) {
nuclear@0 234 FD_SET(s, &wfds);
nuclear@0 235 if((res = select(s+1, 0, &wfds, 0, tvptr)) == -1) {
nuclear@0 236 return -1;
nuclear@0 237 }
nuclear@0 238 return FD_ISSET(s, &wfds) ? 1 : 0;
nuclear@0 239 }
nuclear@0 240
nuclear@0 241 return -1;
nuclear@0 242 }
nuclear@0 243
nuclear@0 244 void sl_set_verbosity(int vlevel) {
nuclear@0 245 verbose = vlevel;
nuclear@0 246 }