OSDN Git Service

change version number
[bbk/bchanl.git] / src / subjectretriever.c
1 /*
2  * subjectretriever.c
3  *
4  * Copyright (c) 2009-2015 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include        <basic.h>
28 #include        <bstdlib.h>
29 #include        <bstdio.h>
30 #include        <bstring.h>
31 #include        <errcode.h>
32 #include        <btron/btron.h>
33 #include        <btron/bsocket.h>
34
35 #include    "subjectretriever.h"
36
37 #include    "subjectcache.h"
38 #include        <http/http_typedef.h>
39 #include        <http/http_connector.h>
40
41 #ifdef BCHANL_CONFIG_DEBUG
42 # define DP(arg) printf arg
43 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
44 #else
45 # define DP(arg) /**/
46 # define DP_ER(msg, err) /**/
47 #endif
48
49 struct sbjtretriever_t_ {
50         http_connector_t *connector;
51         ID endpoint;
52         HTTP_STATUSCODE status;
53         UB *useragent;
54         W useragent_len;
55 };
56
57 EXPORT sbjtretriever_t* sbjtretriever_new(http_connector_t *connector, UB *useragent, W useragent_len)
58 {
59         sbjtretriever_t *retriever;
60
61         retriever = (sbjtretriever_t*)malloc(sizeof(sbjtretriever_t));
62         if (retriever == NULL) {
63                 return NULL;
64         }
65         retriever->connector = connector;
66         retriever->endpoint = -1;
67         retriever->status = 0;
68         retriever->useragent = useragent;
69         retriever->useragent_len = useragent_len;
70
71         return retriever;
72 }
73
74 EXPORT VOID sbjtretriever_delete(sbjtretriever_t *retriever)
75 {
76         if (retriever->endpoint > 0) {
77                 http_connector_deleteendpoint(retriever->connector, retriever->endpoint);
78         }
79         free(retriever);
80 }
81
82 /* from http://www.monazilla.org/index.php?e=197 */
83 #if 0
84 "GET /[ÈÄ̾]/subject.txt HTTP/1.1
85 Accept-Encoding: gzip
86 Host: [¥µ¡¼¥Ð¡¼]
87 Accept: */*
88 Referer: http://[¥µ¡¼¥Ð¡¼]/[ÈÄ̾]/
89 Accept-Language: ja
90 If-Modified-Since: Tue, 23 Dec 2008 14:08:21 GMT
91 If-None-Match: \"3462-1b80-45eb74ece1f40\"
92 User-Agent: Monazilla/1.00 (monaweb/1.00)
93 Connection: close
94 "
95 #endif
96
97 EXPORT W sbjtretriever_sendrequest(sbjtretriever_t *retriever, sbjtcache_t *cache)
98 {
99         W host_len;
100         UB *host;
101         UH port;
102
103         if (retriever->endpoint > 0) {
104                 DP(("sbjtretriever_sendrequest: requesting\n"));
105                 return -1;
106         }
107
108         sbjtcache_gethost(cache, &host, &host_len);
109         sbjtcache_getport(cache, &port);
110
111         retriever->endpoint = http_connector_createendpoint(retriever->connector, host, host_len, port, HTTP_METHOD_GET);
112         if (retriever->endpoint < 0) {
113                 DP_ER("http_connector_createendpoint error", retriever->endpoint);
114                 return -1;
115         }
116
117         return 0;
118 }
119
120 EXPORT Bool sbjtretriever_iswaitingendpoint(sbjtretriever_t *retriever, ID endpoint)
121 {
122         if (retriever->endpoint == endpoint) {
123                 return True;
124         }
125         return False;
126 }
127
128 LOCAL UB header1[] =
129 "Accept: */*\r\n"
130 "Referer: http://";
131 LOCAL UB header2[] =
132 "/\r\n"
133 "Accept-Language: ja\r\n"
134 "User-Agent: ";
135 LOCAL UB header_default_ua[] = "Monazilla/1.00";
136 LOCAL UB header_crlf[] = "\r\n";
137
138 EXPORT W sbjtretriever_recievehttpevent(sbjtretriever_t *retriever, sbjtcache_t *cache, http_connector_event *hevent)
139 {
140         http_connector_t *connector = retriever->connector;
141         W host_len, board_len, path_len;
142         UB *host, *board, *path;
143
144         if (retriever->endpoint <= 0) {
145                 return -1;
146         }
147
148         if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_SEND) {
149                 sbjtcache_getboard(cache, &host, &host_len);
150                 sbjtcache_getboard(cache, &board, &board_len);
151
152                 path_len = 1 + board_len + 12;
153                 path = malloc(sizeof(UB)*(path_len+1));
154                 if (path == NULL) {
155                         return -1;
156                 }
157                 path[0] = '/';
158                 strncpy(path+1, board, board_len);
159                 strncpy(path+1+board_len, "/subject.txt", 12);
160                 path[1+board_len+12] = '\0';
161                 http_connector_sendrequestline(connector, hevent->endpoint, path, path_len);
162                 free(path);
163
164                 http_connector_sendheader(connector, hevent->endpoint, header1, strlen(header1));
165                 http_connector_sendheader(connector, hevent->endpoint, host, host_len);
166                 http_connector_sendheader(connector, hevent->endpoint, "/", 1);
167                 http_connector_sendheader(connector, hevent->endpoint, board, board_len);
168                 http_connector_sendheader(connector, hevent->endpoint, header2, strlen(header2));
169                 if (retriever->useragent != NULL) {
170                         http_connector_sendheader(connector, hevent->endpoint, retriever->useragent, retriever->useragent_len);
171                 } else {
172                         http_connector_sendheader(connector, hevent->endpoint, header_default_ua, strlen(header_default_ua));
173                 }
174                 http_connector_sendheader(connector, hevent->endpoint, header_crlf, strlen(header_crlf));
175                 http_connector_sendheaderend(connector, hevent->endpoint);
176                 http_connector_sendmessagebody(connector, hevent->endpoint, NULL, 0);
177                 http_connector_sendmessagebodyend(connector, hevent->endpoint);
178         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_RECEIVE_STATUSLINE) {
179                 DP(("HTTP_CONNECTOR_EVENTTYPE_RECEIVE_STATUSLINE\n"));
180                 DP(("    status = %d\n", hevent->data.receive_statusline.statuscode));
181                 retriever->status = hevent->data.receive_statusline.statuscode;
182                 if (retriever->status == HTTP_STATUSCODE_200_OK) {
183                         sbjtcache_cleardata(cache);
184                 }
185         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER) {
186 #ifdef BCHANL_CONFIG_DEBUG
187                 {
188                         W i = 0;
189                         for (i = 0; i < hevent->data.receive_header.len; i++) {
190                                 printf("%c", hevent->data.receive_header.bin[i]);
191                         }
192                 }
193 #endif
194         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_RECEIVE_HEADER_END) {
195         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY) {
196                 if (retriever->status == HTTP_STATUSCODE_200_OK) {
197                         sbjtcache_appenddata(cache, hevent->data.receive_messagebody.bin, hevent->data.receive_messagebody.len);
198                 }
199         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_RECEIVE_MESSAGEBODY_END) {
200                 http_connector_deleteendpoint(connector, hevent->endpoint);
201                 retriever->endpoint = -1;
202                 return SBJTRETRIEVER_REQUEST_ALLRELOAD;
203         } else if (hevent->type == HTTP_CONNECTOR_EVENTTYPE_ERROR) {
204                 http_connector_deleteendpoint(connector, hevent->endpoint);
205                 retriever->endpoint = -1;
206                 return SBJTRETRIEVER_REQUEST_ERROR;
207         } else {
208                 /* error */
209                 return -1;
210         }
211
212         return SBJTRETRIEVER_REQUEST_WAITNEXT;
213 }