HyperDbg Debugger
Loading...
Searching...
No Matches
communication.h File Reference

Go to the source code of this file.

Macros

#define COM1_PORT   0x03F8
 
#define COM2_PORT   0x02F8
 
#define COM3_PORT   0x03E8
 
#define COM4_PORT   0x02E8
 

Functions

int CommunicationServerCreateServerAndWaitForClient (PCSTR Port, SOCKET *ClientSocketArg, SOCKET *ListenSocketArg)
 Create server and wait for a client to connect.
 
int CommunicationServerReceiveMessage (SOCKET ClientSocket, char *recvbuf, int recvbuflen)
 listen and receive message as the server
 
int CommunicationServerSendMessage (SOCKET ClientSocket, const char *sendbuf, int length)
 send message as the server
 
int CommunicationServerShutdownAndCleanupConnection (SOCKET ClientSocket, SOCKET ListenSocket)
 Shutdown and cleanup connection as server.
 
int CommunicationClientConnectToServer (PCSTR Ip, PCSTR Port, SOCKET *ConnectSocketArg)
 communication for client, connecting to the server
 
int CommunicationClientSendMessage (SOCKET ConnectSocket, const char *sendbuf, int buflen)
 Send message a client.
 
int CommunicationClientShutdownConnection (SOCKET ConnectSocket)
 shutdown the connection as a client
 
int CommunicationClientReceiveMessage (SOCKET ConnectSocket, CHAR *RecvBuf, UINT32 MaxBuffLen, PUINT32 BuffLenRecvd)
 Receive message as a client.
 
int CommunicationClientCleanup (SOCKET ConnectSocket)
 cleanup the connection as client
 
VOID RemoteConnectionListen (PCSTR Port)
 Listen of a port and wait for a client connection.
 
VOID RemoteConnectionConnect (PCSTR Ip, PCSTR Port)
 Connect to a remote debuggee (guest) as a client (host)
 
int RemoteConnectionSendCommand (const char *sendbuf, int len)
 send the command as a client (debugger, host) to the server (debuggee, guest)
 
int RemoteConnectionSendResultsToHost (const char *sendbuf, int len)
 Send the results of executing a command from deubggee (server, guest) to the debugger (client, host)
 
int RemoteConnectionCloseTheConnectionWithDebuggee ()
 Close the connect from client side to the debuggee.
 

Macro Definition Documentation

◆ COM1_PORT

#define COM1_PORT   0x03F8

◆ COM2_PORT

#define COM2_PORT   0x02F8

◆ COM3_PORT

#define COM3_PORT   0x03E8

◆ COM4_PORT

#define COM4_PORT   0x02E8

Function Documentation

◆ CommunicationClientCleanup()

int CommunicationClientCleanup ( SOCKET ConnectSocket)

cleanup the connection as client

Parameters
ConnectSocket
Returns
int
217{
218 //
219 // cleanup
220 //
221 closesocket(ConnectSocket);
222 WSACleanup();
223
224 return 0;
225}

◆ CommunicationClientConnectToServer()

int CommunicationClientConnectToServer ( PCSTR Ip,
PCSTR Port,
SOCKET * ConnectSocketArg )

communication for client, connecting to the server

