X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fwin32%2Fsilcwin32net.c;h=818945e0c0ec769a0cd9e6bf4f9b4d3c9d3c5ec9;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=d3ff04748ed6ca0767e512cac044788c5a29ea35;hpb=2ed9dcbb8fb101fca8b02901b97273adb16fa8e1;p=silc.git diff --git a/lib/silcutil/win32/silcwin32net.c b/lib/silcutil/win32/silcwin32net.c index d3ff0474..818945e0 100644 --- a/lib/silcutil/win32/silcwin32net.c +++ b/lib/silcutil/win32/silcwin32net.c @@ -4,12 +4,11 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2001 Pekka Riikonen + Copyright (C) 1997 - 2005 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,7 +18,9 @@ */ /* $Id$ */ -#include "silcincludes.h" +/* XXX IPv6 support missing */ + +#include "silc.h" #include "silcnet.h" /* This function creates server or daemon or listener or what ever. This @@ -28,7 +29,7 @@ If argument `ip_addr' is NULL `any' address will be used. Returns the created socket or -1 on error. */ -int silc_net_create_server(int port, char *ip_addr) +int silc_net_create_server(int port, const char *ip_addr) { SOCKET sock; int rval; @@ -99,7 +100,8 @@ void silc_net_close_server(int sock) socket or -1 on error. This blocks the process while trying to create the connection. */ -int silc_net_create_connection(int port, char *host) +int silc_net_create_connection(const char *local_ip, int port, + const char *host) { SOCKET sock; int rval, err; @@ -111,7 +113,8 @@ int silc_net_create_connection(int port, char *host) /* Do host lookup */ dest = gethostbyname(host); if (!dest) { - SILC_LOG_ERROR(("Network (%s) unreachable", host)); + SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the " + "IP address", host)); return -1; } @@ -139,7 +142,9 @@ int silc_net_create_connection(int port, char *host) } /* Set appropriate options */ +#if defined(TCP_NODELAY) silc_net_set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); +#endif silc_net_set_socket_opt(sock, SOL_SOCKET, SO_KEEPALIVE, 1); SILC_LOG_DEBUG(("Connection created")); @@ -152,14 +157,60 @@ int silc_net_create_connection(int port, char *host) connection returns directly. To get the result of the connect() one must select() the socket and read the result after it's ready. */ -/* XXX Is the socket on WIN32 always non-blocking? */ - -int silc_net_create_connection_async(int port, char *host) +int silc_net_create_connection_async(const char *local_ip, int port, + const char *host) { + SOCKET sock; + int rval, err; + struct hostent *dest; + struct sockaddr_in desthost; + SILC_LOG_DEBUG(("Creating connection (async) to host %s port %d", host, port)); - return silc_net_create_connection(port, host); + /* Do host lookup */ + dest = gethostbyname(host); + if (!dest) { + SILC_LOG_ERROR(("Network (%s) unreachable: could not resolve the " + "IP address", host)); + return -1; + } + + /* Set socket information */ + memset(&desthost, 0, sizeof(desthost)); + desthost.sin_port = htons(port); + desthost.sin_family = AF_INET; + memcpy(&desthost.sin_addr, dest->h_addr_list[0], sizeof(desthost.sin_addr)); + + /* Create the connection socket */ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == INVALID_SOCKET) { + SILC_LOG_ERROR(("Cannot create socket")); + return -1; + } + + /* Connect to the host */ + rval = connect(sock, (struct sockaddr *)&desthost, sizeof(desthost)); + err = WSAGetLastError(); + if (rval == SOCKET_ERROR && err != WSAEWOULDBLOCK) { + SILC_LOG_ERROR(("Cannot connect to remote host")); + shutdown(sock, 2); + closesocket(sock); + return -1; + } + + /* Set socket to nonblocking mode */ + silc_net_set_socket_nonblock(sock); + + /* Set appropriate options */ +#if defined(TCP_NODELAY) + silc_net_set_socket_opt(sock, IPPROTO_TCP, TCP_NODELAY, 1); +#endif + silc_net_set_socket_opt(sock, SOL_SOCKET, SO_KEEPALIVE, 1); + + SILC_LOG_DEBUG(("Connection created")); + + return sock; } /* Closes the connection by closing the socket connection. */ @@ -172,8 +223,7 @@ void silc_net_close_connection(int sock) /* Converts the IP number string from numbers-and-dots notation to binary form. */ -bool silc_net_addr2bin(const char *addr, unsigned char *bin, - uint32 bin_len) +SilcBool silc_net_addr2bin(const char *addr, void *bin, SilcUInt32 bin_len) { unsigned long ret; @@ -182,8 +232,7 @@ bool silc_net_addr2bin(const char *addr, unsigned char *bin, if (bin_len < 4) return FALSE; - SILC_PUT32_LSB(ret, bin); - + memcpy(bin, (unsigned char *)&ret, 4); return ret != INADDR_NONE; } @@ -191,5 +240,35 @@ bool silc_net_addr2bin(const char *addr, unsigned char *bin, int silc_net_set_socket_nonblock(int sock) { - return 0; + unsigned long on = 1; + return ioctlsocket(sock, FIONBIO, &on); +} + +/* Init Winsock2. */ + +SilcBool silc_net_win32_init(void) +{ + int ret, sopt = SO_SYNCHRONOUS_NONALERT; + WSADATA wdata; + WORD ver = MAKEWORD(1, 1); + + ret = WSAStartup(ver, &wdata); + if (ret) + return FALSE; + + /* Allow using the SOCKET's as file descriptors so that we can poll + them with SILC Scheduler. */ + ret = setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&sopt, + sizeof(sopt)); + if (ret) + return FALSE; + + return TRUE; +} + +/* Uninit Winsock2 */ + +void silc_net_win32_uninit(void) +{ + WSACleanup(); }