/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #if defined(WIN32) /* fix for an older version of winsock2.h */ #if !defined(SO_EXCLUSIVEADDRUSE) #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) #endif #endif #if defined(WIN32) static int is_init_socket = 0; axis2_bool_t axis2_init_socket( ); #endif AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_handler_open_socket( const axutil_env_t *env, char *server, int port) { axis2_socket_t sock = AXIS2_INVALID_SOCKET; struct sockaddr_in sock_addr; struct linger ll; int nodelay = 1; #if defined(WIN32) if (is_init_socket == 0) { axis2_init_socket(); is_init_socket = 1; } #endif AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); AXIS2_PARAM_CHECK(env->error, server, AXIS2_INVALID_SOCKET); #ifndef WIN32 if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) /*AF_INET is not defined in sys/socket.h but PF_INET */ { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #else if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) /* In Win 32 if the socket creation failed it return 0 not a negative value */ { char buf[AXUTIL_WIN32_ERROR_BUFSIZE]; /* Get the detailed error message */ axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #endif memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = inet_addr(server); /*arpa/inet.d */ if(sock_addr.sin_addr.s_addr == AXIS2_INADDR_NONE) /*netinet/in.h */ { /* * server may be a host name */ struct hostent *lphost = NULL; lphost = gethostbyname(server); if(lphost) { sock_addr.sin_addr.s_addr = ((struct in_addr *)lphost->h_addr)->s_addr; } else { AXIS2_CLOSE_SOCKET(sock); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_ADDRESS, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } } sock_addr.sin_port = htons((axis2_unsigned_short_t)port); /* Connect to server */ if(connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) { AXIS2_CLOSE_SOCKET(sock); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&nodelay, sizeof(nodelay)); ll.l_onoff = 1; ll.l_linger = 5; setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(struct linger)); return sock; } AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_handler_create_server_socket( const axutil_env_t *env, int port) { axis2_socket_t sock = AXIS2_INVALID_SOCKET; axis2_socket_t i = 0; struct sockaddr_in sock_addr; AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); #if defined(WIN32) if (is_init_socket == 0) { axis2_init_socket(); is_init_socket = 1; } #endif sock = socket(AF_INET, SOCK_STREAM, 0); #ifndef WIN32 if(sock < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #else if (sock == INVALID_SOCKET) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_INVALID_SOCKET; } #endif /* Address re-use */ i = 1; #if defined(WIN32) setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &i, sizeof(axis2_socket_t)); /*casted 4th param to char* */ #else setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(axis2_socket_t)); /*casted 4th param to char* */ #endif /* Exec behaviour */ AXIS2_CLOSE_SOCKET_ON_EXIT(sock); memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); sock_addr.sin_port = htons((axis2_unsigned_short_t)port); /* Bind the socket to our port number */ if(bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_BIND_FAILED, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } if(listen(sock, 50) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_LISTEN_FAILED, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } return sock; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_network_handler_close_socket( const axutil_env_t *env, axis2_socket_t socket) { int i = 0; char buf[32]; if(socket < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_SOCKET, AXIS2_FAILURE); return AXIS2_FAILURE; } shutdown(socket, AXIS2_SHUT_WR); axutil_network_handler_set_sock_option(env, socket, SO_RCVTIMEO, 1); i = recv(socket, buf, 32, 0); AXIS2_CLOSE_SOCKET(socket); return AXIS2_SUCCESS; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_network_handler_set_sock_option( const axutil_env_t *env, axis2_socket_t socket, int option, int value) { if(option == SO_RCVTIMEO || option == SO_SNDTIMEO) { #if defined(WIN32) DWORD tv = value; /* windows expects milliseconds in a DWORD */ #else struct timeval tv; /* we deal with milliseconds */ tv.tv_sec = value / 1000; tv.tv_usec = (value % 1000) * 1000; #endif setsockopt(socket, SOL_SOCKET, option, (char *)&tv, sizeof(tv)); return AXIS2_SUCCESS; } else if(option == SO_REUSEADDR) { if((setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(value))) < 0) { return AXIS2_FAILURE; } return AXIS2_SUCCESS; } return AXIS2_FAILURE; } AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_handler_svr_socket_accept( const axutil_env_t *env, axis2_socket_t svr_socket) { struct sockaddr cli_addr; struct linger ll; int nodelay = 1; axis2_socket_len_t cli_len = 0; axis2_socket_t cli_socket = AXIS2_INVALID_SOCKET; AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); cli_len = sizeof(cli_addr); cli_socket = accept(svr_socket, (struct sockaddr *)&cli_addr, &cli_len); #ifndef WIN32 if(cli_socket < 0) { AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[Axis2][network_handler] Socket accept \ failed"); } #else if (cli_socket == INVALID_SOCKET) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); } #endif setsockopt(svr_socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&nodelay, (int)sizeof(nodelay)); /* We are sure that the difference lies within the int range */ ll.l_onoff = 1; ll.l_linger = 5; setsockopt(cli_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, (int)sizeof(struct linger)); /* We are sure that the difference lies within the int range */ return cli_socket; } #if defined (WIN32) axis2_bool_t axis2_init_socket( ) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) return 0; /* WinSock 2.2 not found */ /* Confirm that the WinSock DLL supports 2.2. * Note that if the DLL supports versions greater * than 2.2 in addition to 2.2, it will still return * 2.2 in wVersion since that is the version we * requested. */ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { WSACleanup(); return 0; /* WinSock 2.2 not supported */ } return 1; } #endif AXIS2_EXTERN axis2_char_t *AXIS2_CALL axutil_network_handler_get_svr_ip( const axutil_env_t *env, axis2_socket_t socket) { struct sockaddr_in addr; axis2_socket_len_t len = sizeof(addr); char *ret = NULL; memset(&addr, 0, sizeof(addr)); if(getsockname(socket, (struct sockaddr *)&addr, &len) < 0) { return NULL; } ret = inet_ntoa(addr.sin_addr); return ret; } AXIS2_EXTERN axis2_char_t *AXIS2_CALL axutil_network_handler_get_peer_ip( const axutil_env_t *env, axis2_socket_t socket) { struct sockaddr_in addr; axis2_socket_len_t len = sizeof(addr); char *ret = NULL; memset(&addr, 0, sizeof(addr)); if(getpeername(socket, (struct sockaddr *)&addr, &len) < 0) { return NULL; } ret = inet_ntoa(addr.sin_addr); return ret; } AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_handler_create_dgram_svr_socket( const axutil_env_t *env, int port) { axis2_socket_t sock = AXIS2_INVALID_SOCKET; struct sockaddr_in sock_addr; AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); #if defined(WIN32) if (is_init_socket == 0) { axis2_init_socket(); is_init_socket = 1; } #endif sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); #ifndef WIN32 if(sock < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #else if (sock == INVALID_SOCKET) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_INVALID_SOCKET; } #endif /* Exec behaviour */ AXIS2_CLOSE_SOCKET_ON_EXIT(sock); memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); sock_addr.sin_port = htons((axis2_unsigned_short_t)port); /* Bind the socket to our port number */ if(bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_BIND_FAILED, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } return sock; } AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_handler_open_dgram_socket( const axutil_env_t *env) { axis2_socket_t sock = AXIS2_INVALID_SOCKET; #if defined(WIN32) if (is_init_socket == 0) { axis2_init_socket(); is_init_socket = 1; } #endif #ifndef WIN32 if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) /*AF_INET is not defined in sys/socket.h but PF_INET */ { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #else if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) /* In Win 32 if the socket creation failed it return 0 not a negative value */ { char buf[AXUTIL_WIN32_ERROR_BUFSIZE]; /* Get the detailed error message */ axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #endif return sock; } /* * This function blocks until data is available to read from the socket * and read all the data in the socket. If the buffer size specified is * lesser than the actual data a failure will be returned. */ AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_network_handler_read_dgram( const axutil_env_t *env, axis2_socket_t sock, axis2_char_t *buffer, int *buf_len, axis2_char_t **addr, int *port) { struct sockaddr_in sender_address; int received = 0; socklen_t sender_address_size; sender_address_size = sizeof(sender_address); received = recvfrom(sock, buffer, *buf_len, 0, (struct sockaddr *)&sender_address, &sender_address_size); #ifdef WIN32 if (SOCKET_ERROR == received) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_FAILURE; } #else if(received < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #endif if(port && addr) { *port = ntohs(sender_address.sin_port); *addr = inet_ntoa(sender_address.sin_addr); } *buf_len = received; return AXIS2_SUCCESS; } /* * Sends a datagram to the specified location. */ AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_network_handler_send_dgram( const axutil_env_t *env, axis2_socket_t sock, axis2_char_t *buff, int *buf_len, axis2_char_t *addr, int dest_port, int *source_port) { struct sockaddr_in recv_addr, source_addr; int send_bytes = 0; unsigned int recv_addr_size = 0; socklen_t source_addr_size = sizeof(source_addr); recv_addr_size = sizeof(recv_addr); memset(&recv_addr, 0, sizeof(recv_addr)); memset(&recv_addr, 0, sizeof(source_addr)); recv_addr.sin_addr.s_addr = inet_addr(addr); if(recv_addr.sin_addr.s_addr == AXIS2_INADDR_NONE) /*netinet/in.h */ { /* * server may be a host name */ struct hostent *lphost = NULL; lphost = gethostbyname(addr); if(lphost) { recv_addr.sin_addr.s_addr = ((struct in_addr *)lphost->h_addr)->s_addr; } else { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_INVALID_ADDRESS, AXIS2_FAILURE); return AXIS2_FAILURE; } } recv_addr.sin_family = AF_INET; recv_addr.sin_port = htons((axis2_unsigned_short_t)dest_port); send_bytes = sendto(sock, buff, *buf_len, 0, (struct sockaddr *)&recv_addr, recv_addr_size); getsockname(sock, (struct sockaddr *)&source_addr, &source_addr_size); #ifdef WIN32 if (send_bytes == SOCKET_ERROR) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_FAILURE; } #else if(send_bytes < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_FAILURE; } #endif if(source_port) { *source_port = ntohs(source_addr.sin_port); } *buf_len = send_bytes; return AXIS2_SUCCESS; } AXIS2_EXTERN axis2_status_t AXIS2_CALL axutil_network_handler_bind_socket( const axutil_env_t *env, axis2_socket_t sock, int port) { struct sockaddr_in source_addr; memset(&source_addr, 0, sizeof(source_addr)); source_addr.sin_family = AF_INET; source_addr.sin_addr.s_addr = htonl(INADDR_ANY); source_addr.sin_port = htons((axis2_unsigned_short_t)port); #ifdef WIN32 if (bind(sock, (struct sockaddr *)&source_addr, sizeof(source_addr)) == SOCKET_ERROR) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_FAILURE; } #else if(bind(sock, (struct sockaddr *)&source_addr, sizeof(source_addr)) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } #endif return AXIS2_SUCCESS; } AXIS2_EXTERN axis2_socket_t AXIS2_CALL axutil_network_hadler_create_multicast_svr_socket( const axutil_env_t *env, int port, axis2_char_t *mul_addr) { axis2_socket_t sock = AXIS2_INVALID_SOCKET; struct sockaddr_in sock_addr; struct ip_mreq mc_req; AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); #if defined(WIN32) if (is_init_socket == 0) { axis2_init_socket(); is_init_socket = 1; } #endif sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); #ifndef WIN32 if(sock < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_FAILURE; } #else if (sock == INVALID_SOCKET) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_FAILURE; } #endif /* Exec behaviour */ AXIS2_CLOSE_SOCKET_ON_EXIT(sock); memset(&sock_addr, 0, sizeof(sock_addr)); sock_addr.sin_family = AF_INET; sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); sock_addr.sin_port = htons((axis2_unsigned_short_t)port); /* Bind the socket to our port number */ if(bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_BIND_FAILED, AXIS2_FAILURE); return AXIS2_INVALID_SOCKET; } /* Send an IGMP request to join the multicast group */ mc_req.imr_multiaddr.s_addr = inet_addr(mul_addr); mc_req.imr_interface.s_addr = htonl(INADDR_ANY); #ifdef WIN32 if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_req, sizeof(mc_req))) == SOCKET_ERROR) { axis2_char_t buf[AXUTIL_WIN32_ERROR_BUFSIZE]; axutil_win32_get_last_wsa_error(buf, AXUTIL_WIN32_ERROR_BUFSIZE); AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, buf); return AXIS2_FAILURE; } #else if((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mc_req, sizeof(mc_req))) < 0) { AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); return AXIS2_FAILURE; } #endif return sock; }