Parameters
Ip
Port
ConnectSocketArg
Returns
int
24{
25 WSADATA wsaData;
26 SOCKET ConnectSocket = INVALID_SOCKET;
27 struct addrinfo *result = NULL, *ptr = NULL, hints;
28 int iResult;
29
30 //
31 // Initialize Winsock
32 //
33 iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
34 if (iResult != 0)
35 {
36 ShowMessages("err, WSAStartup failed (%x)\n", iResult);
37 return 1;
38 }
39
40 ZeroMemory(&hints, sizeof(hints));
41 hints.ai_family = AF_UNSPEC;
42 hints.ai_socktype = SOCK_STREAM;
43 hints.ai_protocol = IPPROTO_TCP;
44
45 //
46 // Resolve the server address and port
47 //
48 iResult = getaddrinfo(Ip, Port, &hints, &result);
49 if (iResult != 0)
50 {
51 ShowMessages("getaddrinfo failed (%x)\n", iResult);
52 WSACleanup();
53 return 1;
54 }
55
56 //
57 // Attempt to connect to an address until one succeeds
58 //
59 for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
60 {
61 //
62 // Create a SOCKET for connecting to server
63 //
64 ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
65 if (ConnectSocket == INVALID_SOCKET)
66 {
67 ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
68 WSACleanup();
69 return 1;
70 }
71
72 //
73 // Connect to server.
74 //
75 iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
76 if (iResult == SOCKET_ERROR)
77 {
78 closesocket(ConnectSocket);
79 ConnectSocket = INVALID_SOCKET;
80 continue;
81 }
82 break;
83 }
84
85 freeaddrinfo(result);
86
87 if (ConnectSocket == INVALID_SOCKET)
88 {
89 ShowMessages("unable to connect to the server\n");
90 WSACleanup();
91 return 1;
92 }
93
94 //
95 // Store the arguments
96 //
97 *ConnectSocketArg = ConnectSocket;
98
99 return 0;
100}
VOID ShowMessages(const char *Fmt,...)
Show messages.
Definition libhyperdbg.cpp:96
result
Definition modelsim.py:117
NULL()
Definition test-case-generator.py:530

◆ CommunicationClientReceiveMessage()

int CommunicationClientReceiveMessage ( SOCKET ConnectSocket,
CHAR * RecvBuf,
UINT32 MaxBuffLen,
PUINT32 BuffLenRecvd )

Receive message as a client.

Parameters
ConnectSocket
RecvBuf
MaxBuffLen
BuffLenRecvd
Returns
int
174{
175 int Result;
176
177 //
178 // Receive until the peer closes the connection
179 //
180 Result = recv(ConnectSocket, RecvBuf, MaxBuffLen, 0);
181 if (Result > 0)
182 {
183 //
184 // Set recvd buff len
185 //
186 *BuffLenRecvd = Result;
187
188 /*
189 ShowMessages("bytes received: %d\n", iResult);
190 */
191 }
192 else if (Result == 0)
193 {
194 //
195 // Last packet
196 //
197 }
198 else
199 {
200 ShowMessages("\nrecv failed with error: %d\n", WSAGetLastError());
201 ShowMessages("the remote system closes the connection.\n\n");
202
203 return 1;
204 }
205
206 return 0;
207}

◆ CommunicationClientSendMessage()

int CommunicationClientSendMessage ( SOCKET ConnectSocket,
const char * sendbuf,
int buflen )

Send message a client.

Parameters
ConnectSocket
sendbuf
buflen
Returns
int
112{
113 int iResult;
114
115 //
116 // Send an initial buffer
117 //
118 iResult = send(ConnectSocket, sendbuf, buflen, 0);
119 if (iResult == SOCKET_ERROR)
120 {
121 ShowMessages("err, send failed (%x)\n", WSAGetLastError());
122 closesocket(ConnectSocket);
123 WSACleanup();
124 return 1;
125 }
126
127 return 0;
128}

◆ CommunicationClientShutdownConnection()

int CommunicationClientShutdownConnection ( SOCKET ConnectSocket)

shutdown the connection as a client

Parameters
ConnectSocket
Returns
int
138{
139 int iResult;
140
141 //
142 // shutdown the connection since no more data will be sent
143 //
144 iResult = shutdown(ConnectSocket, SD_SEND);
145 if (iResult == SOCKET_ERROR)
146 {
147 //
148 // We comment this line because the connection might be removed;
149 // thus, we don't need to show error
150 //
151
152 /*
153 ShowMessages("err, shutdown failed (%x)\n", WSAGetLastError());
154 */
155
156 closesocket(ConnectSocket);
157 WSACleanup();
158 return 1;
159 }
160 return 0;
161}

◆ CommunicationServerCreateServerAndWaitForClient()

int CommunicationServerCreateServerAndWaitForClient ( PCSTR Port,
SOCKET * ClientSocketArg,
SOCKET * ListenSocketArg )

Create server and wait for a client to connect.

this function only accepts one client not multiple clients

