static GPResult gpiStartConnect( GPConnection * connection, GPIOperation * operation ) { struct sockaddr_in address; int rcode; //int len; GPIConnection * iconnection = (GPIConnection*)*connection; struct hostent * host; GSUdpErrorCode anError; strncpy(iconnection->mHeader, GPI_UDP_HEADER, GS_UDP_MSG_HEADER_LEN); if (!gsUdpEngineIsInitialized()) { unsigned short peerPort = GPI_PEER_PORT; gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Notice, "Initializing UDP Layer\n"); anError = gsUdpEngineInitialize(peerPort, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (anError != GS_UDP_NO_ERROR) { while (anError != GS_UDP_NO_ERROR && peerPort < GPI_PEER_PORT + 100) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Comment, "Port %d failed, trying next port\n", peerPort); anError = gsUdpEngineInitialize(++peerPort, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } if (anError != GS_UDP_NO_ERROR) { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_HotError, "Tryed all 100 ports after default port, giving up.\n"); CallbackFatalError(connection, GP_NETWORK_ERROR, GP_UDP_LAYER, "There was error starting the UDP layer."); } } if (!iconnection->firewall) { iconnection->peerPort = peerPort; } } else { gsDebugFormat(GSIDebugCat_GP, GSIDebugType_Network, GSIDebugLevel_Notice, "UDP Layer already initialized, using existing port.\n"); iconnection->peerPort = gsUdpEngineGetLocalPort(); } anError = gsUdpEngineAddMsgHandler(iconnection->mHeader, iconnection->mHeader, NULL, gpiPeerAcceptedCallback, gpiPeerLeftCallback, gpiPeerPingReplyCallback, gpiPeerMessageCallback, connection); if (anError != GS_UDP_NO_ERROR) { CallbackFatalError(connection, GP_NETWORK_ERROR, GP_UDP_LAYER, "There was an error starting the UDP Layer."); } if(iconnection->firewall) { /* // Create the peer listening socket. //////////////////////////////////// iconnection->peerSocket = socket(AF_INET, SOCK_STREAM, 0); if(iconnection->peerSocket == INVALID_SOCKET) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error creating a socket."); // Make it non-blocking. //////////////////////// rcode = SetSockBlocking(iconnection->peerSocket,0); if (rcode == 0) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error making a socket non-blocking."); // Bind the socket. /////////////////// memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; rcode = bind(iconnection->peerSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); if(gsiSocketIsError(rcode)) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error binding a socket."); // Start listening on the socket. ///////////////////////////////// rcode = listen(iconnection->peerSocket, SOMAXCONN); if(gsiSocketIsError(rcode)) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error listening on a socket."); // Get the socket's port. ///////////////////////// len = sizeof(struct sockaddr_in); rcode = getsockname(iconnection->peerSocket, (struct sockaddr *)&address, &len); if (gsiSocketIsError(rcode)) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error getting a socket's addres."); iconnection->peerPort = address.sin_port; */ iconnection->peerPort = 0; } /* else { // Deprecated TCP code; Replaced by UDP Layer // No local port. ///////////////// //iconnection->peerSocket = INVALID_SOCKET; // Set to nothing because NN will determine this ////////////////////////// //iconnection->peerPort = 0; } */ // Create the cm socket. //////////////////////// iconnection->cmSocket = socket(AF_INET, SOCK_STREAM, 0); if(iconnection->cmSocket == INVALID_SOCKET) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error creating a socket."); // Make it non-blocking. //////////////////////// rcode = SetSockBlocking(iconnection->cmSocket,0); if(rcode == 0) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error making a socket non-blocking."); /* // Bind the socket. /////////////////// memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; rcode = bind(iconnection->cmSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); if (gsiSocketIsError(rcode)) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error binding a socket."); */ memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; // Get the server host. /////////////////////// if (inet_addr(GPConnectionManagerHostname) == INADDR_NONE) { host = gethostbyname(GPConnectionManagerHostname); if(host == NULL) CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "Could not resolve connection mananger host name."); address.sin_addr.s_addr = *(unsigned int *)host->h_addr_list[0]; //printf("Resolved Hostname and copied address: %s\n", inet_ntoa(address.sin_addr)); } else { address.sin_addr.s_addr = inet_addr(GPConnectionManagerHostname); //printf("Using hardcoded address: %s", GPConnectionManagerHostname); } // Connect the socket. ////////////////////// assert(address.sin_addr.s_addr != 0); address.sin_port = htons(GPI_CONNECTION_MANAGER_PORT); rcode = connect(iconnection->cmSocket, (struct sockaddr *)&address, sizeof(struct sockaddr_in)); if (gsiSocketIsError(rcode)) { int error = GOAGetLastError(iconnection->cmSocket); if((error != WSAEWOULDBLOCK) && (error != WSAEINPROGRESS) && (error != WSAETIMEDOUT)) { CallbackFatalError(connection, GP_NETWORK_ERROR, GP_NETWORK, "There was an error connecting a socket."); } } // We're waiting for the connect to complete. ///////////////////////////////////////////// operation->state = GPI_CONNECTING; iconnection->connectState = GPI_CONNECTING; return GP_NO_ERROR; }
/*************** ** CONNECTING ** ***************/ void ghiDoConnecting ( GHIConnection * connection ) { int rcode; SOCKADDR_IN address; int writeFlag; int exceptFlag; gsDebugFormat(GSIDebugCat_HTTP, GSIDebugType_State, GSIDebugLevel_Comment, "Connecting\n"); // If we don't have a socket yet, set it up. //////////////////////////////////////////// if(connection->socket == INVALID_SOCKET) { // Create the socket. ///////////////////// connection->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(connection->socket == INVALID_SOCKET) { connection->completed = GHTTPTrue; connection->result = GHTTPSocketFailed; connection->socketError = GOAGetLastError(connection->socket); return; } // Set the socket to non-blocking. ////////////////////////////////// if(!SetSockBlocking(connection->socket, 0)) { connection->completed = GHTTPTrue; connection->result = GHTTPSocketFailed; connection->socketError = GOAGetLastError(connection->socket); return; } // If throttling, use a small receive buffer. ///////////////////////////////////////////// if(connection->throttle) SetReceiveBufferSize(connection->socket, ghiThrottleBufferSize); // Setup the server address. //////////////////////////// memset(&address, 0, sizeof(SOCKADDR_IN)); address.sin_family = AF_INET; if (connection->proxyOverrideServer) address.sin_port = htons(connection->proxyOverridePort); else if(ghiProxyAddress) address.sin_port = htons(ghiProxyPort); else address.sin_port = htons(connection->serverPort); address.sin_addr.s_addr = connection->serverIP; // Start the connect. ///////////////////// //rcode = connect(connection->socket, (SOCKADDR *)&address, sizeof(SOCKADDR_IN)); rcode = connect(connection->socket, (SOCKADDR *)&address, sizeof(address)); if(gsiSocketIsError(rcode)) { int socketError = GOAGetLastError(connection->socket); if((socketError != WSAEWOULDBLOCK) && (socketError != WSAEINPROGRESS) && (socketError != WSAETIMEDOUT)) { connection->completed = GHTTPTrue; connection->result = GHTTPConnectFailed; connection->socketError = socketError; return; } } } // Check if the connect has completed. ////////////////////////////////////// rcode = GSISocketSelect(connection->socket, NULL, &writeFlag, &exceptFlag); if((gsiSocketIsError(rcode)) || ((rcode == 1) && exceptFlag)) { connection->completed = GHTTPTrue; connection->result = GHTTPConnectFailed; if(gsiSocketIsError(rcode)) connection->socketError = GOAGetLastError(connection->socket); else connection->socketError = 0; return; } // Check if we're connected. //////////////////////////// if((rcode == 1) && writeFlag) { // Progress. //////////// if (connection->encryptor.mEngine == GHTTPEncryptionEngine_None) connection->state = GHTTPSendingRequest; else connection->state = GHTTPSecuringSession; ghiCallProgressCallback(connection, NULL, 0); } }
// Try to connect to a remote sever using SOCK_STREAM // 1. Input: // <1> host : server host name or ip address // <2> port : server port // <3> timeout : in ms // - if < 0 block forever // - if = 0 non-block // - if > 0 timeout // <4> retry : currently doesn't support // 2. Output // <2> if success return sock_fd, else return -1 int ConnectTo(const char* host, const char* port, int timeout, int retry) { if (!host || !port) { app_error("server address or port cannot be empty!.\n"); return -1; } // given server address and port number, return the basic info about the // server struct addrinfo hints, *server_info = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; int ret; if ((ret = getaddrinfo(host, port, &hints, &server_info)) != 0) { ai_error(ret); return -1; } // Timeout Settings struct timeval tv, *tv_ptr; if (timeout < 0) { tv_ptr = NULL; } else { tv.tv_sec = timeout / 1000; tv.tv_usec = timeout % 1000; tv_ptr = &tv; } // Loop through all the results and connect to the first we can fd_set write_fds; int sock_fd; struct addrinfo* p; for (p = server_info; p != NULL; p = p->ai_next) { if ((sock_fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { perror("client: socket"); continue; } if (SetSockNonBlocking(sock_fd) < 0) { close(sock_fd); unix_error("ConnectTo: SetSockNonBlocking:"); } if (connect(sock_fd, p->ai_addr, p->ai_addrlen) < 0) { if (errno == EINPROGRESS) { FD_ZERO(&write_fds); FD_SET(sock_fd, &write_fds); switch (select(sock_fd + 1, NULL, &write_fds, NULL, tv_ptr)) { case -1: perror("ConnectTo: select:"); close(sock_fd); continue; case 0: DebugStr("ConnectTo: select: timeout\n"); close(sock_fd); continue; } int error; socklen_t len = sizeof(error); if (getsockopt(sock_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { perror("ConnectTo: getsockopt"); close(sock_fd); continue; } if (error) { DebugStr("ConnectTo: %s\n", strerror(error)); close(sock_fd); continue; } } else { DebugStr("ConnectTo: connect:"); close(sock_fd); continue; } } break; } if (!p) { DebugStr("failed to connect to (%s, %s)\n", host, port); if (server_info) { freeaddrinfo(server_info); } return -1; } if (SetSockBlocking(sock_fd) < 0) { close(sock_fd); unix_error("ConnectTo: SetSockBlocking"); } { const int MAXSIZE = 100; char *str = Malloc(MAXSIZE); inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), str, MAXSIZE); DebugStr("connected to %s\n", str); freeaddrinfo(server_info); Free(str); } return sock_fd; }