|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 #include "stdafx.h" |
|
22 #include "statsocket_block.h" |
|
23 |
|
24 //////////////////////////////////////////////////////////////////////////////////////// |
|
25 // Constructor |
|
26 CSTATSocket::CSTATSocket() : pBuffer(NULL), iBufferLength(0) |
|
27 { |
|
28 } |
|
29 |
|
30 |
|
31 //////////////////////////////////////////////////////////////////////////////////////// |
|
32 // Destructor |
|
33 CSTATSocket::~CSTATSocket() |
|
34 { |
|
35 Disconnect(); |
|
36 Release(); |
|
37 } |
|
38 |
|
39 |
|
40 //////////////////////////////////////////////////////////////////////////////////////// |
|
41 // Initialise |
|
42 int CSTATSocket::Initialise(void) |
|
43 { |
|
44 WORD version; |
|
45 WSADATA wsaData; |
|
46 |
|
47 // start the windows socket server |
|
48 version = MAKEWORD( 2, 2 ); |
|
49 if (WSAStartup( version, &wsaData )) |
|
50 return E_SOCKETSTARTUP; |
|
51 |
|
52 return ITS_OK; |
|
53 } |
|
54 |
|
55 |
|
56 //////////////////////////////////////////////////////////////////////////////////////// |
|
57 // Connect |
|
58 int CSTATSocket::Connect(const char *pAddress) |
|
59 { |
|
60 int iPort = ST_DEFAULTDEVICEPORT; |
|
61 |
|
62 // parameter will either be MACHINE_NAME:PORT_NUMBER if connecting |
|
63 // or just PORT_NUMBER if listening |
|
64 char *p = strrchr(pAddress, ':'); |
|
65 char *q = p; |
|
66 if (p) |
|
67 { |
|
68 (*p) = (char)0; |
|
69 |
|
70 p++; |
|
71 if (p && *p) |
|
72 iPort = atoi(p); |
|
73 |
|
74 // local address |
|
75 struct hostent *hp; |
|
76 memset(&sin,0,sizeof(sin)); |
|
77 sin.sin_family = AF_INET; |
|
78 sin.sin_port = htons((unsigned short)iPort); |
|
79 hp = gethostbyname(pAddress); |
|
80 |
|
81 // put this back to restore original string |
|
82 *q = ':'; |
|
83 |
|
84 if (hp) |
|
85 { |
|
86 |
|
87 // create a client socket |
|
88 sock = socket( AF_INET, SOCK_STREAM, 0 ) ; |
|
89 if( sock == INVALID_SOCKET ) |
|
90 return E_SOCKETCREATE; |
|
91 |
|
92 memcpy(&(sin.sin_addr),hp->h_addr,hp->h_length); |
|
93 |
|
94 // connect to server |
|
95 if (connect(sock, (struct sockaddr*)&sin, sizeof(sin)) != 0) |
|
96 return E_SOCKETCONNECT; |
|
97 |
|
98 // Set the socket I/O mode |
|
99 // FIONBIO enables or disables the blocking mode for the |
|
100 // socket: |
|
101 // 0 => blocking is enabled; |
|
102 // !=0 => non-blocking mode is enabled. |
|
103 u_long mode = 1; |
|
104 ioctlsocket(sock, FIONBIO, &mode); |
|
105 |
|
106 } |
|
107 else |
|
108 return E_SOCKETHOSTNAME; |
|
109 } |
|
110 else |
|
111 { |
|
112 // create a listener socket |
|
113 listener = socket(AF_INET, SOCK_STREAM, 0); |
|
114 if( listener == INVALID_SOCKET ) |
|
115 return E_SOCKETCREATE; |
|
116 |
|
117 iPort = atoi(pAddress); |
|
118 if (!iPort) |
|
119 iPort = ST_DEFAULTDEVICEPORT; |
|
120 |
|
121 sin.sin_family = AF_INET; |
|
122 sin.sin_port = htons((unsigned short)iPort); |
|
123 sin.sin_addr.s_addr = INADDR_ANY; |
|
124 |
|
125 if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) != 0) |
|
126 return E_SOCKETBIND; |
|
127 |
|
128 if (listen(listener, 1) != 0) |
|
129 return E_SOCKETLISTEN; |
|
130 |
|
131 int sin_size = sizeof(remote_sin); |
|
132 memset((void *)&remote_sin, 0, sizeof(remote_sin)); |
|
133 sock = accept(listener, (struct sockaddr*)&remote_sin, &sin_size); |
|
134 |
|
135 // shut down the listener now we have our connection |
|
136 shutdown(listener, SD_SEND); |
|
137 shutdown(listener, SD_RECEIVE); |
|
138 closesocket(listener); |
|
139 |
|
140 if (sock == INVALID_SOCKET) |
|
141 return E_OUTOFMEM; |
|
142 } |
|
143 |
|
144 return ITS_OK; |
|
145 } |
|
146 |
|
147 |
|
148 //////////////////////////////////////////////////////////////////////////////////////// |
|
149 // Send |
|
150 int CSTATSocket::Send(const char cIdentifier, const char *pData, const unsigned long ulLength) |
|
151 { |
|
152 int ret = ITS_OK; |
|
153 unsigned long ID = htonl(cIdentifier); |
|
154 unsigned long Length = htonl(ulLength); |
|
155 |
|
156 // send the identifier |
|
157 ret = send( sock, (char*)&ID, sizeof(unsigned long), 0 ); |
|
158 if (ret != sizeof(unsigned long)) |
|
159 return E_SOCKETSEND; |
|
160 |
|
161 // send the length |
|
162 ret = send( sock, (char*)&Length, sizeof(unsigned long), 0 ); |
|
163 if (ret != sizeof(unsigned long)) |
|
164 return E_SOCKETSEND; |
|
165 |
|
166 if (pData && ulLength && (ulLength <= GetMaxPacketSize( )) ) |
|
167 { |
|
168 char *pSendData = new char[ulLength + 1]; |
|
169 if (pSendData) |
|
170 { |
|
171 memset(pSendData, 0, ulLength + 1); |
|
172 memcpy(pSendData, pData, ulLength); |
|
173 } |
|
174 else |
|
175 return E_OUTOFMEM; |
|
176 |
|
177 // send the length |
|
178 ret = send( sock, pSendData, ulLength, 0 ); |
|
179 |
|
180 if (pSendData) |
|
181 delete [] pSendData; |
|
182 |
|
183 if (ret != (int)ulLength) |
|
184 return E_SOCKETSEND; |
|
185 } |
|
186 |
|
187 return ITS_OK; |
|
188 } |
|
189 |
|
190 |
|
191 //////////////////////////////////////////////////////////////////////////////////////// |
|
192 // Receive |
|
193 int CSTATSocket::Receive(char *cIdentifier, char **ppData, unsigned long *pLength) |
|
194 { |
|
195 int ret = ITS_OK; |
|
196 unsigned long ID = 0; |
|
197 unsigned long Length = 0; |
|
198 |
|
199 TIMEVAL timeout; |
|
200 timeout.tv_sec = SOCKETTIMEOUT; |
|
201 timeout.tv_usec = 0; |
|
202 |
|
203 FD_SET reader; |
|
204 |
|
205 FD_ZERO(&reader); |
|
206 FD_SET(sock, &reader); |
|
207 |
|
208 // receive the identifier |
|
209 |
|
210 if(select(0, &reader, NULL, NULL, &timeout)==0) |
|
211 { |
|
212 return E_SOCKETRECV; |
|
213 } |
|
214 |
|
215 ret = recv( sock, (char*)&ID, sizeof(unsigned long), 0 ); |
|
216 if (ret != sizeof(unsigned long)) |
|
217 return E_SOCKETRECV; |
|
218 |
|
219 |
|
220 if(select(0, &reader, NULL, NULL, &timeout)==0) |
|
221 { |
|
222 return E_SOCKETRECV; |
|
223 } |
|
224 |
|
225 // receive the length |
|
226 ret = recv( sock, (char*)&Length, sizeof(unsigned long), 0 ); |
|
227 if (ret != sizeof(unsigned long)) |
|
228 return E_SOCKETRECV; |
|
229 |
|
230 (*cIdentifier) = (char)ntohl(ID); |
|
231 (*pLength) = ntohl(Length); |
|
232 |
|
233 // if the length is zero then there is no more to do |
|
234 if( *pLength == 0 ) { |
|
235 return ITS_OK; |
|
236 } |
|
237 |
|
238 if( *pLength > GetMaxPacketSize( ) ) { |
|
239 SetError( "Received command ID: %c successfully length %d", (*cIdentifier), *pLength ); |
|
240 return ITS_OK; |
|
241 } |
|
242 |
|
243 if (*pLength) |
|
244 { |
|
245 if( *pLength > iBufferLength ) |
|
246 { |
|
247 if( pBuffer ) { |
|
248 delete [] pBuffer; |
|
249 pBuffer = NULL; |
|
250 iBufferLength = 0; |
|
251 } |
|
252 pBuffer = new char [*pLength + 1]; |
|
253 if( pBuffer == NULL ) { |
|
254 SetError( "Unable to allocate %ld bytes of memory to hold data", *pLength ); |
|
255 return E_OUTOFMEM; |
|
256 } |
|
257 memset(pBuffer, 0, (*pLength) + 1); |
|
258 iBufferLength = *pLength; |
|
259 } |
|
260 |
|
261 char *p = pBuffer; |
|
262 |
|
263 // receive the data |
|
264 int iThisAmount = 0; |
|
265 int iTotalReceived = 0; |
|
266 while (iTotalReceived < (int)(*pLength)) |
|
267 { |
|
268 |
|
269 if(select(0, &reader, NULL, NULL, &timeout)==0) |
|
270 { |
|
271 return E_SOCKETRECV; |
|
272 } |
|
273 |
|
274 iThisAmount = recv( sock, p, (*pLength) - iTotalReceived, 0 ); |
|
275 if (iThisAmount == SOCKET_ERROR) |
|
276 return E_SOCKETRECV; |
|
277 |
|
278 iTotalReceived += iThisAmount; |
|
279 p += iThisAmount; |
|
280 Sleep(100); |
|
281 } |
|
282 |
|
283 (*ppData) = pBuffer; |
|
284 } |
|
285 |
|
286 return ITS_OK; |
|
287 } |
|
288 |
|
289 |
|
290 //////////////////////////////////////////////////////////////////////////////////////// |
|
291 // Disconnect |
|
292 int CSTATSocket::Disconnect(void) |
|
293 { |
|
294 // release previous resources |
|
295 if (pBuffer) |
|
296 { |
|
297 delete [] pBuffer; |
|
298 pBuffer = NULL; |
|
299 iBufferLength = 0; |
|
300 } |
|
301 |
|
302 shutdown(sock, SD_SEND); |
|
303 shutdown(sock, SD_RECEIVE); |
|
304 |
|
305 if (closesocket(sock) == SOCKET_ERROR) |
|
306 return E_SOCKETCLOSE; |
|
307 |
|
308 return ITS_OK; |
|
309 } |
|
310 |
|
311 |
|
312 //////////////////////////////////////////////////////////////////////////////////////// |
|
313 // |
|
314 int CSTATSocket::Release(void) |
|
315 { |
|
316 if (WSACleanup() == SOCKET_ERROR) |
|
317 return E_SOCKETSHUTDOWN; |
|
318 |
|
319 return ITS_OK; |
|
320 } |
|
321 |
|
322 |
|
323 //////////////////////////////////////////////////////////////////////////////////////// |
|
324 // PRIVATE FUNCTIONS |
|
325 //////////////////////////////////////////////////////////////////////////////////////// |