Parameters
Port
ClientSocketArg
ListenSocketArg
Returns
int
34{
35 WSADATA wsaData;
36 int iResult;
37
38 SOCKET ListenSocket = INVALID_SOCKET;
39 SOCKET ClientSocket = INVALID_SOCKET;
40
41 struct addrinfo * result = NULL;
42 struct addrinfo hints;
43
44 //
45 // Initialize Winsock
46 //
47 iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
48 if (iResult != 0)
49 {
50 ShowMessages("err, WSAStartup failed (%x)\n", iResult);
51 return 1;
52 }
53
54 ZeroMemory(&hints, sizeof(hints));
55 hints.ai_family = AF_INET;
56 hints.ai_socktype = SOCK_STREAM;
57 hints.ai_protocol = IPPROTO_TCP;
58 hints.ai_flags = AI_PASSIVE;
59
60 //
61 // Resolve the server address and port
62 //
63 iResult = getaddrinfo(NULL, Port, &hints, &result);
64 if (iResult != 0)
65 {
66 ShowMessages("err, getaddrinfo failed (%x)\n", iResult);
67 WSACleanup();
68 return 1;
69 }
70
71 //
72 // Create a SOCKET for connecting to server
73 //
74 ListenSocket =
75 socket(result->ai_family, result->ai_socktype, result->ai_protocol);
76 if (ListenSocket == INVALID_SOCKET)
77 {
78 ShowMessages("socket failed with error: %ld\n", WSAGetLastError());
79 freeaddrinfo(result);
80 WSACleanup();
81 return 1;
82 }
83
84 //
85 // Setup the TCP listening socket
86 //
87 iResult = ::bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
88 if (iResult == SOCKET_ERROR)
89 {
90 ShowMessages("err, bind failed (%x)\n", WSAGetLastError());
91 freeaddrinfo(result);
92 closesocket(ListenSocket);
93 WSACleanup();
94 return 1;
95 }
96
97 freeaddrinfo(result);
98
99 iResult = listen(ListenSocket, SOMAXCONN);
100 if (iResult == SOCKET_ERROR)
101 {
102 ShowMessages("err, listen failed (%x)\n", WSAGetLastError());
103 closesocket(ListenSocket);
104 WSACleanup();
105 return 1;
106 }
107
108 //
109 // Accept a client socket
110 //
111 sockaddr_in name = {0};
112 int addrlen = sizeof(name);
113
114 ClientSocket = accept(ListenSocket, (struct sockaddr *)&name, &addrlen);
115
116 if (ClientSocket == INVALID_SOCKET)
117 {
118 ShowMessages("err, accept failed (%x)\n", WSAGetLastError());
119 closesocket(ListenSocket);
120 WSACleanup();
121 return 1;
122 }
123
124 //
125 // Show that we connected to a client
126 //
127 ShowMessages("connected to : %s:%d\n", inet_ntoa(name.sin_addr), ntohs(name.sin_port));
128
129 //
130 // Set the argument
131 //
132 *ClientSocketArg = ClientSocket;
133 *ListenSocketArg = ListenSocket;
134
135 return 0;
136}

◆ CommunicationServerReceiveMessage()

int CommunicationServerReceiveMessage ( SOCKET ClientSocket,
char * recvbuf,
int recvbuflen )

listen and receive message as the server

Parameters
ClientSocket
recvbuf
recvbuflen
Returns
int
148{
149 int iResult;
150
151 //
152 // Receive until the peer shuts down the connection
153 //
154 iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
155 if (iResult > 0)
156 {
157 //
158 // ShowMessages("bytes received: %d\n", iResult);
159 //
160 }
161 else if (iResult == 0)
162 {
163 //
164 // ShowMessages("connection closing...\n");
165 //
166 }
167 else
168 {
169 ShowMessages("err, recv failed (%x)\n", WSAGetLastError());
170 closesocket(ClientSocket);
171 WSACleanup();
172
173 return 1;
174 }
175
176 return 0;
177}

◆ CommunicationServerSendMessage()

int CommunicationServerSendMessage ( SOCKET ClientSocket,
const char * sendbuf,
int length )

send message as the server

