| 40 |
40 |
| 41 #ifndef S_ISDIR |
41 #ifndef S_ISDIR |
| 42 # define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR) |
42 # define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR) |
| 43 #endif |
43 #endif |
| 44 |
44 |
| 45 /* helpers */ |
|
| 46 static int wpurple_is_socket( int fd ) { |
|
| 47 int optval; |
|
| 48 int optlen = sizeof(int); |
|
| 49 |
|
| 50 if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) { |
|
| 51 int error = WSAGetLastError(); |
|
| 52 if( error == WSAENOTSOCK ) |
|
| 53 return FALSE; |
|
| 54 else { |
|
| 55 purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_is_socket: getsockopt returned error: %d\n", error); |
|
| 56 return FALSE; |
|
| 57 } |
|
| 58 } |
|
| 59 return TRUE; |
|
| 60 } |
|
| 61 |
|
| 62 /* socket.h */ |
45 /* socket.h */ |
| 63 int wpurple_socket (int namespace, int style, int protocol) { |
|
| 64 int ret; |
|
| 65 |
|
| 66 ret = socket( namespace, style, protocol ); |
|
| 67 |
|
| 68 if (ret == (int)INVALID_SOCKET) { |
|
| 69 errno = WSAGetLastError(); |
|
| 70 return -1; |
|
| 71 } |
|
| 72 return ret; |
|
| 73 } |
|
| 74 |
|
| 75 int wpurple_connect(int socket, struct sockaddr *addr, u_long length) { |
|
| 76 int ret; |
|
| 77 |
|
| 78 ret = connect( socket, addr, length ); |
|
| 79 |
|
| 80 if( ret == SOCKET_ERROR ) { |
|
| 81 errno = WSAGetLastError(); |
|
| 82 if( errno == WSAEWOULDBLOCK ) |
|
| 83 errno = WSAEINPROGRESS; |
|
| 84 return -1; |
|
| 85 } |
|
| 86 return 0; |
|
| 87 } |
|
| 88 |
|
| 89 int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) { |
|
| 90 if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) { |
|
| 91 errno = WSAGetLastError(); |
|
| 92 return -1; |
|
| 93 } |
|
| 94 return 0; |
|
| 95 } |
|
| 96 |
|
| 97 int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) { |
|
| 98 if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) { |
|
| 99 errno = WSAGetLastError(); |
|
| 100 return -1; |
|
| 101 } |
|
| 102 return 0; |
|
| 103 } |
|
| 104 |
|
| 105 int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) { |
46 int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) { |
| 106 if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) { |
47 if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) { |
| 107 errno = WSAGetLastError(); |
48 errno = WSAGetLastError(); |
| 108 return -1; |
49 return -1; |
| 109 } |
50 } |
| 110 return 0; |
51 return 0; |
| 111 } |
|
| 112 |
|
| 113 int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length) { |
|
| 114 if(bind(socket, addr, length) == SOCKET_ERROR) { |
|
| 115 errno = WSAGetLastError(); |
|
| 116 return -1; |
|
| 117 } |
|
| 118 return 0; |
|
| 119 } |
|
| 120 |
|
| 121 int wpurple_listen(int socket, unsigned int n) { |
|
| 122 if(listen(socket, n) == SOCKET_ERROR) { |
|
| 123 errno = WSAGetLastError(); |
|
| 124 return -1; |
|
| 125 } |
|
| 126 return 0; |
|
| 127 } |
|
| 128 |
|
| 129 int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { |
|
| 130 int ret; |
|
| 131 if ((ret = sendto(socket, buf, len, flags, to, tolen) |
|
| 132 ) == SOCKET_ERROR) { |
|
| 133 errno = WSAGetLastError(); |
|
| 134 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS) |
|
| 135 errno = EAGAIN; |
|
| 136 return -1; |
|
| 137 } |
|
| 138 return ret; |
|
| 139 } |
52 } |
| 140 |
53 |
| 141 /* fcntl.h */ |
54 /* fcntl.h */ |
| 142 /* This is not a full implementation of fcntl. Update as needed.. */ |
55 /* This is not a full implementation of fcntl. Update as needed.. */ |
| 143 int wpurple_fcntl(int socket, int command, ...) { |
56 int wpurple_fcntl(int socket, int command, ...) { |
| 236 errno = EINVAL; |
149 errno = EINVAL; |
| 237 return -1; |
150 return -1; |
| 238 }/*end switch*/ |
151 }/*end switch*/ |
| 239 } |
152 } |
| 240 |
153 |
| 241 /* arpa/inet.h */ |
|
| 242 int wpurple_inet_aton(const char *name, struct in_addr *addr) { |
|
| 243 if((addr->s_addr = inet_addr(name)) == INADDR_NONE) |
|
| 244 return 0; |
|
| 245 else |
|
| 246 return 1; |
|
| 247 } |
|
| 248 |
|
| 249 /* Thanks to GNU wget for this inet_ntop() implementation */ |
|
| 250 const char * |
|
| 251 wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt) |
|
| 252 { |
|
| 253 /* struct sockaddr can't accomodate struct sockaddr_in6. */ |
|
| 254 union { |
|
| 255 struct sockaddr_in6 sin6; |
|
| 256 struct sockaddr_in sin; |
|
| 257 } sa; |
|
| 258 DWORD dstlen = cnt; |
|
| 259 size_t srcsize; |
|
| 260 |
|
| 261 ZeroMemory(&sa, sizeof(sa)); |
|
| 262 switch (af) |
|
| 263 { |
|
| 264 case AF_INET: |
|
| 265 sa.sin.sin_family = AF_INET; |
|
| 266 sa.sin.sin_addr = *(struct in_addr *) src; |
|
| 267 srcsize = sizeof (sa.sin); |
|
| 268 break; |
|
| 269 case AF_INET6: |
|
| 270 sa.sin6.sin6_family = AF_INET6; |
|
| 271 sa.sin6.sin6_addr = *(struct in6_addr *) src; |
|
| 272 srcsize = sizeof (sa.sin6); |
|
| 273 break; |
|
| 274 default: |
|
| 275 abort (); |
|
| 276 } |
|
| 277 |
|
| 278 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0) |
|
| 279 { |
|
| 280 errno = WSAGetLastError(); |
|
| 281 return NULL; |
|
| 282 } |
|
| 283 return (const char *) dst; |
|
| 284 } |
|
| 285 |
|
| 286 int |
|
| 287 wpurple_inet_pton(int af, const char *src, void *dst) |
|
| 288 { |
|
| 289 /* struct sockaddr can't accomodate struct sockaddr_in6. */ |
|
| 290 union { |
|
| 291 struct sockaddr_in6 sin6; |
|
| 292 struct sockaddr_in sin; |
|
| 293 } sa; |
|
| 294 int srcsize; |
|
| 295 |
|
| 296 switch(af) |
|
| 297 { |
|
| 298 case AF_INET: |
|
| 299 sa.sin.sin_family = AF_INET; |
|
| 300 srcsize = sizeof (sa.sin); |
|
| 301 break; |
|
| 302 case AF_INET6: |
|
| 303 sa.sin6.sin6_family = AF_INET6; |
|
| 304 srcsize = sizeof (sa.sin6); |
|
| 305 break; |
|
| 306 default: |
|
| 307 errno = WSAEPFNOSUPPORT; |
|
| 308 return -1; |
|
| 309 } |
|
| 310 |
|
| 311 if (WSAStringToAddress((LPTSTR)src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0) |
|
| 312 { |
|
| 313 errno = WSAGetLastError(); |
|
| 314 return -1; |
|
| 315 } |
|
| 316 |
|
| 317 switch(af) |
|
| 318 { |
|
| 319 case AF_INET: |
|
| 320 memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr)); |
|
| 321 break; |
|
| 322 case AF_INET6: |
|
| 323 memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr)); |
|
| 324 break; |
|
| 325 } |
|
| 326 |
|
| 327 return 1; |
|
| 328 } |
|
| 329 |
|
| 330 |
|
| 331 /* netdb.h */ |
154 /* netdb.h */ |
| 332 struct hostent* wpurple_gethostbyname(const char *name) { |
155 struct hostent* wpurple_gethostbyname(const char *name) { |
| 333 struct hostent *hp; |
156 struct hostent *hp; |
| 334 |
157 |
| 335 if((hp = gethostbyname(name)) == NULL) { |
158 if((hp = gethostbyname(name)) == NULL) { |
| 339 return hp; |
162 return hp; |
| 340 } |
163 } |
| 341 |
164 |
| 342 /* unistd.h */ |
165 /* unistd.h */ |
| 343 |
166 |
| 344 /* |
|
| 345 * We need to figure out whether fd is a file or socket handle. |
|
| 346 */ |
|
| 347 int wpurple_read(int fd, void *buf, unsigned int size) { |
|
| 348 int ret; |
|
| 349 |
|
| 350 if (fd < 0) { |
|
| 351 errno = EBADF; |
|
| 352 g_return_val_if_reached(-1); |
|
| 353 } |
|
| 354 |
|
| 355 if(wpurple_is_socket(fd)) { |
|
| 356 if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) { |
|
| 357 errno = WSAGetLastError(); |
|
| 358 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS) |
|
| 359 errno = EAGAIN; |
|
| 360 return -1; |
|
| 361 } |
|
| 362 else { |
|
| 363 /* success reading socket */ |
|
| 364 return ret; |
|
| 365 } |
|
| 366 } else { |
|
| 367 /* fd is not a socket handle.. pass it off to read */ |
|
| 368 return _read(fd, buf, size); |
|
| 369 } |
|
| 370 } |
|
| 371 |
|
| 372 int wpurple_send(int fd, const void *buf, unsigned int size, int flags) { |
|
| 373 int ret; |
|
| 374 |
|
| 375 ret = send(fd, buf, size, flags); |
|
| 376 |
|
| 377 if (ret == SOCKET_ERROR) { |
|
| 378 errno = WSAGetLastError(); |
|
| 379 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS) |
|
| 380 errno = EAGAIN; |
|
| 381 return -1; |
|
| 382 } |
|
| 383 return ret; |
|
| 384 } |
|
| 385 |
|
| 386 int wpurple_write(int fd, const void *buf, unsigned int size) { |
|
| 387 |
|
| 388 if (fd < 0) { |
|
| 389 errno = EBADF; |
|
| 390 g_return_val_if_reached(-1); |
|
| 391 } |
|
| 392 |
|
| 393 if(wpurple_is_socket(fd)) |
|
| 394 return wpurple_send(fd, buf, size, 0); |
|
| 395 else |
|
| 396 return _write(fd, buf, size); |
|
| 397 } |
|
| 398 |
|
| 399 int wpurple_recv(int fd, void *buf, size_t len, int flags) { |
|
| 400 int ret; |
|
| 401 |
|
| 402 if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) { |
|
| 403 errno = WSAGetLastError(); |
|
| 404 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS) |
|
| 405 errno = EAGAIN; |
|
| 406 return -1; |
|
| 407 } else { |
|
| 408 return ret; |
|
| 409 } |
|
| 410 } |
|
| 411 |
|
| 412 int wpurple_close(int fd) { |
|
| 413 int ret; |
|
| 414 |
|
| 415 if (fd < 0) { |
|
| 416 errno = EBADF; |
|
| 417 g_return_val_if_reached(-1); |
|
| 418 } |
|
| 419 |
|
| 420 if( wpurple_is_socket(fd) ) { |
|
| 421 if( (ret = closesocket(fd)) == SOCKET_ERROR ) { |
|
| 422 errno = WSAGetLastError(); |
|
| 423 return -1; |
|
| 424 } |
|
| 425 else |
|
| 426 return 0; |
|
| 427 } |
|
| 428 else |
|
| 429 return _close(fd); |
|
| 430 } |
|
| 431 |
|
| 432 int wpurple_gethostname(char *name, size_t size) { |
167 int wpurple_gethostname(char *name, size_t size) { |
| 433 if(gethostname(name, size) == SOCKET_ERROR) { |
168 if(gethostname(name, size) == SOCKET_ERROR) { |
| 434 errno = WSAGetLastError(); |
169 errno = WSAGetLastError(); |
| 435 return -1; |
170 return -1; |
| 436 } |
171 } |
| 437 return 0; |
172 return 0; |
| 438 } |
173 } |
| 439 |
|
| 440 /* sys/time.h */ |
|
| 441 |
|
| 442 int wpurple_gettimeofday(struct timeval *p, struct timezone *z) { |
|
| 443 int res = 0; |
|
| 444 struct _timeb timebuffer; |
|
| 445 |
|
| 446 if (z != 0) { |
|
| 447 _tzset(); |
|
| 448 z->tz_minuteswest = _timezone/60; |
|
| 449 z->tz_dsttime = _daylight; |
|
| 450 } |
|
| 451 |
|
| 452 if (p != 0) { |
|
| 453 _ftime(&timebuffer); |
|
| 454 p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */ |
|
| 455 p->tv_usec = timebuffer.millitm*1000; /* microseconds */ |
|
| 456 } |
|
| 457 |
|
| 458 return res; |
|
| 459 } |
|