/* env_standard.c */ /* Copyright 2009-2012 10gen Inc. * * Licensed 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. */ /* Vanilla networking designed to work on all systems. */ #include "env.h" #include #include #ifdef _WIN32 #ifdef _MSC_VER #include // send,recv,socklen_t etc #include // addrinfo #else #include #include typedef int socklen_t; #endif #else #include #include #include #include #include #include #include #include #endif #ifndef NI_MAXSERV # define NI_MAXSERV 32 #endif int mongo_env_close_socket( int socket ) { #ifdef _WIN32 return closesocket( socket ); #else return close( socket ); #endif } int mongo_env_write_socket( mongo *conn, const void *buf, int len ) { const char *cbuf = buf; #ifdef _WIN32 int flags = 0; #else #ifdef __APPLE__ int flags = 0; #else int flags = MSG_NOSIGNAL; #endif #endif while ( len ) { int sent = send( conn->sock, cbuf, len, flags ); if ( sent == -1 ) { if (errno == EPIPE) conn->connected = 0; conn->err = MONGO_IO_ERROR; return MONGO_ERROR; } cbuf += sent; len -= sent; } return MONGO_OK; } int mongo_env_read_socket( mongo *conn, void *buf, int len ) { char *cbuf = buf; while ( len ) { int sent = recv( conn->sock, cbuf, len, 0 ); if ( sent == 0 || sent == -1 ) { conn->err = MONGO_IO_ERROR; return MONGO_ERROR; } cbuf += sent; len -= sent; } return MONGO_OK; } /* This is a no-op in the generic implementation. */ int mongo_env_set_socket_op_timeout( mongo *conn, int millis ) { return MONGO_OK; } int mongo_env_socket_connect( mongo *conn, const char *host, int port ) { struct sockaddr_in sa; socklen_t addressSize; int flag = 1; if ( ( conn->sock = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { conn->sock = 0; conn->err = MONGO_CONN_NO_SOCKET; return MONGO_ERROR; } memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) ); sa.sin_family = AF_INET; sa.sin_port = htons( port ); sa.sin_addr.s_addr = inet_addr( host ); addressSize = sizeof( sa ); if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) { mongo_env_close_socket( conn->sock ); conn->connected = 0; conn->sock = 0; conn->err = MONGO_CONN_FAIL; return MONGO_ERROR; } setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) ); if( conn->op_timeout_ms > 0 ) mongo_env_set_socket_op_timeout( conn, conn->op_timeout_ms ); conn->connected = 1; return MONGO_OK; } MONGO_EXPORT int mongo_env_sock_init( void ) { #if defined(_WIN32) WSADATA wsaData; WORD wVers; #elif defined(SIGPIPE) struct sigaction act; #endif static int called_once; static int retval; if (called_once) return retval; called_once = 1; #if defined(_WIN32) wVers = MAKEWORD(1, 1); retval = (WSAStartup(wVers, &wsaData) == 0); #elif defined(MACINTOSH) GUSISetup(GUSIwithInternetSockets); retval = 1; #elif defined(SIGPIPE) retval = 1; if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) < 0) retval = 0; else if (act.sa_handler == SIG_DFL) { act.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) < 0) retval = 0; } #endif return retval; }