1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "TcpStream.h" 17 #include <cutils/sockets.h> 18 #include <errno.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <string.h> 23 24 #ifndef _WIN32 25 #include <netinet/in.h> 26 #include <netinet/tcp.h> 27 #else 28 #include <ws2tcpip.h> 29 #endif 30 31 #define LISTEN_BACKLOG 4 32 33 TcpStream::TcpStream(size_t bufSize) : 34 SocketStream(bufSize) 35 { 36 } 37 38 TcpStream::TcpStream(int sock, size_t bufSize) : 39 SocketStream(sock, bufSize) 40 { 41 // disable Nagle algorithm to improve bandwidth of small 42 // packets which are quite common in our implementation. 43 #ifdef _WIN32 44 DWORD flag; 45 #else 46 int flag; 47 #endif 48 flag = 1; 49 setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(flag) ); 50 } 51 52 int TcpStream::listen(char addrstr[MAX_ADDRSTR_LEN]) 53 { 54 m_sock = socket_loopback_server(0, SOCK_STREAM); 55 if (!valid()) 56 return int(ERR_INVALID_SOCKET); 57 58 /* get the actual port number assigned by the system */ 59 struct sockaddr_in addr; 60 socklen_t addrLen = sizeof(addr); 61 memset(&addr, 0, sizeof(addr)); 62 if (getsockname(m_sock, (struct sockaddr*)&addr, &addrLen) < 0) { 63 close(m_sock); 64 return int(ERR_INVALID_SOCKET); 65 } 66 snprintf(addrstr, MAX_ADDRSTR_LEN - 1, "%hu", ntohs(addr.sin_port)); 67 addrstr[MAX_ADDRSTR_LEN-1] = '\0'; 68 69 return 0; 70 } 71 72 SocketStream * TcpStream::accept() 73 { 74 int clientSock = -1; 75 76 while (true) { 77 struct sockaddr_in addr; 78 socklen_t len = sizeof(addr); 79 clientSock = ::accept(m_sock, (sockaddr *)&addr, &len); 80 81 if (clientSock < 0 && errno == EINTR) { 82 continue; 83 } 84 break; 85 } 86 87 TcpStream *clientStream = NULL; 88 89 if (clientSock >= 0) { 90 clientStream = new TcpStream(clientSock, m_bufsize); 91 } 92 return clientStream; 93 } 94 95 int TcpStream::connect(const char* addr) 96 { 97 int port = atoi(addr); 98 return connect("127.0.0.1",port); 99 } 100 101 int TcpStream::connect(const char* hostname, unsigned short port) 102 { 103 m_sock = socket_network_client(hostname, port, SOCK_STREAM); 104 if (!valid()) return -1; 105 return 0; 106 } 107