2 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file SocketStream.cpp
18 * @author Zofia Abramowska (z.abramowska@samsung.com)
20 * @brief Implementation of socket stream class
24 #include <sys/socket.h>
25 #include <sys/select.h>
29 #include <dpl/log/log.h>
30 #include "SocketStream.h"
32 #define READ_TIEMOUT_SEC 1
33 #define READ_TIMEUOT_NSEC 0
34 #define WRITE_TIMEOUT_SEC 0
35 #define WRITE_TIMEOUT_NSEC 100000000
36 #define MAX_BUFFER 10240
38 void SocketStream::throwWithErrnoMessage(std::string function_name){
40 char errbuf[512] = {0,};
42 errstr = strerror_r(errno, errbuf, sizeof(errbuf));
44 strerror_r(errno, errbuf, sizeof(errbuf));
47 LogError(function_name << " : " << errstr);
48 ThrowMsg(Exception::SocketStreamException, function_name << " : " << errstr);
51 void SocketStream::Read(size_t num, void * bytes){
54 LogError("Null pointer to buffer");
55 ThrowMsg(Exception::SocketStreamException, "Null pointer to buffer");
60 if(m_bytesRead > MAX_BUFFER){
61 LogError("Too big buffer requested!");
62 ThrowMsg(Exception::SocketStreamException, "Too big buffer requested!");
65 char part_buffer[MAX_BUFFER];
66 std::string whole_buffer;
70 ssize_t bytes_read = 0, bytes_to_read = (ssize_t) num;
78 FD_SET(m_socketFd, &allset);
83 char errbuf[512] = {0,};
85 while(bytes_to_read != 0){
86 timeout.tv_sec = READ_TIEMOUT_SEC;
87 timeout.tv_nsec = READ_TIMEUOT_NSEC;
90 if(-1 == (returned_value = pselect(max_fd, &rset, NULL, NULL, &timeout, NULL))){
91 if(errno == EINTR) continue;
92 throwWithErrnoMessage("pselect()");
94 if(0 == returned_value){
95 //This means pselect got timedout
96 //This is not a proper behavior in reading data from UDS
97 //And could mean we got corrupted connection
98 LogError("Couldn't read whole data. continue..");
101 if(FD_ISSET(m_socketFd, &rset)){
102 bytes_read = read(m_socketFd, part_buffer, num);
104 if(errno == ECONNRESET || errno == ENOTCONN || errno == ETIMEDOUT){
106 errstr = strerror_r(errno, errbuf, sizeof(errbuf));
108 strerror_r(errno, errbuf, sizeof(errbuf));
111 ThrowMsg(Exception::SocketStreamException,
112 "Connection closed : " << errstr << ". Couldn't read whole data");
113 }else if (errno != EAGAIN && errno != EWOULDBLOCK){
114 throwWithErrnoMessage("read()");
118 whole_buffer.append(part_buffer, bytes_read);
119 bytes_to_read-=bytes_read;
125 memcpy(bytes, whole_buffer.c_str(), num);
128 void SocketStream::Write(size_t num, const void * bytes){
131 LogError("Null pointer to buffer");
132 ThrowMsg(Exception::SocketStreamException, "Null pointer to buffer");
137 if(m_bytesWrote > MAX_BUFFER){
138 LogError("Too big buffer requested!");
139 ThrowMsg(Exception::SocketStreamException, "Too big buffer requested!");
151 FD_SET(m_socketFd, &allset);
155 int write_res, bytes_to_write = num;
156 unsigned int current_offset = 0;
159 char errbuf[512] = {0,};
161 while(current_offset != num){
162 timeout.tv_sec = WRITE_TIMEOUT_SEC;
163 timeout.tv_nsec = WRITE_TIMEOUT_NSEC;
166 if(-1 == (returned_value = pselect(max_fd, NULL, &wset, NULL, &timeout, NULL))){
167 if(errno == EINTR) continue;
168 throwWithErrnoMessage("pselect()");
171 if(FD_ISSET(m_socketFd, &wset)){
172 if(-1 == (write_res = write(m_socketFd, reinterpret_cast<const char *>(bytes) + current_offset, bytes_to_write))){
173 if(errno == ECONNRESET || errno == EPIPE){
175 errstr = strerror_r(errno, errbuf, sizeof(errbuf));
177 strerror_r(errno, errbuf, sizeof(errbuf));
180 ThrowMsg(Exception::SocketStreamException,
181 "Connection closed : " << errstr << ". Couldn't write whole data");
183 }else if(errno != EAGAIN && errno != EWOULDBLOCK){
184 throwWithErrnoMessage("write()");
187 current_offset += write_res;
188 bytes_to_write -= write_res;