summaryrefslogtreecommitdiff
path: root/src/socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/socket.cpp')
-rw-r--r--src/socket.cpp232
1 files changed, 231 insertions, 1 deletions
diff --git a/src/socket.cpp b/src/socket.cpp
index c5c592b..e206bb5 100644
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -1,10 +1,240 @@
1#include <string.h>
2#include <stdio.h>
3#include <errno.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <sys/time.h>
9#include <netinet/in.h>
10#include <netdb.h>
11#include <arpa/inet.h>
12#include <errno.h>
13#include <fcntl.h>
1#include "socket.h" 14#include "socket.h"
15#include "exceptions.h"
2 16
3Bu::Socket::Socket() 17#define RBS (1024*2)
18
19Bu::Socket::Socket( int nSocket ) :
20 nSocket( nSocket ),
21 bActive( true )
4{ 22{
5} 23}
6 24
25Bu::Socket::Socket( const Bu::FString &sAddr, int nPort, int nTimeout )
26{
27 struct sockaddr_in xServerName;
28 bActive = false;
29
30 /* Create the socket. */
31 nSocket = socket( PF_INET, SOCK_STREAM, 0 );
32
33 if( nSocket < 0 )
34 {
35 throw ExceptionBase("Couldn't create socket.\n");
36 }
37
38 // These lines set the socket to non-blocking, a good thing?
39 int flags;
40 flags = fcntl(nSocket, F_GETFL, 0);
41 flags |= O_NONBLOCK;
42 if (fcntl(nSocket, F_SETFL, flags) < 0)
43 {
44 throw ExceptionBase("Couldn't set socket options.\n");
45 }
46
47 /* Connect to the server. */
48 //printf("Resolving hostname (%s)...\n", sAddr );
49 {
50 struct hostent *hostinfo;
51
52 xServerName.sin_family = AF_INET;
53 xServerName.sin_port = htons( nPort );
54 hostinfo = gethostbyname( sAddr.getStr() );
55 if (hostinfo == NULL)
56 {
57 throw ExceptionBase("Couldn't resolve hostname.\n");
58 }
59 xServerName.sin_addr = *(struct in_addr *) hostinfo->h_addr;
60 }
61
62 //printf("Making actual connection...");
63 //fflush( stdout );
64 connect(
65 nSocket,
66 (struct sockaddr *)&xServerName,
67 sizeof(xServerName)
68 );
69 //printf("Connected.\n");
70
71 bActive = true;
72
73 if( nTimeout > 0 )
74 {
75 fd_set rfds, wfds, efds;
76 int retval;
77
78 FD_ZERO(&rfds);
79 FD_SET(nSocket, &rfds);
80 FD_ZERO(&wfds);
81 FD_SET(nSocket, &wfds);
82 FD_ZERO(&efds);
83 FD_SET(nSocket, &efds);
84
85 struct timeval tv;
86 tv.tv_sec = nTimeout;
87 tv.tv_usec = 0;
88
89 retval = select( nSocket+1, &rfds, &wfds, &efds, &tv );
90
91 if( retval == 0 )
92 {
93 close();
94 throw ExceptionBase("Connection timeout.\n");
95 }
96
97 }
98}
99
7Bu::Socket::~Socket() 100Bu::Socket::~Socket()
8{ 101{
9} 102}
10 103
104void Bu::Socket::close()
105{
106 if( bActive )
107 {
108 fsync( nSocket );
109 ::close( nSocket );
110 }
111 bActive = false;
112 //xInputBuf.clearData();
113 //xOutputBuf.clearData();
114 //if( pProtocol != NULL )
115 //{
116 // delete pProtocol;
117 // pProtocol = NULL;
118 //}
119}
120
121void Bu::Socket::read()
122{
123 char buffer[RBS];
124 int nbytes;
125 int nTotalRead=0;
126
127 for(;;)
128 {
129 //memset( buffer, 0, RBS );
130
131 nbytes = ::read( nSocket, buffer, RBS );
132 if( nbytes < 0 && errno != 0 && errno != EAGAIN )
133 {
134 //printf("errno: %d, %s\n", errno, strerror( errno ) );
135 /* Read error. */
136 //perror("readInput");
137 throw ConnectionException(
138 excodeReadError,
139 "Read error: %s",
140 strerror( errno )
141 );
142 }
143 else
144 {
145 if( nbytes <= 0 )
146 break;
147 nTotalRead += nbytes;
148 sReadBuf.append( buffer, nbytes );
149 /* Data read. */
150 if( nbytes < RBS )
151 {
152 break;
153 }
154
155 /* New test, if data is divisible by RBS bytes on some libs the
156 * read could block, this keeps it from happening.
157 */
158 {
159 fd_set rfds;
160 FD_ZERO(&rfds);
161 FD_SET(nSocket, &rfds);
162 struct timeval tv = { 0, 0 };
163 int retval = select( nSocket+1, &rfds, NULL, NULL, &tv );
164 if( retval == -1 )
165 throw ConnectionException(
166 excodeBadReadError,
167 "Bad Read error"
168 );
169 if( !FD_ISSET( nSocket, &rfds ) )
170 break;
171 }
172 }
173 }
174
175 /*
176 if( pProtocol != NULL && nTotalRead > 0 )
177 {
178 pProtocol->onNewData();
179 }*/
180}
181
182size_t Bu::Socket::read( void *pBuf, size_t nBytes )
183{
184 read();
185
186
187
188 return sReadBuf.getSize();
189}
190
191size_t Bu::Socket::write( const void *pBuf, size_t nBytes )
192{
193 int nWrote = TEMP_FAILURE_RETRY( ::write( nSocket, pBuf, nBytes ) );
194 if( nWrote < 0 )
195 {
196 throw ConnectionException( excodeWriteError, strerror(errno) );
197 }
198 return nWrote;
199}
200
201long Bu::Socket::tell()
202{
203 throw UnsupportedException();
204}
205
206void Bu::Socket::seek( long offset )
207{
208 throw UnsupportedException();
209}
210
211void Bu::Socket::setPos( long pos )
212{
213 throw UnsupportedException();
214}
215
216void Bu::Socket::setPosEnd( long pos )
217{
218 throw UnsupportedException();
219}
220
221bool Bu::Socket::isEOS()
222{
223 return !bActive;
224}
225
226bool Bu::Socket::canRead()
227{
228 return true;
229}
230
231bool Bu::Socket::canWrite()
232{
233 return true;
234}
235
236bool Bu::Socket::canSeek()
237{
238 return false;
239}
240