Parameters
ClientSocket
sendbuf
length
Returns
int
189{
190 int iSendResult;
191
192 //
193 // Echo the buffer back to the sender
194 //
195 iSendResult = send(ClientSocket, sendbuf, length, 0);
196 if (iSendResult == SOCKET_ERROR)
197 {
198 /*
199 ShowMessages("err, send failed (%x)\n", WSAGetLastError());
200 closesocket(ClientSocket);
201 WSACleanup();
202 */
203 return 1;
204 }
205 return 0;
206}

◆ CommunicationServerShutdownAndCleanupConnection()

int CommunicationServerShutdownAndCleanupConnection ( SOCKET ClientSocket,
SOCKET ListenSocket )

Shutdown and cleanup connection as server.

Parameters
ClientSocket
ListenSocket
Returns
int
218{
219 int iResult;
220
221 //
222 // No longer need server socket
223 //
224 closesocket(ListenSocket);
225
226 //
227 // shutdown the connection since we're done
228 //
229 iResult = shutdown(ClientSocket, SD_SEND);
230 if (iResult == SOCKET_ERROR)
231 {
232 //
233 // We comment this line because the connection might be removed;
234 // thus, we don't need to show error
235 //
236
237 /*
238 ShowMessages("err, shutdown failed (%x)\n", WSAGetLastError());
239 */
240
241 closesocket(ClientSocket);
242 WSACleanup();
243 return 1;
244 }
245
246 //
247 // cleanup
248 //
249 closesocket(ClientSocket);
250 WSACleanup();
251
252 return 0;
253}

◆ RemoteConnectionCloseTheConnectionWithDebuggee()

int RemoteConnectionCloseTheConnectionWithDebuggee ( )

Close the connect from client side to the debuggee.

Returns
int returning 0 means that there was no error in executing the function and 1 shows there was an error
505{
508
509 return 0;
510}
SOCKET g_ClientConnectSocket
The socket object of host debugger (not debuggee) it is because in HyperDbg, debuggee is server and d...
Definition globals.h:89
int CommunicationClientShutdownConnection(SOCKET ConnectSocket)
shutdown the connection as a client
Definition tcpclient.cpp:137
int CommunicationClientCleanup(SOCKET ConnectSocket)
cleanup the connection as client
Definition tcpclient.cpp:216

◆ RemoteConnectionConnect()

VOID RemoteConnectionConnect ( PCSTR Ip,
PCSTR Port )

Connect to a remote debuggee (guest) as a client (host)

this routine is supposed to be called by .connect command

