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 "SocketStream.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 #include <sys/un.h> 28 #else 29 #include <ws2tcpip.h> 30 #endif 31 32 SocketStream::SocketStream(size_t bufSize) : 33 IOStream(bufSize), 34 m_sock(-1), 35 m_bufsize(bufSize), 36 m_buf(NULL) 37 { 38 } 39 40 SocketStream::SocketStream(int sock, size_t bufSize) : 41 IOStream(bufSize), 42 m_sock(sock), 43 m_bufsize(bufSize), 44 m_buf(NULL) 45 { 46 } 47 48 SocketStream::~SocketStream() 49 { 50 if (m_sock >= 0) { 51 #ifdef _WIN32 52 closesocket(m_sock); 53 #else 54 ::close(m_sock); 55 #endif 56 } 57 if (m_buf != NULL) { 58 free(m_buf); 59 m_buf = NULL; 60 } 61 } 62 63 64 void *SocketStream::allocBuffer(size_t minSize) 65 { 66 size_t allocSize = (m_bufsize < minSize ? minSize : m_bufsize); 67 if (!m_buf) { 68 m_buf = (unsigned char *)malloc(allocSize); 69 } 70 else if (m_bufsize < allocSize) { 71 unsigned char *p = (unsigned char *)realloc(m_buf, allocSize); 72 if (p != NULL) { 73 m_buf = p; 74 m_bufsize = allocSize; 75 } else { 76 ERR("%s: realloc (%d) failed\n", __FUNCTION__, allocSize); 77 free(m_buf); 78 m_buf = NULL; 79 m_bufsize = 0; 80 } 81 } 82 83 return m_buf; 84 }; 85 86 int SocketStream::commitBuffer(size_t size) 87 { 88 return writeFully(m_buf, size); 89 } 90 91 int SocketStream::writeFully(const void* buffer, size_t size) 92 { 93 if (!valid()) return -1; 94 95 size_t res = size; 96 int retval = 0; 97 98 while (res > 0) { 99 ssize_t stat = ::send(m_sock, (const char *)buffer + (size - res), res, 0); 100 if (stat < 0) { 101 if (errno != EINTR) { 102 retval = stat; 103 ERR("%s: failed: %s\n", __FUNCTION__, strerror(errno)); 104 break; 105 } 106 } else { 107 res -= stat; 108 } 109 } 110 return retval; 111 } 112 113 const unsigned char *SocketStream::readFully(void *buf, size_t len) 114 { 115 const unsigned char* ret = NULL; 116 if (!valid()) return NULL; 117 if (!buf) { 118 return NULL; // do not allow NULL buf in that implementation 119 } 120 size_t res = len; 121 while (res > 0) { 122 ssize_t stat = ::recv(m_sock, (char *)(buf) + len - res, res, 0); 123 if (stat > 0) { 124 res -= stat; 125 continue; 126 } 127 if (stat == 0 || errno != EINTR) { // client shutdown or error 128 return NULL; 129 } 130 } 131 return (const unsigned char *)buf; 132 } 133 134 const unsigned char *SocketStream::read( void *buf, size_t *inout_len) 135 { 136 if (!valid()) return NULL; 137 if (!buf) { 138 return NULL; // do not allow NULL buf in that implementation 139 } 140 141 int n; 142 do { 143 n = recv(buf, *inout_len); 144 } while( n < 0 && errno == EINTR ); 145 146 if (n > 0) { 147 *inout_len = n; 148 return (const unsigned char *)buf; 149 } 150 151 return NULL; 152 } 153 154 int SocketStream::recv(void *buf, size_t len) 155 { 156 if (!valid()) return int(ERR_INVALID_SOCKET); 157 int res = 0; 158 while(true) { 159 res = ::recv(m_sock, (char *)buf, len, 0); 160 if (res < 0) { 161 if (errno == EINTR) { 162 continue; 163 } 164 } 165 break; 166 } 167 return res; 168 } 169