dynwatch

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