1 /******************************************************************************
2 *
3 * Copyright (C) 2004-2008, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * Author: Alexey Krivonogov ( gentee )
11 *
12 ******************************************************************************/
13
14 define
15 {
16 SD_RECEIVE = 0x00
17 SD_SEND = 0x01
18 SD_BOTH = 0x02
19
20 SOCKF_PROXY = 0x0001 // Соединение через прокси
21 SOCKF_FTP = 0x0002 // FTP соединение
22 }
23
24 /*-----------------------------------------------------------------------------
25 * Id: tsocket T socket
26 *
27 * Summary: Socket structure.
28 *
29 -----------------------------------------------------------------------------*/
30
31 type socket
32 {
33 str host // Host name.
34 ushort port // Port number.
35 uint socket // Open socket identifier.
36 uint flag // Additional flags. #b($SOCKF_PROXY) - The socket is /
37 // opened via a proxy server.
38 }
39
40 /*-----------------------------------------------------------------------------
41 * Id: socket_isproxy F3
42 *
43 * Summary: Connecting via a proxy or not. This method can be used to determine
44 if a socket is connected via a proxy server or not.
45 *
46 * Return: 1 is returned if the socket is connected via a proxy server and 0
47 is returned otherwise.
48 *
49 -----------------------------------------------------------------------------*/
50
51 method uint socket.isproxy()
52 {
53 return this.flag & $SOCKF_PROXY
54 }
55
56 /*-----------------------------------------------------------------------------
57 * Id: socket_close F3
58 *
59 * Summary: Closes a socket.
60 *
61 * Return: #lng/retf#
62 *
63 -----------------------------------------------------------------------------*/
64
65 method uint socket.close()
66 {
67 ineterror = shutdown( this.socket, $SD_BOTH )
68 if !ineterror : ineterror = closesocket( this.socket )
69 return !ineterror
70 }
71
72 /*-----------------------------------------------------------------------------
73 * Id: socket_connect F3
74 *
75 * Summary: Opens a socket. The method creates a socket and establishes a
76 connection to the #b(host) and #b(port) specified in the host and
77 port fields of the #a(tsocket) structure.
78 *
79 * Return: #lng/retf#
80 *
81 -----------------------------------------------------------------------------*/
82
83 method uint socket.connect()
84 {
85 sockaddr_in saddr
86 uint he ret
87
88 // Получение хоста по имени
89 saddr.sin_addr = inet_addr( this.host.ptr() )
90 if saddr.sin_addr == 0xFFFFFFFF
91 {
92 he = gethostbyname( this.host.ptr() )
93 if !he : return inet_seterror()
94 saddr.sin_addr = ( he->hostent.h_addr_list->uint)->uint
95 }
96 // Открытие сокета
97 this.socket = createsocket( $AF_INET, $SOCK_STREAM, $IPPROTO_TCP )
98 if this.socket == $INVALID_SOCKET : return inet_seterror()
99
100 saddr.sin_family = $AF_INET
101 saddr.sin_port = htons( this.port )
102
103 // Соединение
104 ret = connect( this.socket, &saddr, sizeof( sockaddr ))
105 if ret == $SOCKET_ERROR
106 {
107 // Закрытие сокета в случае ошибки
108 this.close( )
109 return inet_seterror()
110 }
111 return 1
112 }
113
114 /*-----------------------------------------------------------------------------
115 * Id: socket_recv F2
116 *
117 * Summary: The method gets a packet from the connected server.
118 *
119 * Params: data - The buffer for writing data. The received packet will be /
120 added to the data already existing in the buffer.
121 *
122 * Return: #lng/retf#
123 *
124 -----------------------------------------------------------------------------*/
125
126 method uint socket.recv( buf data )
127 {
128 uint ret
129
130 if data.use + 0x7FFF > data.size
131 {
132 data.expand( data.size + 0x7FFF )
133 }
134 ret = recv( this.socket, data.ptr() + data.use, 0x7FFF, 0 )
135 if ret == $SOCKET_ERROR
136 {
137 return inet_seterror()
138 }
139 data.use += ret
140 return 1
141 }
142
143 /*-----------------------------------------------------------------------------
144 * Id: socket_send F2
145 *
146 * Summary: The method sends a request to the connected server.
147 *
148 * Params: data - Request string.
149 *
150 * Return: #lng/retf#
151 *
152 -----------------------------------------------------------------------------*/
153
154 method uint socket.send( str data )
155 {
156 if send( this.socket, data.ptr(), *data, 0 ) == $SOCKET_ERROR
157 {
158 return inet_seterror()
159 }
160 return 1
161 }
162
163 /*-----------------------------------------------------------------------------
164 ** Id: socket_send_1 FA
165 *
166 * Summary: The method sends a request data to the connected server.
167 *
168 * Params: data - Request buffer.
169 *
170 * Return: #lng/retf#
171 *
172 -----------------------------------------------------------------------------*/
173
174 method uint socket.send( buf data )
175 {
176 uint off last = *data
177 uint sent
178
179 while last
180 {
181 sent = send( this.socket, data.ptr() + off, last, 0 )
182 if sent == $SOCKET_ERROR
183 {
184 return inet_seterror()
185 }
186 last -= sent
187 off += sent
188 }
189 return 1
190 }