Parameters
Ip
Port
Returns
VOID
316{
317 DWORD ThreadId;
318 CHAR Recv[3] = {0};
319 UINT32 BuffRecv = 0;
320
321 //
322 // Check if the debugger or debuggee is already active
323 //
325 {
326 return;
327 }
328
329 //
330 // Connect to server
331 //
333 {
334 //
335 // There was an error
336 //
337
338 //
339 // Indicate that debugger is not connected
340 //
342
343 //
344 // Indicate that it's not a remote debuggee
345 //
347
348 //
349 // Shutdown connection
350 //
352
353 //
354 // Cleanup
355 //
357 }
358 else
359 {
360 //
361 // Connection was successful
362 //
363
364 //
365 // Check to see whether the version of debugger and debuggee matches together or not
366 //
368 {
369 //
370 // Failed
371 //
372 ShowMessages("err, failed to communicate with debuggee\n");
373 return;
374 }
375
376 //
377 // Receive the handshake results
378 //
379 if (CommunicationClientReceiveMessage(g_ClientConnectSocket, Recv, sizeof(Recv), &BuffRecv) != 0)
380 {
381 //
382 // Failed, break
383 //
384 ShowMessages("err, failed to receive message from debuggee\n");
385 return;
386 }
387
388 //
389 // Check if the handshake was successful or not
390 //
391 if (strcmp((const char *)"OK", Recv) != 0)
392 {
393 //
394 // Build version not matched
395 //
397 return;
398 }
399
400 //
401 // Indicate that local debugger is not connected
402 //
404
405 //
406 // Indicate that it's a remote debuggee
407 //
409
410 //
411 // Create an event to show signature when the messages finished
412 //
413 if (g_EndOfMessageReceivedEvent == NULL)
414 {
415 g_EndOfMessageReceivedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
416 }
417
418 //
419 // Now, we should create a thread, which always listens to
420 // the remote debuggee for new messages
421 // Listen for upcoming messages
422 //
423 g_RemoteDebuggeeListeningThread = CreateThread(
424 NULL,
425 0,
427 NULL,
428 0,
429 &ThreadId);
430
431 ShowMessages("connected to %s:%s\n", Ip, Port);
432 }
433}
#define TRUE
Definition BasicTypes.h:55
#define FALSE
Definition BasicTypes.h:54
unsigned long DWORD
Definition BasicTypes.h:22
unsigned int UINT32
Definition BasicTypes.h:48
char CHAR
Definition BasicTypes.h:31
const unsigned char BuildSignature[]
Definition Constants.h:130
BOOLEAN IsConnectedToAnyInstanceOfDebuggerOrDebuggee()
Shows whether the debugger is connected to a debugger or debuggee connected to a debugger.
Definition debugger.cpp:668
#define ASSERT_MESSAGE_BUILD_SIGNATURE_DOESNT_MATCH
Definition common.h:27
BOOLEAN g_IsConnectedToRemoteDebuggee
Shows whether the current debugger is the host and connected to a remote debuggee (guest)
Definition globals.h:74
DWORD WINAPI RemoteConnectionThreadListeningToDebuggee(LPVOID lpParam)
A thread that listens for server (debuggee) messages and show it by using ShowMessages wrapper.
Definition remote-connection.cpp:211
HANDLE g_RemoteDebuggeeListeningThread
In debugger (not debuggee), we save the ip of server debuggee in this variable to use it later e....
Definition globals.h:124
HANDLE g_EndOfMessageReceivedEvent
Handle to if the end of the message received (for showing signature)
Definition globals.h:137
BOOLEAN g_IsConnectedToHyperDbgLocally
Shows whether the user is allowed to use 'load' command to load modules locally in VMI (virtual machi...
Definition globals.h:67
int CommunicationClientReceiveMessage(SOCKET ConnectSocket, CHAR *RecvBuf, UINT32 MaxBuffLen, PUINT32 BuffLenRecvd)
Receive message as a client.
Definition tcpclient.cpp:173
int CommunicationClientConnectToServer(PCSTR Ip, PCSTR Port, SOCKET *ConnectSocketArg)
communication for client, connecting to the server
Definition tcpclient.cpp:23
int CommunicationClientSendMessage(SOCKET ConnectSocket, const char *sendbuf, int buflen)
Send message a client.
Definition tcpclient.cpp:111

◆ RemoteConnectionListen()

VOID RemoteConnectionListen ( PCSTR Port)

Listen of a port and wait for a client connection.

this routine is supposed to be called by .listen command

Parameters
Port
Returns
VOID
41{
42 char recvbuf[COMMUNICATION_BUFFER_SIZE] = {0};
43
44 //
45 // Check if the debugger or debuggee is already active
46 //
48 {
49 return;
50 }
51
52 //
53 // Start server and wait for client
54 //
56
57 //
58 // Check the version of debuggee and debugger
59 //
61 {
62 //
63 // Failed
64 //
65 ShowMessages("err, unable to handshake with the remote debugger\n");
66
67 //
68 // Close the connection
69 //
71
72 return;
73 }
74
75 //
76 // Check whether the signature of debuggee and debugger match or not
77 //
78 if (strcmp((const char *)BuildSignature, recvbuf) != 0)
79 {
80 //
81 // Build version not matched
82 //
84
85 //
86 // Send unsuccessful handshake (version match) message
87 //
89 {
90 //
91 // Failed
92 //
93 ShowMessages("err, unable to handshake with the remote debugger\n");
94 }
95
96 //
97 // Close the connection
98 //
100
101 return;
102 }
103 else
104 {
105 //
106 // Send successful handshake (version match) message
107 //
109 {
110 //
111 // Failed
112 //
113 ShowMessages("err, unable to handshake with the remote debugger\n");
114
115 //
116 // Close the connection
117 //
119
120 return;
121 }
122 }
123
124 //
125 // Indicate that it's a remote debugger
126 //
128
129 //
130 // And also, make it a local debugger
131 //
133
134 //
135 // Zero the buffer for next command
136 //
137 RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
138
139 while (true)
140 {
141 //
142 // Receive message (this loop works as a command executer,
143 // we don't send the results to the remote machine by using
144 // this tools
145 //
147 {
148 //
149 // Failed, break
150 //
151 break;
152 }
153
154 //
155 // Execute the command
156 //
157 int CommandExecutionResult = HyperDbgInterpreter(recvbuf);
158
159 //
160 // Send end of buffer
161 //
163
164 //
165 // if the debugger encounters an exit state then the return will be 1
166 //
167 if (CommandExecutionResult == 1)
168 {
169 //
170 // Exit from the debugger
171 //
172 exit(0);
173 }
174
175 //
176 // Zero the buffer for next command
177 //
178 RtlZeroMemory(recvbuf, COMMUNICATION_BUFFER_SIZE);
179 }
180
181 //
182 // Indicate that debugger is not connected
183 //
185
186 //
187 // Indicate that it's note a remote debugger
188 //
190
191 //
192 // Indicate that we're not in remote debugger anymore
193 //
194 ShowMessages("closing the conntection...\n");
195
196 //
197 // Close the connection
198 //
201}
#define COMMUNICATION_BUFFER_SIZE
Packet size for TCP connections.
Definition Constants.h:330
INT HyperDbgInterpreter(CHAR *Command)
Interpret commands.
Definition interpreter.cpp:280
BYTE g_EndOfBufferCheckTcp[TCP_END_OF_BUFFER_CHARS_COUNT]
the buffer that we set at the end of buffers for tcp connection
Definition globals.h:56
SOCKET g_ServerListenSocket
Server in debuggee needs an extra socket.
Definition globals.h:103
SOCKET g_SeverSocket
The socket object of guest debuggee (not debugger) it is because in HyperDbg, debugger is client and ...
Definition globals.h:97
BOOLEAN g_IsConnectedToRemoteDebugger
Shows whether the current system is a guest (debuggee) and a remote debugger is connected to this sys...
Definition globals.h:81
int RemoteConnectionSendResultsToHost(const char *sendbuf, int len)
Send the results of executing a command from deubggee (server, guest) to the debugger (client,...
Definition remote-connection.cpp:481
int CommunicationServerShutdownAndCleanupConnection(SOCKET ClientSocket, SOCKET ListenSocket)
Shutdown and cleanup connection as server.
Definition tcpserver.cpp:216
int CommunicationServerCreateServerAndWaitForClient(PCSTR Port, SOCKET *ClientSocketArg, SOCKET *ListenSocketArg)
Create server and wait for a client to connect.
Definition tcpserver.cpp:31
int CommunicationServerReceiveMessage(SOCKET ClientSocket, char *recvbuf, int recvbuflen)
listen and receive message as the server
Definition tcpserver.cpp:147
int CommunicationServerSendMessage(SOCKET ClientSocket, const char *sendbuf, int length)
send message as the server
Definition tcpserver.cpp:188

◆ RemoteConnectionSendCommand()

int RemoteConnectionSendCommand ( const char * sendbuf,
int len )

send the command as a client (debugger, host) to the server (debuggee, guest)

Parameters
sendbufaddress of message buffer
lenlength of buffer
Returns
int returning 0 means that there was no error in executing the function and 1 shows there was an error
446{
447 //
448 // Send Message
449 //
451 {
452 //
453 // Failed
454 //
455 return 1;
456 }
457
458 //
459 // We wait for the debuggee to send the message
460 //
461 WaitForSingleObject(
463 INFINITE);
464
465 //
466 // Successful
467 //
468 return 0;
469}

◆ RemoteConnectionSendResultsToHost()

int RemoteConnectionSendResultsToHost ( const char * sendbuf,
int len )

Send the results of executing a command from deubggee (server, guest) to the debugger (client, host)

Parameters
sendbufbuffer address
lenlength of buffer
Returns
int returning 0 means that there was no error in executing the function and 1 shows there was an error
482{
483 //
484 // Send the message
485 //
486 if (CommunicationServerSendMessage(g_SeverSocket, sendbuf, len) != 0)
487 {
488 //
489 // Failed
490 //
491 return 1;
492 }
493
494 return 0;
495}