1/****************************************************************************** 2 * 3 * Copyright (C) 2009-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19#define LOG_TAG "bt_btif_sock" 20 21#include "btif_sock_util.h" 22 23#include <arpa/inet.h> 24#include <errno.h> 25#include <netinet/in.h> 26#include <netinet/tcp.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30#include <sys/ioctl.h> 31#include <sys/socket.h> 32#include <sys/types.h> 33#include <sys/un.h> 34#include <unistd.h> 35 36#include <hardware/bluetooth.h> 37#include <hardware/bt_sock.h> 38 39#include "bt_common.h" 40#include "bt_target.h" 41#include "bta_api.h" 42#include "bta_jv_api.h" 43#include "bta_jv_co.h" 44#include "btif_common.h" 45#include "btif_sock_sdp.h" 46#include "btif_sock_thread.h" 47#include "btif_util.h" 48#include "btm_api.h" 49#include "btm_int.h" 50#include "btu.h" 51#include "hcimsgs.h" 52#include "osi/include/log.h" 53#include "port_api.h" 54#include "sdp_api.h" 55 56#define asrt(s) \ 57 do { \ 58 if (!(s)) \ 59 BTIF_TRACE_ERROR("## %s assert %s failed at line:%d ##", __func__, #s, \ 60 __LINE__) \ 61 } while (0) 62 63int sock_send_all(int sock_fd, const uint8_t* buf, int len) { 64 int s = len; 65 66 while (s) { 67 ssize_t ret; 68 OSI_NO_INTR(ret = send(sock_fd, buf, s, 0)); 69 if (ret <= 0) { 70 BTIF_TRACE_ERROR("sock fd:%d send errno:%d, ret:%d", sock_fd, errno, ret); 71 return -1; 72 } 73 buf += ret; 74 s -= ret; 75 } 76 return len; 77} 78int sock_recv_all(int sock_fd, uint8_t* buf, int len) { 79 int r = len; 80 81 while (r) { 82 ssize_t ret; 83 OSI_NO_INTR(ret = recv(sock_fd, buf, r, MSG_WAITALL)); 84 if (ret <= 0) { 85 BTIF_TRACE_ERROR("sock fd:%d recv errno:%d, ret:%d", sock_fd, errno, ret); 86 return -1; 87 } 88 buf += ret; 89 r -= ret; 90 } 91 return len; 92} 93 94int sock_send_fd(int sock_fd, const uint8_t* buf, int len, int send_fd) { 95 struct msghdr msg; 96 unsigned char* buffer = (unsigned char*)buf; 97 memset(&msg, 0, sizeof(msg)); 98 99 struct cmsghdr* cmsg; 100 char msgbuf[CMSG_SPACE(1)]; 101 asrt(send_fd != -1); 102 if (sock_fd == -1 || send_fd == -1) return -1; 103 // Add any pending outbound file descriptors to the message 104 // See "man cmsg" really 105 msg.msg_control = msgbuf; 106 msg.msg_controllen = sizeof msgbuf; 107 cmsg = CMSG_FIRSTHDR(&msg); 108 cmsg->cmsg_level = SOL_SOCKET; 109 cmsg->cmsg_type = SCM_RIGHTS; 110 cmsg->cmsg_len = CMSG_LEN(sizeof send_fd); 111 memcpy(CMSG_DATA(cmsg), &send_fd, sizeof send_fd); 112 113 // We only write our msg_control during the first write 114 int ret_len = len; 115 while (len > 0) { 116 struct iovec iv; 117 memset(&iv, 0, sizeof(iv)); 118 119 iv.iov_base = buffer; 120 iv.iov_len = len; 121 122 msg.msg_iov = &iv; 123 msg.msg_iovlen = 1; 124 125 ssize_t ret; 126 OSI_NO_INTR(ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL)); 127 if (ret < 0) { 128 BTIF_TRACE_ERROR("fd:%d, send_fd:%d, sendmsg ret:%d, errno:%d, %s", 129 sock_fd, send_fd, (int)ret, errno, strerror(errno)); 130 ret_len = -1; 131 break; 132 } 133 134 buffer += ret; 135 len -= ret; 136 137 // Wipes out any msg_control too 138 memset(&msg, 0, sizeof(msg)); 139 } 140 BTIF_TRACE_DEBUG("close fd:%d after sent", send_fd); 141 // TODO: This seems wrong - if the FD is not opened in JAVA before this is 142 // called 143 // we get a "socket closed" exception in java, when reading from the 144 // socket... 145 close(send_fd); 146 return ret_len; 147} 148 149static const char* hex_table = "0123456789abcdef"; 150static inline void byte2hex(const char* data, char** str) { 151 **str = hex_table[(*data >> 4) & 0xf]; 152 ++*str; 153 **str = hex_table[*data & 0xf]; 154 ++*str; 155} 156static inline void byte2char(const char* data, char** str) { 157 **str = *data < ' ' ? '.' : *data > '~' ? '.' : *data; 158 ++(*str); 159} 160static inline void word2hex(const char* data, char** hex) { 161 byte2hex(&data[1], hex); 162 byte2hex(&data[0], hex); 163} 164void dump_bin(const char* title, const char* data, int size) { 165 char line_buff[256]; 166 char* line; 167 int i, j, addr; 168 const int width = 16; 169 LOG_DEBUG(LOG_TAG, "%s, size:%d, dump started {", title, size); 170 if (size <= 0) return; 171 // write offset 172 line = line_buff; 173 *line++ = ' '; 174 *line++ = ' '; 175 *line++ = ' '; 176 *line++ = ' '; 177 *line++ = ' '; 178 *line++ = ' '; 179 for (j = 0; j < width; j++) { 180 byte2hex((const char*)&j, &line); 181 *line++ = ' '; 182 } 183 *line = 0; 184 LOG_DEBUG(LOG_TAG, "%s", line_buff); 185 186 for (i = 0; i < size / width; i++) { 187 line = line_buff; 188 // write address: 189 addr = i * width; 190 word2hex((const char*)&addr, &line); 191 *line++ = ':'; 192 *line++ = ' '; 193 // write hex of data 194 for (j = 0; j < width; j++) { 195 byte2hex(&data[j], &line); 196 *line++ = ' '; 197 } 198 // write char of data 199 for (j = 0; j < width; j++) byte2char(data++, &line); 200 // wirte the end of line 201 *line = 0; 202 // output the line 203 LOG_DEBUG(LOG_TAG, "%s", line_buff); 204 } 205 // last line of left over if any 206 int leftover = size % width; 207 if (leftover > 0) { 208 line = line_buff; 209 // write address: 210 addr = i * width; 211 word2hex((const char*)&addr, &line); 212 *line++ = ':'; 213 *line++ = ' '; 214 // write hex of data 215 for (j = 0; j < leftover; j++) { 216 byte2hex(&data[j], &line); 217 *line++ = ' '; 218 } 219 // write hex padding 220 for (; j < width; j++) { 221 *line++ = ' '; 222 *line++ = ' '; 223 *line++ = ' '; 224 } 225 // write char of data 226 for (j = 0; j < leftover; j++) byte2char(data++, &line); 227 // write the end of line 228 *line = 0; 229 // output the line 230 LOG_DEBUG(LOG_TAG, "%s", line_buff); 231 } 232 LOG_DEBUG(LOG_TAG, "%s, size:%d, dump ended }", title, size); 233} 234