OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / io / inet.c
1 /*
2  * @brief ネットワーク機能処理
3  * @date 2002/01/12
4  * @author mogami
5  */
6
7 #include "io/inet.h"
8 #include "io/files-util.h"
9 #include "util/angband-files.h"
10
11 #ifdef WORLD_SCORE
12
13 #include <stdio.h>
14 #include <stdarg.h>
15 #include <ctype.h>
16
17 #if defined(WINDOWS)
18 #include <winsock.h>
19 #else
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #include <sys/time.h>
25
26 #include <setjmp.h>
27 #include <signal.h>
28 #endif
29
30 #include <stdlib.h>
31
32 static concptr errstr;
33 static char     *proxy;
34 static int      proxy_port;
35
36 bool browsing_movie;
37
38 /* プロキシサーバのアドレスををファイルから読んで設定する */
39 void set_proxy(char *default_url, int default_port)
40 {
41         char buf[1024];
42         size_t len;
43         FILE *fp;
44         char *s;
45
46         path_build(buf, sizeof(buf), ANGBAND_DIR_PREF, "proxy.prf");
47
48         /* ファイルから設定を読む。 */
49         fp = angband_fopen(buf, "r");
50
51         if (!fp)
52         {
53                 /* ファイルが存在しない場合はデフォルトを設定 */
54                 proxy = default_url;
55                 proxy_port = default_port;
56                 return;
57         }
58
59         while (angband_fgets(fp, buf, sizeof(buf)) == 0)
60         {
61                 if (buf[0] != '#' && buf[0] != '\0') break;
62         }
63
64         angband_fclose(fp);
65
66         /* ポインタを用意。 */
67         s = buf;
68
69         /* "http://" から始まっている場合はその部分をカットする。 */
70 #if defined(WINDOWS)
71         if (!strnicmp(s, "http://", 7))
72         {
73                 s += 7;
74         }
75 #else
76         if (!strncasecmp(s, "http://", 7))
77         {
78                 s += 7;
79         }
80 #endif
81
82         /* 文字列の長さを調べ、必要なメモリを確保 */
83         len = strlen(s);
84         proxy = malloc(len + 1);
85
86         /* ポート番号があるかどうかを調べ、あればproxy_portに設定。 */
87         --len;
88         while (len > 0 && isdigit((unsigned char)s[len]))
89                 --len;
90         if (len > 0 && s[len] == ':' && s[len + 1] != '\0')
91         {
92                 s[len] = '\0';
93                 strcpy(proxy, s);
94                 proxy_port = atoi(s + (len + 1));
95         }
96         else
97         {
98                 strcpy(proxy, s);
99                 proxy_port = default_port;
100         }
101
102         /* プロキシのアドレスをproxyにコピー */
103         strcpy(proxy, s);
104
105         if (proxy_port == 0)
106                 proxy_port = 80;
107 }
108
109 /* ソケットにバッファの内容を書き込む */
110 int soc_write(int sd, char *buf, size_t sz)
111 {
112         int nleft, nwritten;
113
114         nleft = sz;
115
116         while (nleft > 0) {
117                 nwritten = send(sd, buf, nleft, 0);
118                 if (nwritten <= 0)
119                         return (nwritten);
120                 nleft -= nwritten;
121                 buf += nwritten;
122         }
123
124         return sz;
125 }
126
127 int soc_read(int sd, char *buf, size_t sz)
128 {
129         int nleft, nread = 0;
130
131         nleft = sz;
132
133         while (nleft > 0) {
134                 int n;
135                 n = recv(sd, buf + nread, nleft, 0);
136                 if (n <= 0)
137                         return (nread);
138                 nleft -= n;
139                 nread += n;
140         }
141
142         return nread;
143 }
144
145 #if !defined(WINDOWS)
146 static sigjmp_buf       env;
147 static void(*sig_int_saved)(int);
148 static void(*sig_alm_saved)(int);
149 #endif
150
151 static void restore_signal(void)
152 {
153 #if !defined(WINDOWS)
154         struct itimerval        val0;
155
156         /* itimerリセット用 */
157         val0.it_interval.tv_sec = 0;
158         val0.it_interval.tv_usec = 0;
159         val0.it_value.tv_sec = 0;
160         val0.it_value.tv_usec = 0;
161
162         /* アラーム解除 */
163         setitimer(ITIMER_REAL, &val0, NULL);
164         signal(SIGALRM, sig_alm_saved);
165         signal(SIGINT, sig_int_saved);
166 #endif
167 }
168
169
170 #if !defined(WINDOWS)
171 static void interrupt_report(int sig)
172 {
173         restore_signal();
174         siglongjmp(env, sig);
175 }
176 #endif
177
178
179 /* サーバにコネクトする関数。 */
180 int connect_server(int timeout, concptr host, int port)
181 {
182         int                     sd;
183         struct sockaddr_in      to;
184         struct hostent  *hp;
185
186 #ifndef WINDOWS
187         struct itimerval        val;
188         int                     ret;
189
190         /* itimer設定用 */
191         val.it_interval.tv_sec = 0;
192         val.it_interval.tv_usec = 0;
193         val.it_value.tv_sec = timeout;
194         val.it_value.tv_usec = 0;
195
196         /* タイムアウト、もしくは中断した時の処理。 */
197         if ((ret = sigsetjmp(env, 1)) != 0)
198         {
199 #ifdef JP
200                 if (ret == SIGALRM)
201                         errstr = "エラー: タイムアウト";
202                 else
203                         errstr = "エラー: インタラプト";
204 #else
205                 if (ret == SIGALRM)
206                         errstr = "Error : time out";
207                 else
208                         errstr = "Error : interupted";
209 #endif
210                 return -1;
211         }
212         sig_int_saved = signal(SIGINT, interrupt_report);
213         sig_alm_saved = signal(SIGALRM, interrupt_report);
214
215         /* タイムアウトの時間を設定 */
216         setitimer(ITIMER_REAL, &val, NULL);
217 #else
218         /* Unused in Windows */
219         (void)timeout;
220 #endif
221
222         /* プロキシが設定されていればプロキシに繋ぐ */
223         if (proxy && proxy[0])
224         {
225                 if ((hp = gethostbyname(proxy)) == NULL)
226                 {
227 #ifdef JP
228                         errstr = "エラー: プロキシのアドレスが不正です";
229 #else
230                         errstr = "Error : wrong proxy addres";
231 #endif
232
233                         restore_signal();
234
235                         return -1;
236                 }
237         }
238         else if ((hp = gethostbyname(host)) == NULL)
239         {
240 #ifdef JP
241                 errstr = "エラー: サーバのアドレスが不正です";
242 #else
243                 errstr = "Error : wrong server adress";
244 #endif
245
246                 restore_signal();
247
248                 return -1;
249         }
250
251         memset(&to, 0, sizeof(to));
252         memcpy(&to.sin_addr, hp->h_addr_list[0], hp->h_length);
253
254         to.sin_family = AF_INET;
255
256         if (proxy && proxy[0] && proxy_port)
257                 to.sin_port = htons((unsigned short int)proxy_port);
258         else
259                 to.sin_port = htons((unsigned short int)port);
260
261 #ifndef WINDOWS
262         if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
263 #else
264         if ((sd = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
265 #endif
266         {
267 #ifdef JP
268                 errstr = "エラー: ソケットを生成できません";
269 #else
270                 errstr = "Error : cannot create socket.";
271 #endif
272                 restore_signal();
273                 return -1;
274         }
275
276         if (connect(sd, (struct sockaddr *)&to, sizeof(to)) < 0)
277         {
278 #ifdef JP
279                 errstr = "エラー: サーバに接続できません";
280 #else
281                 errstr = "Error : failed to connect server";
282 #endif
283                 restore_signal();
284 #ifndef WINDOWS
285                 close(sd);
286 #else
287                 closesocket(sd);
288 #endif
289                 return -1;
290         }
291
292         restore_signal();
293
294         return sd;
295 }
296
297
298 int disconnect_server(int sd)
299 {
300 #if defined(WINDOWS)
301         return closesocket(sd);
302 #else
303         return close(sd);
304 #endif
305 }
306
307 concptr soc_err()
308 {
309         return errstr;
310 }
311
312 #endif /* WORLD_SCORE */