source: svn/newcon3bcm2_21bu/dta/src/nexus/mini_httpd/mini_httpd.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 8.2 KB
Line 
1
2#include "mini_httpd.h"
3#include "mini_httpd_defs.h"
4#include "bos.h"
5#include "bos_task_priorities.h"
6
7#define MH_TASK_STACK_WORDS 512
8
9typedef struct mh_server_t
10{
11    mh_post_cb_t post_cb;
12        struct sockaddr_in cli_addr; 
13        struct sockaddr_in serv_addr;
14        int port;
15        int listenfd;
16        int socketfd;
17        unsigned int task_stack[MH_TASK_STACK_WORDS];
18        b_task_t task_h;       
19        char buffer[MH_BUFSIZE+1];
20        char path[MH_MAX_PATH_SIZE+1];
21        char fullpath[MH_MAX_FULLPATH_SIZE+1];
22    bool done;
23}mh_server_t;
24
25char MH_ERROR_PAGE[] = "<html><head><title>\nServer Error</title></head>\n<body bgcolor=red text=black>\nERROR:  %s %s\n</body></html>\n";
26
27typedef struct file_extensions_t
28{
29        char *ext;
30        char *filetype;
31} file_extensions_t;
32
33file_extensions_t mime_type_map[] = 
34{
35        {"gif", "image/gif" }, 
36        {"jpg", "image/jpeg"}, 
37        {"jpeg","image/jpeg"},
38        {"png", "image/png" }, 
39        {"zip", "image/zip" }, 
40        {"gz",  "image/gz"  }, 
41        {"tar", "image/tar" }, 
42        {"htm", "text/html" }, 
43        {"html","text/html" }, 
44        {0,0} 
45};
46
47
48static int mh_startup(mh_server_t *p_server)
49{
50#ifdef WIN32
51        WSADATA wsaData;
52    int iResult;
53
54        iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
55    if (iResult != 0) {
56        printf("WSAStartup failed with error: %d\n", iResult);
57        return 1;
58    }
59#endif
60        return 0;
61}
62static void mh_shutdown(mh_server_t *p_server)
63{
64#ifdef WIN32
65        WSACleanup();
66#endif
67}
68
69static void *mh_realloc(void* ptr,int new_size)
70{
71        void * nptr = mh_malloc(new_size);
72        if (!nptr)
73                return NULL;
74
75        mh_memcpy(nptr,ptr,new_size);
76        mh_free(ptr);
77        return nptr;
78}
79
80static int mh_open(char *fname)
81{
82        FILE *f = fopen(fname,"rb");
83        if (f == NULL)
84                return -1;
85        return (int)f;
86}
87static void mh_close(int fd)
88{
89        fclose((FILE*)fd);
90}
91static int mh_read(int fd, void* buf, int len)
92{
93        return (int)fread(buf,1,len,(FILE*)fd);
94}
95
96static char* mh_get_token (char *str, int *idx) 
97{
98        char *token = (char*)mh_malloc (MH_MAX_TOKEN_SIZE);
99        int i = 0;
100        int tsize = MH_MAX_TOKEN_SIZE;
101        char c = 'a';
102
103        while ( (str[i] != ' ') && (str[i] != 0) && (str[i] != 13)) 
104        {
105                c = str[i];
106                token[i++] = c;
107                if (i >= tsize) 
108                {
109                        tsize += 256;
110                        token = (char*)mh_realloc ((void*)token,tsize);
111                }
112        }
113
114        if (i == 0)
115        {
116                mh_free(token);
117                return NULL;
118
119        }
120
121        token[i] = 0;
122        *idx = i + 1;
123        MH_DBG_LOG(eMH_DBG_WRN,("Token: %s",token));
124
125        return token;
126}
127
128static char* mh_get_mime_type(char * str)
129{
130        char *fstr = NULL;
131        int slen,len,i;
132        /* work out the file type and check we support it */
133        slen = mh_strlen(str);
134
135        for ( i = 0; mime_type_map[i].ext != 0;i++) 
136        {
137                len = mh_strlen(mime_type_map[i].ext);
138                if (!mh_strncmp(&str[slen-len], mime_type_map[i].ext, len)) 
139                {
140                        fstr = mime_type_map[i].filetype;
141                        break;
142                }
143        }
144        return fstr;
145}
146static mh_cmd_t mh_cmd(char *cmd) 
147{
148        if (cmd)
149        {
150                if (mh_strcmp (cmd,"GET") == 0) {
151                        return eMH_CMD_GET;
152                }
153                if (mh_strcmp (cmd,"POST") == 0) {
154                        return eMH_CMD_POST;
155                }
156                if (mh_strcmp (cmd,"HEAD") == 0) {
157                        return eMH_CMD_HEAD;
158                }
159        }
160        return eMH_CMD_NONE;
161}
162
163static void mh_send_error (mh_server_t *p_server, char *str, mh_send_err_t err) 
164{
165        int len;
166        switch (err) 
167        {
168        case eMH_SEND_ERR_NO_FILE:
169                len = mh_sprintf(p_server->buffer,MH_ERROR_PAGE,str,"NO FILE");
170                mh_send(p_server->socketfd,p_server->buffer,len);
171                break;
172        case eMH_SEND_ERR_UNSUPPORTED:
173        default:
174                len = mh_sprintf(p_server->buffer,MH_ERROR_PAGE,str,"UNSUPPORTED");
175                mh_send(p_server->socketfd,p_server->buffer,len);
176                break;
177        }
178}
179static int mh_send_file(mh_server_t *p_server, char* filepath)
180{
181        int file_fd = -1;
182        int ret;
183        char *mime_str = mh_get_mime_type(filepath);
184
185        if (!mime_str)
186        {
187                MH_DBG_LOG(eMH_DBG_ERR,("File type not supported %s",filepath));
188                return -1;
189        }
190
191        mh_sprintf(p_server->fullpath,"%s%s",p_server->path,filepath);
192
193        if (( file_fd = mh_open(p_server->fullpath)) == -1) /* open the file for reading */
194        {
195                MH_DBG_LOG(eMH_DBG_ERR,("failed to open file %s",p_server->fullpath));
196                return -1;
197        }
198
199        MH_DBG_LOG(eMH_DBG_MSG,("SEND %s",p_server->fullpath));
200
201         mh_sprintf(p_server->buffer,"HTTP/1.0 200 OK\r\nContent-Type: %s\r\n\r\n", mime_str);
202         mh_send(p_server->socketfd,p_server->buffer,mh_strlen(p_server->buffer));
203
204        /* send file in 8KB block - last block may be smaller */
205        while ( (ret = mh_read(file_fd, p_server->buffer, MH_BUFSIZE)) > 0 ) {
206                 mh_send(p_server->socketfd,p_server->buffer,ret);
207        }
208
209        mh_close(file_fd);
210        return 0;
211}
212
213static int mh_handle_request(mh_server_t *p_server)
214{
215        int idx, ret,free_path;
216        char *token = NULL;
217        char *path = NULL;
218
219        free_path = 1;
220        ret = mh_recv(p_server->socketfd,p_server->buffer,MH_BUFSIZE);  /* read Web request in one go */
221        if ((ret == 0) || (ret == -1))  /* read failure stop now */
222        {
223                 MH_DBG_LOG(eMH_DBG_ERR,("failed to read browser request %d",mh_geterror(0)));
224                 goto done;
225        }
226        p_server->buffer[ret]=0;                /* terminate the buffer */
227
228        idx = 0;
229        token = mh_get_token (p_server->buffer, &idx);
230
231        switch (mh_cmd (token)) 
232        {
233                case eMH_CMD_GET:
234                        path = mh_get_token (&p_server->buffer[idx], &idx);
235                        if ((path == NULL) || ((path[0] == '/') && (path[1] == '\0')))
236                        {
237                                path = "/index.html";
238                                free_path = 0;
239                        }
240                        if (mh_send_file(p_server,path) != 0)
241                                mh_send_error(p_server, path, eMH_SEND_ERR_NO_FILE);
242                        break;
243                case eMH_CMD_POST:
244                        path = mh_get_token (&p_server->buffer[idx], &idx);
245                        MH_DBG_LOG(eMH_DBG_ERR,("%s",path));
246            if (p_server->post_cb)
247            {
248                p_server->post_cb(path);
249            }
250
251                        path = "/index.html";
252                        free_path = 0;
253                        if (mh_send_file(p_server,path) != 0)
254                                mh_send_error(p_server, path, eMH_SEND_ERR_NO_FILE);
255                        break;
256                case eMH_CMD_HEAD:
257                default:
258                        MH_DBG_LOG(eMH_DBG_ERR,("%s: not supported",token));
259                        mh_send_error(p_server, token, eMH_SEND_ERR_UNSUPPORTED);
260                        break;
261        }
262
263done:
264        if (token)
265                mh_free(token);
266        if (path && free_path)
267                mh_free(path);
268
269        if (p_server->socketfd != -1)
270                mh_closesocket(p_server->socketfd);
271        p_server->socketfd = -1;
272
273        return 0;
274}
275
276
277
278static void mh_done(mh_server_t *p_server)
279{
280    MH_DBG_LOG(eMH_DBG_ERR,("%s:%d\n",__FUNCTION__,__LINE__));
281        if (p_server->listenfd != -1)
282                mh_closesocket(p_server->listenfd);
283        if (p_server->socketfd != -1)
284                mh_closesocket(p_server->socketfd);
285
286        mh_shutdown(p_server);
287        mh_free(p_server);
288}
289
290
291static void mh_task(void *arg)
292{
293        mh_server_t *p_server = (mh_server_t*)arg;
294        size_t length;
295    MH_DBG_LOG(eMH_DBG_ERR,("%s:%d\n",__FUNCTION__,__LINE__));
296
297    while (!p_server->done)
298    {
299        if ( listen(p_server->listenfd,64) < 0)
300        {
301                MH_DBG_LOG(eMH_DBG_ERR,("listen failed %d",mh_geterror(0)));
302            bos_sleep(100);
303            continue;
304        }
305   
306        while (1) 
307        {
308                length = sizeof(p_server->cli_addr);
309                if ((p_server->socketfd = accept(p_server->listenfd, (struct sockaddr *)&(p_server->cli_addr), (socklen_t*)&length)) < 0)
310                {
311                        MH_DBG_LOG(eMH_DBG_ERR,("accept failed %d",mh_geterror(0)));
312                        break;
313                }
314               
315                mh_handle_request(p_server);
316        }
317    }
318   
319        mh_done(p_server);
320        return;
321}
322int mh_start(mh_post_cb_t func)
323{
324        mh_server_t *p_server;
325        b_task_params task_params;
326
327        p_server = (mh_server_t*)mh_malloc(sizeof(mh_server_t));
328        if (!p_server)
329                return -1;
330
331        mh_memset(p_server,0,sizeof(mh_server_t));
332    p_server->post_cb = func;
333        p_server->listenfd = -1;
334        p_server->socketfd = -1;
335        p_server->port = DEF_SERVER_PORT;
336        mh_strcpy(p_server->path,".");
337
338        if (mh_startup(p_server) != 0)
339        {
340                mh_done(p_server);
341                return -1;
342        }
343
344        /* setup the network socket */
345        if ((p_server->listenfd = socket(AF_INET, SOCK_STREAM,0)) < 0)
346        {
347                MH_DBG_LOG(eMH_DBG_ERR,("socket failed %d",mh_geterror(0)));
348                mh_done(p_server);
349                return -1;
350        }
351        p_server->port = DEF_SERVER_PORT;
352
353        p_server->serv_addr.sin_family = AF_INET;
354        p_server->serv_addr.sin_addr.s_addr = INADDR_ANY;
355        p_server->serv_addr.sin_port = htons(p_server->port);
356        if (bind(p_server->listenfd, (struct sockaddr *)&(p_server->serv_addr),sizeof(p_server->serv_addr)) < 0)
357        {
358                MH_DBG_LOG(eMH_DBG_ERR,("bind failed %d",mh_geterror(0)));
359                mh_done(p_server);
360                return -1;
361        }
362
363    MH_DBG_LOG(eMH_DBG_ERR,("%s:%d\n",__FUNCTION__,__LINE__));
364        task_params.name = "RECORD_TASK";
365        task_params.priority = HTTPD_PRIORITY;
366        task_params.stack_size = MH_TASK_STACK_WORDS;
367        task_params.stack = p_server->task_stack;
368        bos_start_task(&(p_server->task_h), &task_params, mh_task, p_server);
369
370        return 0;
371}
372
373#ifdef WIN32
374int _tmain(int argc, _TCHAR* argv[])
375{
376        return mh_start();
377}
378#endif
Note: See TracBrowser for help on using the repository browser.